You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by dk...@apache.org on 2018/11/20 20:28:38 UTC

[avro] branch master updated: AVRO-1658: Java: Add reflection annotation @AvroDoc.

This is an automated email from the ASF dual-hosted git repository.

dkulp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new 01a347e  AVRO-1658: Java: Add reflection annotation @AvroDoc.
01a347e is described below

commit 01a347e996a20406b0bf13026dd375725c4efb7f
Author: Evan McClain <ae...@gmail.com>
AuthorDate: Sun Sep 17 00:13:54 2017 -0400

    AVRO-1658: Java: Add reflection annotation @AvroDoc.
    
    @AvroMeta can be used for other keys, but doc is passed into the field's
    constructor.
    
    Patch 2: @AvroDoc should work for class-level documentation too.
    
    Closes #189
---
 .../main/java/org/apache/avro/reflect/AvroDoc.java | 17 ++++++++++++
 .../java/org/apache/avro/reflect/ReflectData.java  | 12 ++++++---
 .../java/org/apache/avro/reflect/TestReflect.java  | 30 ++++++++++++++++++++++
 3 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroDoc.java b/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroDoc.java
new file mode 100644
index 0000000..7b46a47
--- /dev/null
+++ b/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroDoc.java
@@ -0,0 +1,17 @@
+package org.apache.avro.reflect;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Sets the avrodoc for this java field.
+ * When reading into this class, a reflectdatumreader
+ * looks for a schema field with the avrodoc.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
+public @interface AvroDoc {
+  String value();
+}
diff --git a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
index 12d3e15..3e9e079 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
@@ -574,6 +574,8 @@ public class ReflectData extends SpecificData {
       String fullName = c.getName();
       Schema schema = names.get(fullName);
       if (schema == null) {
+        AvroDoc annotatedDoc = c.getAnnotation(AvroDoc.class);    // Docstring
+        String doc = (annotatedDoc != null) ? annotatedDoc.value() : null;
         String name = c.getSimpleName();
         String space = c.getPackage() == null ? "" : c.getPackage().getName();
         if (c.getEnclosingClass() != null)                   // nested class
@@ -590,18 +592,18 @@ public class ReflectData extends SpecificData {
           Enum[] constants = (Enum[])c.getEnumConstants();
           for (int i = 0; i < constants.length; i++)
             symbols.add(constants[i].name());
-          schema = Schema.createEnum(name, null /* doc */, space, symbols);
+          schema = Schema.createEnum(name, doc, space, symbols);
           consumeAvroAliasAnnotation(c, schema);
         } else if (GenericFixed.class.isAssignableFrom(c)) { // fixed
           int size = c.getAnnotation(FixedSize.class).value();
-          schema = Schema.createFixed(name, null /* doc */, space, size);
+          schema = Schema.createFixed(name, doc, space, size);
           consumeAvroAliasAnnotation(c, schema);
         } else if (IndexedRecord.class.isAssignableFrom(c)) { // specific
           return super.createSchema(type, names);
         } else {                                             // record
           List<Schema.Field> fields = new ArrayList<>();
           boolean error = Throwable.class.isAssignableFrom(c);
-          schema = Schema.createRecord(name, null /* doc */, space, error);
+          schema = Schema.createRecord(name, doc, space, error);
           consumeAvroAliasAnnotation(c, schema);
           names.put(c.getName(), schema);
           for (Field field : getCachedFields(c))
@@ -613,6 +615,8 @@ public class ReflectData extends SpecificData {
               Object defaultValue = (defaultAnnotation == null)
                 ? null
                 : Schema.parseJsonToObject(defaultAnnotation.value());
+              annotatedDoc = field.getAnnotation(AvroDoc.class);    // Docstring
+              doc = (annotatedDoc != null) ? annotatedDoc.value() : null;
 
               if (defaultValue == null
                   && fieldSchema.getType() == Schema.Type.UNION) {
@@ -626,7 +630,7 @@ public class ReflectData extends SpecificData {
                 ? annotatedName.value()
                 : field.getName();
               Schema.Field recordField
-                = new Schema.Field(fieldName, fieldSchema, null, defaultValue);
+                = new Schema.Field(fieldName, fieldSchema, doc, defaultValue);
 
               AvroMeta meta = field.getAnnotation(AvroMeta.class);              // add metadata
               if (meta != null)
diff --git a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
index 45ee2af..c58030d 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
@@ -1128,4 +1128,34 @@ public class TestReflect {
   public void testNullableByteArrayNullValue() throws Exception {
     checkReadWrite(new NullableBytesTest());
   }
+
+  private enum DocTestEnum {
+    ENUM_1,
+    ENUM_2
+  }
+
+  @AvroDoc("DocTest class docs")
+  private static class DocTest {
+    @AvroDoc("Some Documentation")
+    int foo;
+
+    @AvroDoc("Some other Documentation")
+    DocTestEnum enums;
+
+    @AvroDoc("And again")
+    DefaultTest defaultTest;
+  }
+
+  @Test
+  public void testAvroDoc() {
+    check(DocTest.class,
+            "{\"type\":\"record\",\"name\":\"DocTest\",\"namespace\":\"org.apache.avro.reflect.TestReflect\","
+                    + "\"doc\":\"DocTest class docs\","
+                    + "\"fields\":[{\"name\":\"foo\",\"type\":\"int\",\"doc\":\"Some Documentation\"},"
+                    + "{\"name\":\"enums\",\"type\":{\"type\":\"enum\",\"name\":\"DocTestEnum\","
+                    + "\"symbols\":[\"ENUM_1\",\"ENUM_2\"]},\"doc\":\"Some other Documentation\"},"
+                    + "{\"name\":\"defaultTest\",\"type\":{\"type\":\"record\",\"name\":\"DefaultTest\","
+                    + "\"fields\":[{\"name\":\"foo\",\"type\":\"int\",\"default\":1}]},\"doc\":\"And again\"}]}");
+  }
+
 }