Add the ability to access type annotations for Java
Client: java
Patch: jrhee17 <guins_j@guins.org>

This closes #3114
diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc
index d944e26..3524ada 100644
--- a/compiler/cpp/src/thrift/generate/t_java_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc
@@ -2997,7 +2997,7 @@
 }
 
 void t_java_generator::generate_metadata_for_field_annotations(std::ostream& out, t_field* field) {
-  if (field->annotations_.size() == 0) {
+  if (field->annotations_.size() == 0 && field->get_type()->annotations_.size() == 0) {
     return;
   }
   out << ", " << '\n';
@@ -3014,6 +3014,15 @@
                        + "\", \"" + annotation.second.back() + "\"))"
                 << '\n';
   }
+  for (auto& annotation : field->get_type()->annotations_) {
+    // field annotations have higher priority than type annotations
+    if (field->annotations_.find(annotation.first) != field->annotations_.end()) {
+      continue;
+    }
+    indent(out) << ".add(new java.util.AbstractMap.SimpleImmutableEntry<>(\"" + annotation.first
+                       + "\", \"" + annotation.second.back() + "\"))"
+                << '\n';
+  }
   indent(out) << ".build().collect(java.util.stream.Collectors.toMap(java.util.Map.Entry::getKey, "
                  "java.util.Map.Entry::getValue))";
   indent_down();
diff --git a/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java b/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java
index c40c49b..e06ea23 100644
--- a/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java
+++ b/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java
@@ -65,5 +65,15 @@
       expected.put("compression", "false");
       assertEquals(expected, metadata);
     }
+    {
+      Map<String, String> metadata =
+          structMetaDataMap
+              .get(OneOfEachBeansWithAnnotations._Fields.TYPEDEF_META)
+              .getFieldAnnotations();
+      Map<String, String> expected = new HashMap<>();
+      expected.put("a", "b");
+      expected.put("c", "d");
+      assertEquals(expected, metadata);
+    }
   }
 }
diff --git a/lib/java/src/test/resources/JavaAnnotationTest.thrift b/lib/java/src/test/resources/JavaAnnotationTest.thrift
index 925a05d..15fc87a 100644
--- a/lib/java/src/test/resources/JavaAnnotationTest.thrift
+++ b/lib/java/src/test/resources/JavaAnnotationTest.thrift
@@ -19,6 +19,8 @@
 
 namespace java thrift.test.annotations
 
+typedef string my_typedef (a = "a", c = "d")
+
 struct OneOfEachBeansWithAnnotations {
   1: bool boolean_field,
   2: byte a_bite (compression = "false"),
@@ -30,5 +32,7 @@
   8: binary base64,
   9: list<byte> byte_list (non_empty = "true"),
   10: list<i16> i16_list,
-  11: list<i64> i64_list
+  11: list<i64> i64_list,
+  // a is overridden to b
+  12: my_typedef typedef_meta (a = "b"),
 }