[prev in list] [next in list] [prev in thread] [next in thread] 

List:       avro-commits
Subject:    svn commit: r1556592 - in /avro/trunk: ./ lang/java/avro/src/main/java/org/apache/avro/reflect/
From:       cutting () apache ! org
Date:       2014-01-08 18:04:18
Message-ID: 20140108180419.0FF4323888A6 () eris ! apache ! org
[Download RAW message or body]

Author: cutting
Date: Wed Jan  8 18:04:18 2014
New Revision: 1556592

URL: http://svn.apache.org/r1556592
Log:
AVRO-1421. Java: Add an @AvroSchema annotation to reflect.

Added:
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroSchema.java   \
(with props) Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
    avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java

Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1556592&r1=1556591&r2=1556592&view=diff
 ==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Wed Jan  8 18:04:18 2014
@@ -33,6 +33,8 @@ Trunk (not yet released)
     AVRO-1418. Java: Add sync support to AvroMultipleOutputs.
     (Deepak Kumar V via cutting)
 
+    AVRO-1421. Java: Add an @AvroSchema annotation to reflect. (cutting)
+
   OPTIMIZATIONS
 
     AVRO-1348. Java: Improve UTF-8 to String conversion performance in

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroSchema.java
                
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroSchema.java?rev=1556592&view=auto
 ==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroSchema.java \
                (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroSchema.java \
Wed Jan  8 18:04:18 2014 @@ -0,0 +1,44 @@
+/**
+ * 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.avro.reflect;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Declares that a Java type should have a specified Avro schema, overriding
+ * the normally inferred schema.  May be used for classes, parameters, fields
+ * and method return types.
+ * <p> This is useful for slight alterations to the schema that would be
+ * automatically inferred.  For example, a
+ * <code>List&lt;Integer&gt;</code>whose elements may be null might use the
+ * annotation
+ * <pre>@AvroSchema("{\"type\":\"array\",\"items\":[\"null\",\"int\"]}")</pre>
+ * since the {@link Nullable} annotation could not be used here.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+  @Target({ElementType.TYPE, ElementType.PARAMETER,
+           ElementType.METHOD, ElementType.FIELD})
+@Documented
+public @interface AvroSchema {
+  /** The schema to use for this value. */
+  String value();
+}

Propchange: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroSchema.java
                
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
                
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java?rev=1556592&r1=1556591&r2=1556592&view=diff
 ==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java \
                (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java \
Wed Jan  8 18:04:18 2014 @@ -422,6 +422,9 @@ public class ReflectData extends Specifi
         setElement(result, component);
         return result;
       }
+      AvroSchema explicit = c.getAnnotation(AvroSchema.class);
+      if (explicit != null)                                  // explicit schema
+        return Schema.parse(explicit.value());
       if (CharSequence.class.isAssignableFrom(c))            // String
         return Schema.create(Schema.Type.STRING);
       if (ByteBuffer.class.isAssignableFrom(c))              // bytes
@@ -580,6 +583,11 @@ public class ReflectData extends Specifi
       } catch (Exception e) {
           throw new AvroRuntimeException("Could not create schema from custom \
serializer for " + field.getName());  } 
+
+    AvroSchema explicit = field.getAnnotation(AvroSchema.class);
+    if (explicit != null)                                   // explicit schema
+      return Schema.parse(explicit.value());
+
     Schema schema = createSchema(field.getGenericType(), names);
     if (field.isAnnotationPresent(Stringable.class)) {      // Stringable
       schema = Schema.create(Schema.Type.STRING);
@@ -628,11 +636,15 @@ public class ReflectData extends Specifi
     Annotation[][] annotations = method.getParameterAnnotations();
     for (int i = 0; i < paramTypes.length; i++) {
       Schema paramSchema = getSchema(paramTypes[i], names);
-      for (int j = 0; j < annotations[i].length; j++)
-        if (annotations[i][j] instanceof Union)
-          paramSchema = getAnnotatedUnion(((Union)annotations[i][j]), names);
-        else if (annotations[i][j] instanceof Nullable)
+      for (int j = 0; j < annotations[i].length; j++) {
+        Annotation annotation = annotations[i][j];
+        if (annotation instanceof AvroSchema)     // explicit schema
+          paramSchema = Schema.parse(((AvroSchema)annotation).value());
+        else if (annotation instanceof Union)     // union
+          paramSchema = getAnnotatedUnion(((Union)annotation), names);
+        else if (annotation instanceof Nullable)  // nullable
           paramSchema = makeNullable(paramSchema);
+      }
       String paramName =  paramNames.length == paramTypes.length
         ? paramNames[i]
         : paramSchema.getName()+i;
@@ -648,6 +660,10 @@ public class ReflectData extends Specifi
     if (method.isAnnotationPresent(Nullable.class))          // nullable
       response = makeNullable(response);
 
+    AvroSchema explicit = method.getAnnotation(AvroSchema.class);
+    if (explicit != null)                         // explicit schema
+      response = Schema.parse(explicit.value());
+
     List<Schema> errs = new ArrayList<Schema>();
     errs.add(Protocol.SYSTEM_ERROR);              // every method can throw
     for (Type err : method.getGenericExceptionTypes())

Modified: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
                
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java?rev=1556592&r1=1556591&r2=1556592&view=diff
 ==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java \
                (original)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java \
Wed Jan  8 18:04:18 2014 @@ -373,6 +373,45 @@ public class TestReflect {
     assertEquals(String.class, ReflectData.get().getClass(param));
   }
 
+  // test AvroSchema annotation
+  public static class R12 {                       // fields
+    @AvroSchema("\"int\"")
+      Object x;
+
+    @AvroSchema("{\"type\":\"array\",\"items\":[\"null\",\"string\"]}")
+      List<String> strings;
+  }
+
+
+  @Test public void testR12() throws Exception {
+    Schema s = ReflectData.get().getSchema(R12.class);
+    assertEquals(Schema.Type.INT, s.getField("x").schema().getType());
+    assertEquals(Schema.parse
+                 ("{\"type\":\"array\",\"items\":[\"null\",\"string\"]}"),
+                 s.getField("strings").schema());
+  }
+    
+  @AvroSchema("\"null\"")                          // record
+  public class R13 {}
+
+  @Test public void testR13() throws Exception {
+    Schema s = ReflectData.get().getSchema(R13.class);
+    assertEquals(Schema.Type.NULL, s.getType());
+  }
+    
+  public interface P4 {
+    @AvroSchema("\"int\"")                        // message value
+    Object foo(@AvroSchema("\"int\"")Object x);   // message param
+  }
+
+  @Test public void testP4() throws Exception {
+    Protocol p = ReflectData.get().getProtocol(P4.class);
+    Protocol.Message message = p.getMessages().get("foo");
+    assertEquals(Schema.Type.INT, message.getResponse().getType());
+    Field field = message.getRequest().getField("x");
+    assertEquals(Schema.Type.INT, field.schema().getType());
+  }
+
   // test error
   @SuppressWarnings("serial")
   public static class E1 extends Exception {}


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic