diff options
author | Jiayu Liu <Jimexist@users.noreply.github.com> | 2022-05-06 03:19:57 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-05 15:19:57 -0400 |
commit | ada086529730b13eedb74a975db5167f405d18af (patch) | |
tree | 3311044cf35ddc4c9a45bd39d96eab4d74483268 | |
parent | 7fb21ebff73d6d1f87c67d7d0285ef39f704bce6 (diff) | |
download | thrift-ada086529730b13eedb74a975db5167f405d18af.tar.gz |
THRIFT-5544: annotations_as_metadata java code gen param (#2553)
Add a java code generation parameter called "annotations_as_metadata" to
optionally include Thrift field annotations as metadata in the generated code.
5 files changed, 170 insertions, 11 deletions
diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc index a875c9b62..3ce1450b1 100644 --- a/compiler/cpp/src/thrift/generate/t_java_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc @@ -78,6 +78,7 @@ public: suppress_generated_annotations_ = false; rethrow_unhandled_exceptions_ = false; unsafe_binaries_ = false; + annotations_as_metadata_ = false; for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if (iter->first.compare("beans") == 0) { bean_style_ = true; @@ -124,6 +125,8 @@ public: } } else if (iter->first.compare("unsafe_binaries") == 0) { unsafe_binaries_ = true; + } else if (iter->first.compare("annotations_as_metadata") == 0) { + annotations_as_metadata_ = true; } else { throw "unknown option java:" + iter->first; } @@ -188,6 +191,7 @@ public: void generate_java_struct_read_object(std::ostream& out, t_struct* tstruct); void generate_java_meta_data_map(std::ostream& out, t_struct* tstruct); void generate_field_value_meta_data(std::ostream& out, t_type* type); + void generate_metadata_for_field_annotations(std::ostream& out, t_field* field); std::string get_java_type_string(t_type* type); void generate_java_struct_field_by_id(ostream& out, t_struct* tstruct); void generate_reflection_setters(std::ostringstream& out, @@ -439,6 +443,7 @@ private: bool suppress_generated_annotations_; bool rethrow_unhandled_exceptions_; bool unsafe_binaries_; + bool annotations_as_metadata_; }; /** @@ -2856,6 +2861,11 @@ void t_java_generator::generate_java_meta_data_map(ostream& out, t_struct* tstru // Create value meta data generate_field_value_meta_data(out, field->get_type()); + + // Include the annotation into metadata when asked + if (annotations_as_metadata_) { + generate_metadata_for_field_annotations(out, field); + } out << "));" << endl; } @@ -2924,6 +2934,33 @@ std::string t_java_generator::get_java_type_string(t_type* type) { } } +void t_java_generator::generate_metadata_for_field_annotations(std::ostream& out, t_field* field) { + if (field->annotations_.size() == 0) { + return; + } + out << ", " << endl; + indent_up(); + indent_up(); + indent(out) << "java.util.stream.Stream.<java.util.Map.Entry<java.lang.String, " + "java.lang.String>>builder()" + << endl; + + indent_up(); + indent_up(); + for (auto& annotation : field->annotations_) { + indent(out) << ".add(new java.util.AbstractMap.SimpleImmutableEntry<>(\"" + annotation.first + + "\", \"" + annotation.second + "\"))" + << endl; + } + indent(out) << ".build().collect(java.util.stream.Collectors.toMap(java.util.Map.Entry::getKey, " + "java.util.Map.Entry::getValue))"; + indent_down(); + indent_down(); + + indent_down(); + indent_down(); +} + void t_java_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) { out << endl; indent_up(); @@ -5740,4 +5777,6 @@ THRIFT_REGISTER_GENERATOR( " generated_annotations=[undated|suppress]:\n" " undated: suppress the date at @Generated annotations\n" " suppress: suppress @Generated annotations entirely\n" - " unsafe_binaries: Do not copy ByteBuffers in constructors, getters, and setters.\n") + " unsafe_binaries: Do not copy ByteBuffers in constructors, getters, and setters.\n" + " annotations_as_metadata:\n" + " Include Thrift field annotations as metadata in the generated code.\n") diff --git a/lib/java/gradle/generateTestThrift.gradle b/lib/java/gradle/generateTestThrift.gradle index b8a963d12..e8515473e 100644 --- a/lib/java/gradle/generateTestThrift.gradle +++ b/lib/java/gradle/generateTestThrift.gradle @@ -86,6 +86,7 @@ task generateJava(group: 'Build') { thriftCompile(it, 'EnumContainersTest.thrift') thriftCompile(it, 'JavaBinaryDefault.thrift') thriftCompile(it, 'VoidMethExceptionsTest.thrift') + thriftCompile(it, 'AnnotationTest.thrift') thriftCompile(it, 'partial/thrift_test_schema.thrift') } @@ -133,3 +134,12 @@ task generateUnsafeBinariesJava(group: 'Build') { thriftCompile(it, 'UnsafeTypes.thrift', 'java:unsafe_binaries', genUnsafeSrc) } + +task generateWithAnnotationMetadata(group: 'Build') { + description = 'Generate with annotation enabled and add to the default source' + generate.dependsOn it + + ext.outputBuffer = new ByteArrayOutputStream() + + thriftCompile(it, 'JavaAnnotationTest.thrift', 'java:annotations_as_metadata', genSrc) +} diff --git a/lib/java/src/main/java/org/apache/thrift/meta_data/FieldMetaData.java b/lib/java/src/main/java/org/apache/thrift/meta_data/FieldMetaData.java index 753439045..5691f83e6 100644 --- a/lib/java/src/main/java/org/apache/thrift/meta_data/FieldMetaData.java +++ b/lib/java/src/main/java/org/apache/thrift/meta_data/FieldMetaData.java @@ -19,9 +19,14 @@ package org.apache.thrift.meta_data; +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.thrift.TBase; import org.apache.thrift.TFieldIdEnum; @@ -42,18 +47,28 @@ public class FieldMetaData implements java.io.Serializable { public final String fieldName; public final byte requirementType; public final FieldValueMetaData valueMetaData; - private static final Map<Class<? extends TBase>, Map<? extends TFieldIdEnum, FieldMetaData>> structMap; - - static { - structMap = new ConcurrentHashMap<Class<? extends TBase>, Map<? extends TFieldIdEnum, FieldMetaData>>(); - } - + private final Map<String, String> fieldAnnotations; + private static final Map<Class<? extends TBase>, Map<? extends TFieldIdEnum, FieldMetaData>> structMap = new ConcurrentHashMap<>(); + public FieldMetaData(String name, byte req, FieldValueMetaData vMetaData){ - this.fieldName = name; - this.requirementType = req; - this.valueMetaData = vMetaData; + this(name, req, vMetaData, Collections.emptyMap()); } - + + public FieldMetaData(String fieldName, byte requirementType, FieldValueMetaData valueMetaData, Map<String, String> fieldAnnotations) { + this.fieldName = fieldName; + this.requirementType = requirementType; + this.valueMetaData = valueMetaData; + this.fieldAnnotations = fieldAnnotations; + } + + /** + * @return an unmodifiable view of the annotations for this field, empty if no annotations present or code gen param + * is not turned on + */ + public Map<String, String> getFieldAnnotations() { + return Collections.unmodifiableMap(fieldAnnotations); + } + public static void addStructMetaDataMap(Class<? extends TBase> sClass, Map<? extends TFieldIdEnum, FieldMetaData> map){ structMap.put(sClass, map); } diff --git a/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java b/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java new file mode 100644 index 000000000..a9381e65d --- /dev/null +++ b/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java @@ -0,0 +1,61 @@ +/* + * 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 org.apache.thrift; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.thrift.meta_data.FieldMetaData; +import org.junit.Assert; +import org.junit.Test; +import thrift.test.OneOfEachBeans; +import thrift.test.annotations.OneOfEachBeansWithAnnotations; + +public class TestAnnotationMetadata { + + @Test + public void testWithoutParamShouldGenerateEmpty() { + Map<? extends TFieldIdEnum, FieldMetaData> structMetaDataMap = FieldMetaData.getStructMetaDataMap(OneOfEachBeans.class); + { + Map<String, String> metadata = structMetaDataMap.get(OneOfEachBeans._Fields.I16_LIST).getFieldAnnotations(); + Assert.assertEquals(Collections.emptyMap(), metadata); + } + { + Map<String, String> metadata = structMetaDataMap.get(OneOfEachBeans._Fields.A_BITE).getFieldAnnotations(); + Assert.assertEquals(Collections.emptyMap(), metadata); + } + } + + @Test + public void testGeneratedAnnotations() { + Map<? extends TFieldIdEnum, FieldMetaData> structMetaDataMap = FieldMetaData.getStructMetaDataMap(OneOfEachBeansWithAnnotations.class); + { + Map<String, String> metadata = structMetaDataMap.get(OneOfEachBeansWithAnnotations._Fields.I16_LIST).getFieldAnnotations(); + Assert.assertEquals(Collections.emptyMap(), metadata); + } + { + Map<String, String> metadata = structMetaDataMap.get(OneOfEachBeansWithAnnotations._Fields.A_BITE).getFieldAnnotations(); + Map<String, String> expected = new HashMap<>(); + expected.put("compression", "false"); + Assert.assertEquals(expected, metadata); + } + } +} diff --git a/lib/java/src/test/resources/JavaAnnotationTest.thrift b/lib/java/src/test/resources/JavaAnnotationTest.thrift new file mode 100644 index 000000000..925a05d16 --- /dev/null +++ b/lib/java/src/test/resources/JavaAnnotationTest.thrift @@ -0,0 +1,34 @@ +/* + * 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. + */ + +namespace java thrift.test.annotations + +struct OneOfEachBeansWithAnnotations { + 1: bool boolean_field, + 2: byte a_bite (compression = "false"), + 3: i16 integer16 (must_be_postive = "true"), + 4: i32 integer32, + 5: i64 integer64, + 6: double double_precision (nan_inf_allowed = "false"), + 7: string some_characters, + 8: binary base64, + 9: list<byte> byte_list (non_empty = "true"), + 10: list<i16> i16_list, + 11: list<i64> i64_list +} |