diff --git a/LICENSE b/LICENSE index b14bc8a2dda8..6b3f53421ddf 100644 --- a/LICENSE +++ b/LICENSE @@ -285,6 +285,10 @@ SOURCE/JAVA-CORE This product contains test cases adapted from Test Framework for Apache Drill (https://github.com/apache/drill-test-framework). * sql/src/test/resources/drill/window + This product contains the class copied from https://github.com/FasterXML/jackson-databind + * extensions-core/s3-extensions/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategies.java + + MIT License ================================ diff --git a/extensions-core/s3-extensions/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategies.java b/extensions-core/s3-extensions/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategies.java new file mode 100644 index 000000000000..8d5a255cf6da --- /dev/null +++ b/extensions-core/s3-extensions/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategies.java @@ -0,0 +1,465 @@ +/** + * ******** NOTICE ************ + * https://github.com/FasterXML/jackson-databind/blob/2.16/LICENSE + * Stating the Credits to FasterXML project based on Apache Lic. + * No changes are done in the file other than attaching notice. + * Copyright 2023 Apache Druid + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * **************************** + * Container for standard {@link PropertyNamingStrategy} implementations + * and singleton instances. + *
+ * Added in Jackson 2.12 to resolve issue + * databind#2715. + * + * @since 2.12 + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.fasterxml.jackson.databind; + +import com.fasterxml.jackson.databind.cfg.MapperConfig; +import com.fasterxml.jackson.databind.introspect.AnnotatedField; +import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; +import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; + +import java.io.Serializable; +import java.util.Locale; + + +public abstract class PropertyNamingStrategies implements Serializable +{ + private static final long serialVersionUID = 2L; + + /* + /********************************************************************** + /* Static instances that may be referenced + /********************************************************************** + */ + + /** + * Naming convention used in Java, where words other than first are capitalized + * and no separator is used between words. Since this is the native Java naming convention, + * naming strategy will not do any transformation between names in data (JSON) and + * POJOS. + *
+ * Example external property names would be "numberValue", "namingStrategy", "theDefiniteProof". + */ + public static final PropertyNamingStrategy LOWER_CAMEL_CASE = LowerCamelCaseStrategy.INSTANCE; + + /** + * Naming convention used in languages like Pascal, where all words are capitalized + * and no separator is used between words. + * See {@link UpperCamelCaseStrategy} for details. + *
+ * Example external property names would be "NumberValue", "NamingStrategy", "TheDefiniteProof". + */ + public static final PropertyNamingStrategy UPPER_CAMEL_CASE = UpperCamelCaseStrategy.INSTANCE; + + /** + * Naming convention used in languages like C, where words are in lower-case + * letters, separated by underscores. + * See {@link SnakeCaseStrategy} for details. + *
+ * Example external property names would be "number_value", "naming_strategy", "the_definite_proof". + */ + public static final PropertyNamingStrategy SNAKE_CASE = SnakeCaseStrategy.INSTANCE; + + /** + * Naming convention in which the words are in upper-case letters, separated by underscores. + * See {@link UpperSnakeCaseStrategy} for details. + * + * @since 2.13 + *
+ */ + public static final PropertyNamingStrategy UPPER_SNAKE_CASE = UpperSnakeCaseStrategy.INSTANCE; + + /** + * Naming convention in which all words of the logical name are in lower case, and + * no separator is used between words. + * See {@link LowerCaseStrategy} for details. + *
+ * Example external property names would be "numbervalue", "namingstrategy", "thedefiniteproof". + */ + public static final PropertyNamingStrategy LOWER_CASE = LowerCaseStrategy.INSTANCE; + + /** + * Naming convention used in languages like Lisp, where words are in lower-case + * letters, separated by hyphens. + * See {@link KebabCaseStrategy} for details. + *
+ * Example external property names would be "number-value", "naming-strategy", "the-definite-proof". + */ + public static final PropertyNamingStrategy KEBAB_CASE = KebabCaseStrategy.INSTANCE; + + /** + * Naming convention widely used as configuration properties name, where words are in + * lower-case letters, separated by dots. + * See {@link LowerDotCaseStrategy} for details. + *
+ * Example external property names would be "number.value", "naming.strategy", "the.definite.proof". + */ + public static final PropertyNamingStrategy LOWER_DOT_CASE = LowerDotCaseStrategy.INSTANCE; + + /* + /********************************************************************** + /* Public base class for simple implementations + /********************************************************************** + */ + + /** + * Intermediate base class for simple implementations + */ + public abstract static class NamingBase extends PropertyNamingStrategy + { + private static final long serialVersionUID = 2L; + + @Override + public String nameForField(MapperConfig> config, AnnotatedField field, String defaultName) + { + return translate(defaultName); + } + + @Override + public String nameForGetterMethod(MapperConfig> config, AnnotatedMethod method, String defaultName) + { + return translate(defaultName); + } + + @Override + public String nameForSetterMethod(MapperConfig> config, AnnotatedMethod method, String defaultName) + { + return translate(defaultName); + } + + @Override + public String nameForConstructorParameter(MapperConfig> config, AnnotatedParameter ctorParam, String defaultName) + { + return translate(defaultName); + } + + public abstract String translate(String propertyName); + + /** + * Helper method to share implementation between snake and dotted case. + */ + protected String translateLowerCaseWithSeparator(final String input, final char separator) + { + if (input == null || input.isEmpty()) { + return input; + } + + final int length = input.length(); + final StringBuilder result = new StringBuilder(length + (length >> 1)); + int upperCount = 0; + for (int i = 0; i < length; ++i) { + char ch = input.charAt(i); + char lc = Character.toLowerCase(ch); + + if (lc == ch) { // lower-case letter means we can get new word + // but need to check for multi-letter upper-case (acronym), where assumption + // is that the last upper-case char is start of a new word + if (upperCount > 1) { + // so insert hyphen before the last character now + result.insert(result.length() - 1, separator); + } + upperCount = 0; + } else { + // Otherwise starts new word, unless beginning of string + if ((upperCount == 0) && (i > 0)) { + result.append(separator); + } + ++upperCount; + } + result.append(lc); + } + return result.toString(); + } + } + + /* + /********************************************************************** + /* Standard implementations + /********************************************************************** + */ + + /** + * A {@link PropertyNamingStrategy} that translates typical camel case Java + * property names to lower case JSON element names, separated by + * underscores. This implementation is somewhat lenient, in that it + * provides some additional translations beyond strictly translating from + * camel case only. In particular, the following translations are applied + * by this PropertyNamingStrategy. + * + *
+ * These rules result in the following additional example translations from + * Java property names to JSON element names. + *
+ * This rules result in the following example translation from + * Java property names to JSON element names. + *
+ * For example, "userName" would be converted to
+ * "UserName".
+ *
+ * @param input formatted as camelCase string
+ * @return input converted to PascalCase format
+ */
+ @Override
+ public String translate(String input)
+ {
+ if (input == null || input.isEmpty()) {
+ return input; // garbage in, garbage out
+ }
+ // Replace first lower-case letter with upper-case equivalent
+ char c = input.charAt(0);
+ char uc = Character.toUpperCase(c);
+ if (c == uc) {
+ return input;
+ }
+ StringBuilder sb = new StringBuilder(input);
+ sb.setCharAt(0, uc);
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Simple strategy where external name simply only uses lower-case characters,
+ * and no separators.
+ * Conversion from internal name like "someOtherValue" would be into external name
+ * if "someothervalue".
+ */
+ public static class LowerCaseStrategy extends NamingBase
+ {
+ private static final long serialVersionUID = 2L;
+
+ /**
+ * @since 2.14
+ */
+ public static final PropertyNamingStrategies.LowerCaseStrategy INSTANCE = new PropertyNamingStrategies.LowerCaseStrategy();
+
+ @Override
+ public String translate(String input)
+ {
+ if (input == null || input.isEmpty()) {
+ return input;
+ }
+ return input.toLowerCase(Locale.ENGLISH);
+ }
+ }
+
+ /**
+ * Naming strategy similar to {@link PropertyNamingStrategies.SnakeCaseStrategy},
+ * but instead of underscores
+ * as separators, uses hyphens. Naming convention traditionally used for languages
+ * like Lisp.
+ */
+ public static class KebabCaseStrategy extends NamingBase
+ {
+ private static final long serialVersionUID = 2L;
+
+ /**
+ * @since 2.14
+ */
+ public static final PropertyNamingStrategies.KebabCaseStrategy INSTANCE = new PropertyNamingStrategies.KebabCaseStrategy();
+
+ @Override
+ public String translate(String input)
+ {
+ return translateLowerCaseWithSeparator(input, '-');
+ }
+ }
+
+ /**
+ * Naming strategy similar to {@link PropertyNamingStrategies.KebabCaseStrategy},
+ * but instead of hyphens
+ * as separators, uses dots. Naming convention widely used as configuration properties name.
+ */
+ public static class LowerDotCaseStrategy extends NamingBase
+ {
+ private static final long serialVersionUID = 2L;
+
+ /**
+ * @since 2.14
+ */
+ public static final PropertyNamingStrategies.LowerDotCaseStrategy INSTANCE = new PropertyNamingStrategies.LowerDotCaseStrategy();
+
+ @Override
+ public String translate(String input)
+ {
+ return translateLowerCaseWithSeparator(input, '.');
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index 6f667c4fc6ec..fbdc6f83bc09 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1299,7 +1299,8 @@