avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cutt...@apache.org
Subject svn commit: r1511531 - in /avro/trunk: ./ lang/java/avro/src/main/java/org/apache/avro/ lang/java/avro/src/main/java/org/apache/avro/generic/ lang/java/avro/src/main/java/org/apache/avro/reflect/ lang/java/avro/src/test/java/org/apache/avro/reflect/
Date Wed, 07 Aug 2013 23:16:59 GMT
Author: cutting
Date: Wed Aug  7 23:16:58 2013
New Revision: 1511531

URL: http://svn.apache.org/r1511531
Log:
AVRO-1341. Java: Add reflection annotations @AvroName, @AvroIgnore, @AvroMeta, @AvroAlias
and @AvroEncode.  Contributed by Vincenz Priesnitz.

Added:
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroAlias.java   (with
props)
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroEncode.java   (with
props)
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroIgnore.java   (with
props)
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroMeta.java   (with
props)
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroName.java   (with
props)
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/CustomEncoding.java  
(with props)
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/DateAsLongEncoding.java
  (with props)
Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessUnsafe.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessor.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumReader.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumWriter.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/Stringable.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/package.html
    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=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Wed Aug  7 23:16:58 2013
@@ -19,6 +19,9 @@ Trunk (not yet released)
     AVRO-1337. Java: Add a command line tool to generate schema files
     from a protocol. (Bertrand Dechoux via cutting)
 
+    AVRO-1341. Java: Add reflection annotations @AvroName, @AvroIgnore,
+    @AvroMeta, @AvroAlias and @AvroEncode. (Vincenz Priesnitz via cutting)
+
   IMPROVEMENTS
 
     AVRO-1260. Ruby: Improve read performance. (Martin Kleppmann via cutting)

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java Wed Aug  7 23:16:58
2013
@@ -242,6 +242,11 @@ public abstract class Schema extends Jso
     throw new AvroRuntimeException("Not a named type: "+this);
   }
 
+  /** If this is a record, enum or fixed, add an alias. */
+  public void addAlias(String alias, String space) {
+    throw new AvroRuntimeException("Not a named type: "+this);
+  }
+
   /** If this is a record, enum or fixed, return its aliases, if any. */
   public Set<String> getAliases() {
     throw new AvroRuntimeException("Not a named type: "+this);
@@ -481,9 +486,14 @@ public abstract class Schema extends Jso
     public String getNamespace() { return name.space; }
     public String getFullName() { return name.full; }
     public void addAlias(String alias) {
+      addAlias(alias, null);
+    }
+    public void addAlias(String name, String space) {
       if (aliases == null)
         this.aliases = new LinkedHashSet<Name>();
-      aliases.add(new Name(alias, name.space));
+      if (space == null)
+        space = this.name.space;
+      aliases.add(new Name(name, space));
     }
     public Set<String> getAliases() {
       Set<String> result = new LinkedHashSet<String>();

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
(original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
Wed Aug  7 23:16:58 2013
@@ -400,7 +400,7 @@ public class GenericDatumReader<D> imple
     new HashMap<Class,Constructor>();
 
   @SuppressWarnings("unchecked")
-  private Object newInstanceFromString(Class c, String s) {
+  protected Object newInstanceFromString(Class c, String s) {
     try {
       Constructor ctor = stringCtorCache.get(c);
       if (ctor == null) {

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroAlias.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroAlias.java?rev=1511531&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroAlias.java (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroAlias.java Wed Aug
 7 23:16:58 2013
@@ -0,0 +1,37 @@
+/**
+ * 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.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Adds the given name and space as an alias to the schema.
+ * Avro files of this schema can be read into classes
+ * named by the alias. 
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface AvroAlias {
+  String NULL = "NOT A VALID NAMESPACE";
+
+  String alias();
+  String space() default NULL;
+}

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

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroEncode.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroEncode.java?rev=1511531&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroEncode.java (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroEncode.java Wed Aug
 7 23:16:58 2013
@@ -0,0 +1,35 @@
+/**
+ * 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.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Expert: Fields with this annotation are encoded using the given custom encoder.
+ * This annotation overrides {@link org.apache.avro.reflect.Stringable Stringable} and {@link
org.apache.avro.reflect.Nullable Nullable}.
+ * Since no validation is performed, invalid custom encodings may result in an unreadable
file.
+ * Use of {@link org.apache.avro.io.ValidatingEncoder} is recommended.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface AvroEncode {
+  Class<? extends CustomEncoding<?>> using();
+}

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

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroIgnore.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroIgnore.java?rev=1511531&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroIgnore.java (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroIgnore.java Wed Aug
 7 23:16:58 2013
@@ -0,0 +1,33 @@
+/**
+ * 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.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a field as transient.
+ * Such a field will not get written into or read from a schema,
+ * when using reflection.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface AvroIgnore {
+}

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

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroMeta.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroMeta.java?rev=1511531&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroMeta.java (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroMeta.java Wed Aug
 7 23:16:58 2013
@@ -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.
+ */
+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;
+
+/**
+ * Adds the given key:Value pair as metadata into the schema,
+ * at the corresponding node.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
+public @interface AvroMeta {
+  String key();
+  String value();
+}

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

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroName.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroName.java?rev=1511531&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroName.java (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/AvroName.java Wed Aug
 7 23:16:58 2013
@@ -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.
+ */
+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 avroname for this java field.
+ * When reading into this class, a reflectdatumreader
+ * looks for a schema field with the avroname.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AvroName {
+  String value();
+}

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

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/CustomEncoding.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/CustomEncoding.java?rev=1511531&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/CustomEncoding.java (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/CustomEncoding.java Wed
Aug  7 23:16:58 2013
@@ -0,0 +1,53 @@
+/**
+ * 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.io.IOException;
+
+import org.apache.avro.Schema;
+import org.apache.avro.io.Decoder;
+import org.apache.avro.io.Encoder;
+
+/**
+ * Expert:  a custom encoder and decoder that writes
+ * an object directly to avro. 
+ * No validation is performed to check that the encoding conforms to the schema.
+ * Invalid implementations may result in an unreadable file.
+ * The use of {@link org.apache.avro.io.ValidatingEncoder} is recommended. 
+ *
+ * @param <T> The class of objects that can be serialized with this encoder / decoder.
+ */
+public abstract class CustomEncoding<T> {
+
+  protected Schema schema;
+
+  
+  protected abstract void write(Object datum, Encoder out) throws IOException;
+
+  protected abstract T read(Object reuse, Decoder in) throws IOException;
+
+  T read(Decoder in) throws IOException {
+    return this.read(null, in);
+  }
+
+  protected Schema getSchema() {
+    return schema;
+  }
+
+
+}

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

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/DateAsLongEncoding.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/DateAsLongEncoding.java?rev=1511531&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/DateAsLongEncoding.java
(added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/DateAsLongEncoding.java
Wed Aug  7 23:16:58 2013
@@ -0,0 +1,53 @@
+/**
+ * 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.io.IOException;
+import java.util.Date;
+
+import org.apache.avro.Schema;
+import org.apache.avro.io.Decoder;
+import org.apache.avro.io.Encoder;
+
+/**
+ * This encoder/decoder writes a java.util.Date object as a long to
+ * avro and reads a Date object from long.
+ * The long stores the number of milliseconds since January 1, 1970, 00:00:00 GMT
+ * represented by the Date object.
+ */
+public class DateAsLongEncoding extends CustomEncoding<Date> {
+  {
+    schema = Schema.create(Schema.Type.LONG);
+    schema.addProp("CustomEncoding", "DateAsLongEncoding");
+  }
+
+  @Override
+  protected final void write(Object datum, Encoder out) throws IOException {
+    out.writeLong(((Date)datum).getTime());
+  }
+
+  @Override
+  protected final Date read(Object reuse, Decoder in) throws IOException {
+    if (reuse != null && reuse instanceof Date) {
+      ((Date)reuse).setTime(in.readLong());
+      return (Date)reuse;
+    }
+    else return new Date(in.readLong());
+  }
+
+}

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

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
(original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
Wed Aug  7 23:16:58 2013
@@ -29,10 +29,14 @@ class FieldAccessReflect extends FieldAc
 
   private final class ReflectionBasedAccessor extends FieldAccessor {
     private final Field field;
+    private boolean isStringable;
+    private boolean isCustomEncoded;
 
     public ReflectionBasedAccessor(Field field) {
       this.field = field;
       this.field.setAccessible(true);
+      isStringable = field.isAnnotationPresent(Stringable.class);
+      isCustomEncoded = field.isAnnotationPresent(AvroEncode.class); 
     }
 
     @Override
@@ -50,6 +54,21 @@ class FieldAccessReflect extends FieldAc
         IOException {
       field.set(object, value);
     }
+    
+    @Override
+    protected Field getField() {
+      return field;
+    }
+    
+    @Override
+    protected boolean isStringable() {
+      return isStringable;
+    }
+    
+    @Override
+    protected boolean isCustomEncoded() {
+      return isCustomEncoded;
+    }
 
   }
 }

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessUnsafe.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessUnsafe.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessUnsafe.java
(original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessUnsafe.java
Wed Aug  7 23:16:58 2013
@@ -20,6 +20,7 @@ package org.apache.avro.reflect;
 import java.io.IOException;
 import java.lang.reflect.Field;
 
+import org.apache.avro.AvroRuntimeException;
 import org.apache.avro.io.Decoder;
 import org.apache.avro.io.Encoder;
 
@@ -43,6 +44,13 @@ class FieldAccessUnsafe extends FieldAcc
 
   @Override
   protected FieldAccessor getAccessor(Field field) {
+    AvroEncode enc = field.getAnnotation(AvroEncode.class);
+    if (enc != null)
+      try {
+        return new UnsafeCustomEncodedField(field, enc.using().newInstance() );
+      } catch (Exception e) {
+        throw new AvroRuntimeException("Could not instantiate custom Encoding");
+      }
     Class<?> c = field.getType();
     if (c == int.class)
       return new UnsafeIntField(field);
@@ -66,20 +74,34 @@ class FieldAccessUnsafe extends FieldAcc
 
   abstract static class UnsafeCachedField extends FieldAccessor {
     protected final long offset;
+    protected Field field;
+    protected final boolean isStringable;
 
-    UnsafeCachedField(long offset) {
-      this.offset = offset;
+    UnsafeCachedField(Field f) {
+      this.offset = UNSAFE.objectFieldOffset(f);
+      this.field = f;
+      this.isStringable = f.isAnnotationPresent(Stringable.class);
+    }
+
+    @Override
+    protected Field getField() {
+      return field;
     }
 
     @Override
     protected boolean supportsIO() {
       return true;
     }
+    
+    @Override
+    protected boolean isStringable() {
+      return isStringable;
+    }
   }
 
   final static class UnsafeIntField extends UnsafeCachedField {
     UnsafeIntField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -105,7 +127,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeFloatField extends UnsafeCachedField {
     protected UnsafeFloatField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -131,7 +153,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeShortField extends UnsafeCachedField {
     protected UnsafeShortField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -157,7 +179,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeByteField extends UnsafeCachedField {
     protected UnsafeByteField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -183,7 +205,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeBooleanField extends UnsafeCachedField {
     protected UnsafeBooleanField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -209,7 +231,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeCharField extends UnsafeCachedField {
     protected UnsafeCharField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -235,7 +257,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeLongField extends UnsafeCachedField {
     protected UnsafeLongField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -261,7 +283,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeDoubleField extends UnsafeCachedField {
     protected UnsafeDoubleField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -287,7 +309,7 @@ class FieldAccessUnsafe extends FieldAcc
 
   final static class UnsafeObjectField extends UnsafeCachedField {
     protected UnsafeObjectField(Field f) {
-      super(UNSAFE.objectFieldOffset(f));
+      super(f);
     }
 
     @Override
@@ -306,4 +328,38 @@ class FieldAccessUnsafe extends FieldAcc
     }
     
   }
+  
+  final static class UnsafeCustomEncodedField extends UnsafeCachedField {
+
+    private CustomEncoding<?> encoding;
+    
+    UnsafeCustomEncodedField(Field f, CustomEncoding<?> encoding) {
+      super(f);
+      this.encoding = encoding;
+    }
+
+    @Override
+    protected Object get(Object object) throws IllegalAccessException {
+      return UNSAFE.getObject(object, offset);
+    }
+
+    @Override
+    protected void set(Object object, Object value) throws IllegalAccessException, IOException
{
+      UNSAFE.putObject(object, offset, value);
+    }
+    
+    @Override
+    protected void read(Object object, Decoder in) throws IOException {
+      UNSAFE.putObject(object, offset, encoding.read(in));
+    }
+
+    @Override
+    protected void write(Object object, Encoder out) throws IOException {
+      encoding.write(UNSAFE.getObject(object, offset), out);
+    }
+    
+    protected boolean isCustomEncoded() {
+      return true;
+    }
+  }
 }

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessor.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessor.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessor.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessor.java Wed
Aug  7 23:16:58 2013
@@ -18,6 +18,7 @@
 package org.apache.avro.reflect;
 
 import java.io.IOException;
+import java.lang.reflect.Field;
 
 import org.apache.avro.io.Decoder;
 import org.apache.avro.io.Encoder;
@@ -40,4 +41,15 @@ abstract class FieldAccessor {
   protected boolean supportsIO() {
     return false;
   }
+  
+  protected abstract Field getField();
+  
+  protected boolean isStringable() {
+    return false;
+  }
+  
+  protected boolean isCustomEncoded() {
+    return false;
+  }
+  
 }

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=1511531&r1=1511530&r2=1511531&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 Aug
 7 23:16:58 2013
@@ -211,8 +211,14 @@ public class ReflectData extends Specifi
     private ClassAccessorData(Class<?> c) {
       clazz = c;
       for(Field f : getFields(c, false)) {
+        if (f.isAnnotationPresent(AvroIgnore.class)) {
+          continue;
+        }
         FieldAccessor accessor = ReflectionUtil.getFieldAccess().getAccessor(f);
-        byName.put(f.getName(), accessor);
+        AvroName avroname = f.getAnnotation(AvroName.class);    
+        byName.put( (avroname != null 
+          ? avroname.value()
+          : f.getName()) , accessor);  
       }
     }
     
@@ -436,18 +442,22 @@ public class ReflectData extends Specifi
           for (int i = 0; i < constants.length; i++)
             symbols.add(constants[i].name());
           schema = Schema.createEnum(name, null /* 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);
+          consumeAvroAliasAnnotation(c, schema);
         } else if (IndexedRecord.class.isAssignableFrom(c)) { // specific
           return super.createSchema(type, names);
         } else {                                             // record
           List<Schema.Field> fields = new ArrayList<Schema.Field>();
           boolean error = Throwable.class.isAssignableFrom(c);
           schema = Schema.createRecord(name, null /* doc */, space, error);
+          consumeAvroAliasAnnotation(c, schema);
           names.put(c.getName(), schema);
           for (Field field : getCachedFields(c))
-            if ((field.getModifiers()&(Modifier.TRANSIENT|Modifier.STATIC))==0){
+            if ((field.getModifiers()&(Modifier.TRANSIENT|Modifier.STATIC))==0 
+                && !field.isAnnotationPresent(AvroIgnore.class)) {
               Schema fieldSchema = createFieldSchema(field, names);
               JsonNode defaultValue = null;
               if (fieldSchema.getType() == Schema.Type.UNION) {
@@ -456,14 +466,29 @@ public class ReflectData extends Specifi
                   defaultValue = NullNode.getInstance();
                 }
               }
-              Schema.Field recordField = new Schema.Field(field.getName(),
-                      fieldSchema, null /* doc */, defaultValue);
+              AvroName annotatedName = field.getAnnotation(AvroName.class);       // Rename
fields
+              String fieldName = (annotatedName != null)            
+                ? annotatedName.value()
+                : field.getName();
+              Schema.Field recordField 
+                = new Schema.Field(fieldName, fieldSchema, null, defaultValue);
+             
+              AvroMeta meta = field.getAnnotation(AvroMeta.class);              // add metadata
+              if (meta != null) 
+                recordField.addProp(meta.key(), meta.value());  
+              for(Schema.Field f : fields) {                                
+                if (f.name().equals(fieldName)) 
+                  throw new AvroTypeException("double field entry: "+ fieldName);
+              }
               fields.add(recordField);
             }
           if (error)                              // add Throwable message
             fields.add(new Schema.Field("detailMessage", THROWABLE_MESSAGE,
                                         null, null));
           schema.setFields(fields);
+          AvroMeta meta = c.getAnnotation(AvroMeta.class);
+          if (meta != null) 
+              schema.addProp(meta.key(), meta.value());
         }
         names.put(fullName, schema);
       }
@@ -536,7 +561,17 @@ public class ReflectData extends Specifi
   
   /** Create a schema for a field. */
   protected Schema createFieldSchema(Field field, Map<String, Schema> names) {
+    AvroEncode enc = field.getAnnotation(AvroEncode.class);
+    if (enc != null)
+      try {
+          return enc.using().newInstance().getSchema();
+      } catch (Exception e) {
+          throw new AvroRuntimeException("Could not create schema from custom serializer
for " + field.getName());
+      } 
     Schema schema = createSchema(field.getGenericType(), names);
+    if (field.isAnnotationPresent(Stringable.class)) {      // Stringable
+      schema = Schema.create(Schema.Type.STRING);
+    }
     if (field.isAnnotationPresent(Nullable.class))           // nullable
       schema = makeNullable(schema);
     return schema;
@@ -650,4 +685,15 @@ public class ReflectData extends Specifi
   protected Object getRecordState(Object record, Schema schema) {
     return getFieldAccessors(record.getClass(), schema);
   }
+  
+  private void consumeAvroAliasAnnotation(Class<?> c, Schema schema) {
+    AvroAlias alias = c.getAnnotation(AvroAlias.class);
+    if (alias != null) {
+      String space = alias.space();
+      if (AvroAlias.NULL.equals(space))
+        space = null;
+      schema.addAlias(alias.alias(), space);
+    }
+  }
+  
 }

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumReader.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumReader.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumReader.java
(original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumReader.java
Wed Aug  7 23:16:58 2013
@@ -87,6 +87,9 @@ public class ReflectDatumReader<T> exten
     }
 
     if (elementClass == null) {
+      elementClass = collectionClass.getComponentType();
+    }
+    if (elementClass == null) {
       ReflectData data = (ReflectData)getData();
       elementClass = data.getClass(schema.getElementType());
     }
@@ -204,10 +207,24 @@ public class ReflectDatumReader<T> exten
       ResolvingDecoder in, Object state) throws IOException {
     if (state != null) {
       FieldAccessor accessor = ((FieldAccessor[]) state)[f.pos()];
-      if (accessor != null && !Schema.Type.UNION.equals(f.schema().getType())
-          && accessor.supportsIO()) {
-        accessor.read(record, in);
-        return;
+      if (accessor != null) {
+        if (accessor.supportsIO()
+            && (!Schema.Type.UNION.equals(f.schema().getType())
+                || accessor.isCustomEncoded())) {
+          accessor.read(record, in);
+          return;
+        }
+        if (accessor.isStringable()) {
+          try {
+            String asString = (String) read(null, f.schema(), in);
+            accessor.set(record, asString == null 
+              ? null
+              : newInstanceFromString(accessor.getField().getType(), asString));
+            return;
+          } catch (Exception e) {
+            throw new AvroRuntimeException("Failed to read Stringable", e);
+          } 
+        }
       }
     }
     super.readField(record, f, oldDatum, in, state);

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumWriter.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumWriter.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumWriter.java
(original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumWriter.java
Wed Aug  7 23:16:58 2013
@@ -154,10 +154,22 @@ public class ReflectDatumWriter<T> exten
       throws IOException {
     if (state != null) {
       FieldAccessor accessor = ((FieldAccessor[]) state)[f.pos()];
-      if (accessor != null && !Schema.Type.UNION.equals(f.schema().getType())
-          && accessor.supportsIO()) {
-        accessor.write(record, out);
-        return;
+      if (accessor != null) {
+        if (accessor.supportsIO()
+            && (!Schema.Type.UNION.equals(f.schema().getType())
+                || accessor.isCustomEncoded())) {
+          accessor.write(record, out);
+          return;
+        }
+        if (accessor.isStringable()) {
+          try {
+            Object object = accessor.get(record);
+            write(f.schema(), (object == null) ? null : object.toString(), out);
+          } catch (IllegalAccessException e) {
+            throw new AvroRuntimeException("Failed to write Stringable", e);
+          }
+          return;
+        }  
       }
     }
     super.writeField(record, f, out, state);

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/Stringable.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/Stringable.java?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/Stringable.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/Stringable.java Wed Aug
 7 23:16:58 2013
@@ -24,11 +24,11 @@ import java.lang.annotation.RetentionPol
 import java.lang.annotation.Target;
 
 /**
- * Declares that a class should be represented by an Avro string.  It's {@link
+ * Declares that a class or field should be represented by an Avro string.  It's {@link
  * Object#toString()} method will be used to convert it to a string, and its
  * single String parameter constructor will be used to create instances.
  */
 @Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
+@Target({ElementType.TYPE, ElementType.FIELD})
 @Documented
 public @interface Stringable {}

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/package.html
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/package.html?rev=1511531&r1=1511530&r2=1511531&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/package.html (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/package.html Wed Aug 
7 23:16:58 2013
@@ -77,5 +77,22 @@ and other uses of polymorphism.
 will cause a type to be serialized via its {@link java.lang.Object#toString()
 toString} method.
 
+<p>Fields annotated with {@link org.apache.avro.reflect.AvroIgnore AvroIgnore} 
+will not be written or read to. 
+
+<p> The {@link org.apache.avro.reflect.Avroname AvroName} annotation renames 
+the field in the schema to the given name. The reflect datum reader will look 
+for a schema field with the given name, when trying to read into such an 
+annotated java field. 
+
+<p>The {@link org.apache.avro.reflect.AvroMeta AvroMeta} annotation adds an 
+arbitrary key:value pair in the schema at the node of the java field.
+
+<p>The {@link org.apache.avro.reflect.AvroEncode AvroEncode} annotation forces 
+the use of an custom encoder. This annotation overrides 
+{@link org.apache.avro.reflect.Stringable Stringable} and 
+{@link org.apache.avro.reflect.Nullable Nullable}.
+
+
 </body>
 </html>

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=1511531&r1=1511530&r2=1511531&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 Aug
 7 23:16:58 2013
@@ -433,6 +433,45 @@ public class TestReflect {
           +"{\"name\":\"a\",\"type\":\"int\"},"
           +"{\"name\":\"b\",\"type\":\"long\"}]}");
   }
+  
+  public static class RAvroIgnore { @AvroIgnore int a; }
+  @Test public void testAnnotationAvroIgnore() throws Exception {
+    check(RAvroIgnore.class, "{\"type\":\"record\",\"name\":\"RAvroIgnore\",\"namespace\":"
+          +"\"org.apache.avro.reflect.TestReflect$\",\"fields\":[]}");
+  }
+  
+  public static class RAvroMeta { @AvroMeta(key="K", value="V") int a; }
+  @Test public void testAnnotationAvroMeta() throws Exception {
+    check(RAvroMeta.class, "{\"type\":\"record\",\"name\":\"RAvroMeta\",\"namespace\":"
+          +"\"org.apache.avro.reflect.TestReflect$\",\"fields\":[" 
+          +"{\"name\":\"a\",\"type\":\"int\",\"K\":\"V\"}]}");
+  }
+  
+  public static class RAvroName { @AvroName("b") int a; }
+  @Test public void testAnnotationAvroName() throws Exception {
+    check(RAvroName.class, "{\"type\":\"record\",\"name\":\"RAvroName\",\"namespace\":"
+          +"\"org.apache.avro.reflect.TestReflect$\",\"fields\":[" 
+          +"{\"name\":\"b\",\"type\":\"int\"}]}");
+  }
+  
+  public static class RAvroNameCollide { @AvroName("b") int a; int b; }
+  @Test(expected=Exception.class)
+  public void testAnnotationAvroNameCollide() throws Exception {
+    check(RAvroNameCollide.class, "{\"type\":\"record\",\"name\":\"RAvroNameCollide\",\"namespace\":"
+          +"\"org.apache.avro.reflect.TestReflect$\",\"fields\":[" 
+          +"{\"name\":\"b\",\"type\":\"int\"}," 
+          +"{\"name\":\"b\",\"type\":\"int\"}]}");
+  }
+  
+  public static class RAvroStringableField { @Stringable int a; }
+  public void testAnnotationAvroStringableFields() throws Exception {
+    check(RAvroStringableField.class, "{\"type\":\"record\",\"name\":\"RAvroNameCollide\",\"namespace\":"
+          +"\"org.apache.avro.reflect.TestReflect$\",\"fields\":[" 
+          +"{\"name\":\"a\",\"type\":\"String\"}]}");
+  }
+  
+  
+  
 
   private void check(Object o, String schemaJson) {
     check(o.getClass(), schemaJson);
@@ -460,6 +499,129 @@ public class TestReflect {
     assertEquals(record, decoded);
   }
 
+  public static class AvroEncRecord {
+    @AvroEncode(using=DateAsLongEncoding.class)
+    java.util.Date date;
+    
+    @Override 
+    public boolean equals(Object o) {
+      if (!(o instanceof AvroEncRecord)) return false;
+      return date.equals(((AvroEncRecord)o).date);
+    }
+  }
+  
+  public static class multipleAnnotationRecord {
+    @AvroIgnore
+    @Stringable
+    Integer i1;
+    
+    @AvroIgnore
+    @Nullable
+    Integer i2;
+
+    @AvroIgnore
+    @AvroName("j")
+    Integer i3;
+    
+    @AvroIgnore
+    @AvroEncode(using=DateAsLongEncoding.class)
+    java.util.Date i4;
+    
+    @Stringable
+    @Nullable
+    Integer i5;
+    
+    @Stringable
+    @AvroName("j6")
+    Integer i6 = 6;    
+    
+    @Stringable
+    @AvroEncode(using=DateAsLongEncoding.class)
+    java.util.Date i7 = new java.util.Date(7L);
+    
+    @Nullable
+    @AvroName("j8")
+    Integer i8;    
+      
+    @Nullable
+    @AvroEncode(using=DateAsLongEncoding.class)
+    java.util.Date i9;
+
+    @AvroName("j10")
+    @AvroEncode(using=DateAsLongEncoding.class)
+    java.util.Date i10 = new java.util.Date(10L);
+
+    @Stringable
+    @Nullable
+    @AvroName("j11")
+    @AvroEncode(using=DateAsLongEncoding.class)
+    java.util.Date i11;
+  }
+  
+  @Test
+  public void testMultipleAnnotations() throws IOException {
+    Schema schm = ReflectData.get().getSchema(multipleAnnotationRecord.class);
+    ReflectDatumWriter<multipleAnnotationRecord> writer = 
+      new ReflectDatumWriter<multipleAnnotationRecord>(schm);
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    multipleAnnotationRecord record = new multipleAnnotationRecord();
+    record.i1 = 1;
+    record.i2 = 2;
+    record.i3 = 3;
+    record.i4 = new java.util.Date(4L);
+    record.i5 = 5;
+    record.i6 = 6;
+    record.i7 = new java.util.Date(7L);
+    record.i8 = 8;
+    record.i9 = new java.util.Date(9L);
+    record.i10 = new java.util.Date(10L);
+    record.i11 = new java.util.Date(11L);
+    
+    writer.write(record, factory.directBinaryEncoder(out, null));
+    ReflectDatumReader<multipleAnnotationRecord> reader = 
+      new ReflectDatumReader<multipleAnnotationRecord>(schm);
+      multipleAnnotationRecord decoded =
+      reader.read(new multipleAnnotationRecord(), DecoderFactory.get().binaryDecoder(
+          out.toByteArray(), null));
+    assertTrue(decoded.i1 == null);
+    assertTrue(decoded.i2 == null);
+    assertTrue(decoded.i3 == null);
+    assertTrue(decoded.i4 == null);
+    assertTrue(decoded.i5 == 5);
+    assertTrue(decoded.i6 == 6);
+    assertTrue(decoded.i7.getTime() == 7);
+    assertTrue(decoded.i8 == 8);
+    assertTrue(decoded.i9.getTime() == 9);
+    assertTrue(decoded.i10.getTime() == 10);
+    assertTrue(decoded.i11.getTime() == 11);
+  }
+  
+  
+  @Test
+  public void testAvroEncodeInducing() throws IOException {
+    Schema schm = ReflectData.get().getSchema(AvroEncRecord.class);
+    assertEquals(schm.toString(), "{\"type\":\"record\",\"name\":\"AvroEncRecord\",\"namespace"
+
+      "\":\"org.apache.avro.reflect.TestReflect$\",\"fields\":[{\"name\":\"date\"," +
+      "\"type\":{\"type\":\"long\",\"CustomEncoding\":\"DateAsLongEncoding\"}}]}");
+  }
+  
+  @Test
+  public void testAvroEncodeIO() throws IOException {
+    Schema schm = ReflectData.get().getSchema(AvroEncRecord.class);
+    ReflectDatumWriter<AvroEncRecord> writer = 
+      new ReflectDatumWriter<AvroEncRecord>(schm);
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    AvroEncRecord record = new AvroEncRecord();
+    record.date = new java.util.Date(948833323L);
+    writer.write(record, factory.directBinaryEncoder(out, null));
+    ReflectDatumReader<AvroEncRecord> reader = 
+      new ReflectDatumReader<AvroEncRecord>(schm);
+    AvroEncRecord decoded =
+      reader.read(new AvroEncRecord(), DecoderFactory.get().binaryDecoder(
+          out.toByteArray(), null));
+    assertEquals(record, decoded);
+  }
+  
   @Test
   public void testRecordWithNullIO() throws IOException {
     ReflectData reflectData = ReflectData.AllowNull.get();
@@ -768,4 +930,17 @@ public class TestReflect {
     }
   }
 
+  @AvroAlias(alias="a", space="b")
+  private static class AliasA { }
+  @AvroAlias(alias="a", space="")
+  private static class AliasB { }
+  @AvroAlias(alias="a")
+  private static class AliasC { }  
+  
+  @Test
+  public void testAvroAlias() {
+    check(AliasA.class, "{\"type\":\"record\",\"name\":\"AliasA\",\"namespace\":\"org.apache.avro.reflect.TestReflect$\",\"fields\":[],\"aliases\":[\"b.a\"]}");
+    check(AliasB.class, "{\"type\":\"record\",\"name\":\"AliasB\",\"namespace\":\"org.apache.avro.reflect.TestReflect$\",\"fields\":[],\"aliases\":[\"a\"]}");
+    check(AliasC.class, "{\"type\":\"record\",\"name\":\"AliasC\",\"namespace\":\"org.apache.avro.reflect.TestReflect$\",\"fields\":[],\"aliases\":[\"a\"]}");
   
+  }
 }



Mime
View raw message