avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cutt...@apache.org
Subject svn commit: r810638 - in /hadoop/avro/trunk: ./ src/java/org/apache/avro/generic/ src/java/org/apache/avro/io/ src/java/org/apache/avro/reflect/ src/java/org/apache/avro/specific/ src/java/org/apache/avro/util/ src/test/java/org/apache/avro/
Date Wed, 02 Sep 2009 18:10:04 GMT
Author: cutting
Date: Wed Sep  2 18:10:02 2009
New Revision: 810638

URL: http://svn.apache.org/viewvc?rev=810638&view=rev
Log:
AVRO-110, AVRO-41.  Implement Comparable in generic and specific.  Also convert GenericData and ReflectData to singletons.

Added:
    hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericContainer.java
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificData.java
Modified:
    hadoop/avro/trunk/CHANGES.txt
    hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericArray.java
    hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericData.java
    hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java
    hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumWriter.java
    hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericRecord.java
    hadoop/avro/trunk/src/java/org/apache/avro/generic/package.html
    hadoop/avro/trunk/src/java/org/apache/avro/io/BinaryData.java
    hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectData.java
    hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumWriter.java
    hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectRequestor.java
    hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectResponder.java
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificExceptionBase.java
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecord.java
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecordBase.java
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRequestor.java
    hadoop/avro/trunk/src/java/org/apache/avro/util/Utf8.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/RandomData.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/TestCompare.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/TestDataFileReflect.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/TestReflect.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java

Modified: hadoop/avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/CHANGES.txt?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/CHANGES.txt (original)
+++ hadoop/avro/trunk/CHANGES.txt Wed Sep  2 18:10:02 2009
@@ -4,6 +4,24 @@
 
   INCOMPATIBLE CHANGES
 
+    AVRO-110. GenericData and ReflectData have been converted to use a
+    singleton pattern.  Calls to static methods on these classes must
+    be replaced with calls on the singleton instance. (cutting)
+
+    AVRO-41. GenericArray's constructor now requires a Schema, so that
+    it may implement Comparable consistently with AVRO-108. (cutting)
+
+    AVRO-41. Several GenericDatumWriter methods (instanceOf(),
+    isRecord(), etc.) have been moved to GenericData, where they can
+    better be shared with comparators.  Applications which subclassed
+    GenericDatumWriter overriding these methods must now instead
+    subclass GenericData and pass their subclass to
+    GenericDatumWriter. (cutting)
+
+    AVRO-41. SpecificRecord's schema() method has been renamed
+    getSchema(), since it now implements the new GenericContainer
+    interface shared with GenericRecord. (cutting)
+
   NEW FEATURES
 
     AVRO-50. Implmenent JSON data codec in Java. (Thiruvalluvan
@@ -20,6 +38,10 @@
     AVRO-108.  Add Java implementation of binary comparator.
     (cutting)
 
+    AVRO-41. Java generic and specific data instances now implement
+    Comparable.  The implementation is consistent with the binary
+    comparator added in AVRO-108. (cutting)
+
   IMPROVEMENTS
 
     AVRO-71.  C++: make deserializer more generic.  (Scott Banachowski

Modified: hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericArray.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericArray.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericArray.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericArray.java Wed Sep  2 18:10:02 2009
@@ -19,7 +19,7 @@
 
 
 /** An array of objects. */
-public interface GenericArray<T> extends Iterable<T> {
+public interface GenericArray<T> extends Iterable<T>, GenericContainer {
   /** The number of elements contained in this array. */
   long size();
 

Added: hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericContainer.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericContainer.java?rev=810638&view=auto
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericContainer.java (added)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericContainer.java Wed Sep  2 18:10:02 2009
@@ -0,0 +1,27 @@
+/**
+ * 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.generic;
+
+import org.apache.avro.Schema;
+
+/** Contains data of other types. */
+public interface GenericContainer {
+  /** The schema of this instance. */
+  Schema getSchema();
+}
+

Modified: hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericData.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericData.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericData.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericData.java Wed Sep  2 18:10:02 2009
@@ -24,37 +24,54 @@
 import java.util.Arrays;
 import java.util.Map;
 
+import org.apache.avro.AvroRuntimeException;
 import org.apache.avro.AvroTypeException;
 import org.apache.avro.Schema;
 import org.apache.avro.Schema.Field;
 import org.apache.avro.Schema.Type;
 import org.apache.avro.util.Utf8;
+import org.apache.avro.io.BinaryData;
 
 /** Utilities for generic Java data. */
 public class GenericData {
-  private GenericData() {}
+
+  private static final GenericData INSTANCE = new GenericData();
+  
+  /** Return the singleton instance. */
+  public static GenericData get() { return INSTANCE; }
+
+  protected GenericData() {}
   
   /** Default implementation of {@link GenericRecord}. */
+  @SuppressWarnings(value="unchecked")
   public static class Record
-    extends HashMap<String,Object> implements GenericRecord {
+    extends HashMap<String,Object>
+    implements GenericRecord, Comparable<Record> {
     private final Schema schema;
     public Record(Schema schema) {
       super(schema.getFields().size());
       this.schema = schema;
     }
     public Schema getSchema() { return schema; }
+    public int compareTo(Record that) {
+      return GenericData.get().compare(this, that, this.getSchema());
+    }
   }
 
   /** Default implementation of {@link GenericArray}. */
   @SuppressWarnings(value="unchecked")
-  public static class Array<T> implements GenericArray<T> {
+  public static class Array<T>
+    implements GenericArray<T>, Comparable<Array<T>> {
     private static final Object[] EMPTY = new Object[0];
+    private final Schema schema;
     private int size;
     private Object[] elements = EMPTY;
-    public Array(int capacity) {
+    public Array(int capacity, Schema schema) {
+      this.schema = schema;
       if (capacity != 0)
         elements = new Object[capacity];
     }
+    public Schema getSchema() { return schema; }
     public long size() { return size; }
     public void clear() { size = 0; }
     public Iterator<T> iterator() {
@@ -95,9 +112,12 @@
       }
       return !(e1.hasNext() || e2.hasNext());
     }
+    public int compareTo(Array<T> that) {
+      return GenericData.get().compare(this, that, this.getSchema());
+    }
   }
 
-  public static class Fixed implements GenericFixed {
+  public static class Fixed implements GenericFixed, Comparable<Fixed> {
     private byte[] bytes;
 
     public Fixed(Schema schema) { bytes(new byte[schema.getFixedSize()]); }
@@ -117,11 +137,15 @@
     public int hashCode() { return Arrays.hashCode(bytes); }
 
     public String toString() { return Arrays.toString(bytes); }
-  }
 
+    public int compareTo(Fixed that) {
+      return BinaryData.compareBytes(this.bytes, 0, this.bytes.length,
+                                     that.bytes, 0, that.bytes.length);
+    }
+  }
 
   /** Returns true if a Java datum matches a schema. */
-  public static boolean validate(Schema schema, Object datum) {
+  public boolean validate(Schema schema, Object datum) {
     switch (schema.getType()) {
     case RECORD:
       if (!(datum instanceof GenericRecord)) return false;
@@ -167,12 +191,12 @@
   }
 
   /** Renders a Java datum as <a href="http://www.json.org/">JSON</a>. */
-  public static String toString(Object datum) {
+  public String toString(Object datum) {
     StringBuilder buffer = new StringBuilder();
     toString(datum, buffer);
     return buffer.toString();
   }
-  private static void toString(Object datum, StringBuilder buffer) {
+  private void toString(Object datum, StringBuilder buffer) {
     if (datum instanceof GenericRecord) {
       buffer.append("{");
       int count = 0;
@@ -225,7 +249,7 @@
   }
 
   /** Create a schema given an example datum. */
-  public static Schema induce(Object datum) {
+  public Schema induce(Object datum) {
     if (datum instanceof GenericRecord) {
       GenericRecord record = (GenericRecord)datum;
       LinkedHashMap<String,Field> fields = new LinkedHashMap<String,Field>();
@@ -276,5 +300,126 @@
 
     else throw new AvroTypeException("Can't create schema for: "+datum);
   }
+
+  /** Return the index for a datum within a union.  Implemented with {@link
+   * #instanceOf(Schema,Object)}.*/
+  public int resolveUnion(Schema union, Object datum) {
+    int i = 0;
+    for (Schema type : union.getTypes()) {
+      if (instanceOf(type, datum))
+        return i;
+      i++;
+    }
+    throw new AvroRuntimeException("Not in union "+union+": "+datum);
+  }
+
+  /** Called by {@link #resolveUnion(Schema,Object)}.  May be overridden for
+      alternate data representations.*/
+  protected boolean instanceOf(Schema schema, Object datum) {
+    switch (schema.getType()) {
+    case RECORD:
+      if (!isRecord(datum)) return false;
+      return (schema.getName() == null) ||
+        schema.getName().equals(getRecordSchema(datum).getName());
+    case ENUM:    return isEnum(datum);
+    case ARRAY:   return isArray(datum);
+    case MAP:     return isMap(datum);
+    case FIXED:   return isFixed(datum);
+    case STRING:  return isString(datum);
+    case BYTES:   return isBytes(datum);
+    case INT:     return datum instanceof Integer;
+    case LONG:    return datum instanceof Long;
+    case FLOAT:   return datum instanceof Float;
+    case DOUBLE:  return datum instanceof Double;
+    case BOOLEAN: return datum instanceof Boolean;
+    case NULL:    return datum == null;
+    default: throw new AvroRuntimeException("Unexpected type: " +schema);
+    }
+  }
+
+  /** Called by the default implementation of {@link #instanceOf}.*/
+  protected boolean isArray(Object datum) {
+    return datum instanceof GenericArray;
+  }
+
+  /** Called by the default implementation of {@link #instanceOf}.*/
+  protected boolean isRecord(Object datum) {
+    return datum instanceof GenericRecord;
+  }
+
+  /** Called to obtain the schema of a record.  By default calls
+   * {GenericRecord#getSchema().  May be overridden for alternate record
+   * representations. */
+  protected Schema getRecordSchema(Object record) {
+    return ((GenericContainer)record).getSchema();
+  }
+
+  /** Called by the default implementation of {@link #instanceOf}.*/
+  protected boolean isEnum(Object datum) {
+    return datum instanceof String;
+  }
+  
+  /** Called by the default implementation of {@link #instanceOf}.*/
+  protected boolean isMap(Object datum) {
+    return (datum instanceof Map) && (!(datum instanceof GenericRecord));
+  }
+  
+  /** Called by the default implementation of {@link #instanceOf}.*/
+  protected boolean isFixed(Object datum) {
+    return datum instanceof GenericFixed;
+  }
+
+  /** Called by the default implementation of {@link #instanceOf}.*/
+  protected boolean isString(Object datum) {
+    return datum instanceof Utf8;
+  }
+
+  /** Called by the default implementation of {@link #instanceOf}.*/
+  protected boolean isBytes(Object datum) {
+    return datum instanceof ByteBuffer;
+  }
+
+  /** Compare objects according to their schema.  If equal, return zero.  If
+   * greater-than, return 1, if less than return -1.  Order is consistent with
+   * that of {@link BinaryData#compare(byte[], int, byte[], int, Schema)}.
+   */
+  @SuppressWarnings(value="unchecked")
+  public int compare(Object o1, Object o2, Schema s) {
+    switch (s.getType()) {
+    case RECORD:
+      GenericRecord r1 = (GenericRecord)o1;
+      GenericRecord r2 = (GenericRecord)o2;
+      for (Map.Entry<String, Schema> e : s.getFieldSchemas()) {
+        String field = e.getKey();
+        int compare = compare(r1.get(field), r2.get(field), e.getValue());
+        if (compare != 0) return compare;
+      }
+      return 0;
+    case ENUM:
+      return s.getEnumOrdinal((String)o1) - s.getEnumOrdinal((String)o2);
+    case ARRAY:
+      GenericArray a1 = (GenericArray)o1;
+      GenericArray a2 = (GenericArray)o2;
+      Iterator e1 = a1.iterator();
+      Iterator e2 = a2.iterator();
+      Schema elementType = a1.getSchema().getElementType();
+      while(e1.hasNext() && e2.hasNext()) {
+        int compare = compare(e1.next(), e2.next(), elementType);
+        if (compare != 0) return compare;
+      }
+      return e1.hasNext() ? 1 : (e2.hasNext() ? -1 : 0);
+    case MAP:
+      throw new AvroRuntimeException("Can't compare maps!");
+    case UNION:
+      int i1 = resolveUnion(s, o1);
+      int i2 = resolveUnion(s, o2);
+      return (i1 == i2)
+        ? compare(o1, o2, s.getTypes().get(i1))
+        : i1 - i2;
+    default:
+      return ((Comparable)o1).compareTo(o2);
+    }
+  }
+
 }
 

Modified: hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java Wed Sep  2 18:10:02 2009
@@ -214,7 +214,7 @@
     case ENUM:
       return createEnum(json.getTextValue(), schema);
     case ARRAY:
-      Object array = newArray(old, json.size());
+      Object array = newArray(old, json.size(), schema);
       Schema element = schema.getElementType();
       for (JsonNode node : json)
         addToArray(array, defaultFieldValue(peekArray(array), element, node));
@@ -264,7 +264,7 @@
     Schema expectedType = expected.getElementType();
     long l = in.readArrayStart();
     if (l > 0) {
-      Object array = newArray(old, (int) l);
+      Object array = newArray(old, (int) l, expected);
       do {
         for (long i = 0; i < l; i++) {
           addToArray(array, read(peekArray(array), actualType, expectedType, in));  
@@ -273,7 +273,7 @@
       
       return array;
     } else {
-      return newArray(old, 0);
+      return newArray(old, 0, expected);
     }
   }
 
@@ -368,11 +368,11 @@
    * different array implementation.  By default, this returns a {@link
    * GenericData.Array}.*/
   @SuppressWarnings("unchecked")
-  protected Object newArray(Object old, int size) {
+  protected Object newArray(Object old, int size, Schema schema) {
     if (old instanceof GenericArray) {
       ((GenericArray) old).clear();
       return old;
-    } else return new GenericData.Array(size);
+    } else return new GenericData.Array(size, schema);
   }
 
   /** Called to create new array instances.  Subclasses may override to use a

Modified: hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumWriter.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumWriter.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumWriter.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumWriter.java Wed Sep  2 18:10:02 2009
@@ -23,7 +23,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.apache.avro.AvroRuntimeException;
 import org.apache.avro.AvroTypeException;
 import org.apache.avro.Schema;
 import org.apache.avro.Schema.Field;
@@ -33,11 +32,20 @@
 
 /** {@link DatumWriter} for generic Java objects. */
 public class GenericDatumWriter<D> implements DatumWriter<D> {
+  private final GenericData data;
   private Schema root;
 
-  public GenericDatumWriter() {}
+  public GenericDatumWriter() { this(GenericData.get()); }
+
+  protected GenericDatumWriter(GenericData data) { this.data = data; }
 
   public GenericDatumWriter(Schema root) {
+    this();
+    setSchema(root);
+  }
+
+  protected GenericDatumWriter(Schema root, GenericData data) {
+    this(data);
     setSchema(root);
   }
 
@@ -56,7 +64,7 @@
     case ARRAY:  writeArray(schema, datum, out);  break;
     case MAP:    writeMap(schema, datum, out);    break;
     case UNION:
-      int index = resolveUnion(schema, datum);
+      int index = data.resolveUnion(schema, datum);
       out.writeIndex(index);
       write(schema.getTypes().get(index), datum, out);
       break;
@@ -169,88 +177,12 @@
     out.writeBytes((ByteBuffer)datum);
   }
 
-  private int resolveUnion(Schema union, Object datum) {
-    int i = 0;
-    for (Schema type : union.getTypes()) {
-      if (instanceOf(type, datum))
-        return i;
-      i++;
-    }
-    throw new AvroRuntimeException("Not in union "+union+": "+datum);
-  }
-
-  /** Called to resolve unions.  May be overridden for alternate data
-      representations.*/
-  protected boolean instanceOf(Schema schema, Object datum) {
-    switch (schema.getType()) {
-    case RECORD:
-      if (!isRecord(datum)) return false;
-      return (schema.getName() == null) ||
-        schema.getName().equals(getRecordSchema(datum).getName());
-    case ENUM:    return isEnum(datum);
-    case ARRAY:   return isArray(datum);
-    case MAP:     return isMap(datum);
-    case FIXED:   return isFixed(datum);
-    case STRING:  return isString(datum);
-    case BYTES:   return isBytes(datum);
-    case INT:     return datum instanceof Integer;
-    case LONG:    return datum instanceof Long;
-    case FLOAT:   return datum instanceof Float;
-    case DOUBLE:  return datum instanceof Double;
-    case BOOLEAN: return datum instanceof Boolean;
-    case NULL:    return datum == null;
-    default: throw new AvroRuntimeException("Unexpected type: " +schema);
-    }
-  }
-
-  /** Called to obtain the schema of a record.  By default calls
-   * {GenericRecord#getSchema().  May be overridden for alternate record
-   * representations. */
-  protected Schema getRecordSchema(Object record) {
-    return ((GenericRecord)record).getSchema();
-  }
-
   /** Called to write a fixed value.  May be overridden for alternate fixed
    * representations.*/
   protected void writeFixed(Schema schema, Object datum, Encoder out)
     throws IOException {
     out.writeFixed(((GenericFixed)datum).bytes(), 0, schema.getFixedSize());
   }
-
-  /** Called by the default implementation of {@link #instanceOf}.*/
-  protected boolean isArray(Object datum) {
-    return datum instanceof GenericArray;
-  }
-
-  /** Called by the default implementation of {@link #instanceOf}.*/
-  protected boolean isRecord(Object datum) {
-    return datum instanceof GenericRecord;
-  }
-
-  /** Called by the default implementation of {@link #instanceOf}.*/
-  protected boolean isEnum(Object datum) {
-    return datum instanceof String;
-  }
-  
-  /** Called by the default implementation of {@link #instanceOf}.*/
-  protected boolean isMap(Object datum) {
-    return (datum instanceof Map) && (!(datum instanceof GenericRecord));
-  }
-  
-  /** Called by the default implementation of {@link #instanceOf}.*/
-  protected boolean isFixed(Object datum) {
-    return datum instanceof GenericFixed;
-  }
-
-  /** Called by the default implementation of {@link #instanceOf}.*/
-  protected boolean isString(Object datum) {
-    return datum instanceof Utf8;
-  }
-
-  /** Called by the default implementation of {@link #instanceOf}.*/
-  protected boolean isBytes(Object datum) {
-    return datum instanceof ByteBuffer;
-  }
   
   private void error(Schema schema, Object datum) {
     throw new AvroTypeException("Not a "+schema+": "+datum);

Modified: hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericRecord.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericRecord.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericRecord.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericRecord.java Wed Sep  2 18:10:02 2009
@@ -19,11 +19,6 @@
 
 import java.util.Map;
 
-import org.apache.avro.Schema;
-
 /** A set of fields, each a name/value pair.*/
-public interface GenericRecord extends Map<String,Object> {
-  /** The schema of this instance. */
-  Schema getSchema();
+public interface GenericRecord extends Map<String,Object>, GenericContainer {
 }
-

Modified: hadoop/avro/trunk/src/java/org/apache/avro/generic/package.html
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/package.html?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/package.html (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/package.html Wed Sep  2 18:10:02 2009
@@ -27,6 +27,7 @@
 <li>Schema enums are implemented as {@link java.lang.String}.
 <li>Schema arrays are implemented as {@link org.apache.avro.generic.GenericArray}.
 <li>Schema maps are implemented as {@link java.util.Map}.
+<li>Schema fixed are implemented as {@link org.apache.avro.generic.GenericFixed}.
 <li>Schema strings are implemented as {@link org.apache.avro.util.Utf8}.
 <li>Schema bytes are implemented as {@link java.nio.ByteBuffer}.
 <li>Schema ints are implemented as {@link java.lang.Integer}.

Modified: hadoop/avro/trunk/src/java/org/apache/avro/io/BinaryData.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/io/BinaryData.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/io/BinaryData.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/io/BinaryData.java Wed Sep  2 18:10:02 2009
@@ -31,7 +31,8 @@
   private static final int LT = -2;
 
   /** Compare binary encoded data.  If equal, return zero.  If greater-than,
-   * return 1, if less than return -1. */
+   * return 1, if less than return -1. Order is consistent with that of {@link
+   * org.apache.avro.generic.GenericData#compare(Object, Object, Schema)}.*/
   public static int compare(byte[] b1, int s1,
                             byte[] b2, int s2,
                             Schema schema) {

Modified: hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectData.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectData.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectData.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectData.java Wed Sep  2 18:10:02 2009
@@ -36,6 +36,7 @@
 import org.apache.avro.Schema;
 import org.apache.avro.Protocol.Message;
 import org.apache.avro.Schema.Type;
+import org.apache.avro.generic.GenericData;
 import org.apache.avro.generic.GenericArray;
 import org.apache.avro.generic.GenericFixed;
 import org.apache.avro.ipc.AvroRemoteException;
@@ -45,26 +46,50 @@
 import com.thoughtworks.paranamer.Paranamer;
 
 /** Utilities to use existing Java classes and interfaces via reflection. */
-public class ReflectData {
+public class ReflectData extends GenericData {
   
-  /** Create a {@link ReflectData} instance that permits record fields to be
-   * null.  The schema generated for each field is a union of its declared type
-   * and null. */
-  public static ReflectData newNullAllowingInstance() {
-    return new ReflectData() {
-      @Override
-        protected Schema createFieldSchema(Field field,
-                                           Map<String, Schema> names) {
-        Schema schema = super.createFieldSchema(field, names);
-        return Schema.createUnion(Arrays.asList(new Schema[] { schema,
+  /** {@link ReflectData} implementation that permits null field values.  The
+   * schema generated for each field is a union of its declared type and
+   * null. */
+  public static class AllowNull extends ReflectData {
+
+    private static final AllowNull INSTANCE = new AllowNull();
+
+    /** Return the singleton instance. */
+    public static AllowNull get() { return INSTANCE; }
+
+    protected Schema createFieldSchema(Field field, Map<String, Schema> names) {
+      Schema schema = super.createFieldSchema(field, names);
+      return Schema.createUnion(Arrays.asList(new Schema[] {
+            schema,
             Schema.create(Schema.Type.NULL) }));
-      }
-    };
+    }
   }
   
-  public ReflectData() {}
+  private static final ReflectData INSTANCE = new ReflectData();
+
+  protected ReflectData() {}
   
+  /** Return the singleton instance. */
+  public static ReflectData get() { return INSTANCE; }
+
+  @Override
+  protected boolean isRecord(Object datum) {
+    return getSchema(datum.getClass()).getType() == Type.RECORD;
+  }
+
+  @Override
+  protected Schema getRecordSchema(Object record) {
+    return getSchema(record.getClass());
+  }
+
+  @Override
+  protected boolean isEnum(Object datum) {
+    return datum instanceof Enum;
+  }
+
   /** Returns true if an object matches a schema. */
+  @Override
   public boolean validate(Schema schema, Object datum) {
     switch (schema.getType()) {
     case RECORD:

Modified: hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumWriter.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumWriter.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumWriter.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumWriter.java Wed Sep  2 18:10:02 2009
@@ -21,7 +21,6 @@
 
 import org.apache.avro.AvroRuntimeException;
 import org.apache.avro.Schema;
-import org.apache.avro.Schema.Type;
 import org.apache.avro.generic.GenericDatumWriter;
 import org.apache.avro.io.Encoder;
 
@@ -30,23 +29,20 @@
  * via Java reflection.
  */
 public class ReflectDatumWriter extends GenericDatumWriter<Object> {
-  private final ReflectData reflectData;
-  
   public ReflectDatumWriter() {
-    this(new ReflectData());
+    this(ReflectData.get());
   }
 
   public ReflectDatumWriter(Schema root) {
-    this(root, new ReflectData());
+    this(root, ReflectData.get());
   }
 
   public ReflectDatumWriter(Schema root, ReflectData reflectData) {
-    super(root);
-    this.reflectData = reflectData;
+    super(root, reflectData);
   }
   
   public ReflectDatumWriter(ReflectData reflectData) {
-    this.reflectData = reflectData;
+    super(reflectData);
   }
   
   protected Object getField(Object record, String name, int position) {
@@ -66,15 +62,5 @@
     return datum instanceof Enum;
   }
 
-  @Override
-  protected boolean isRecord(Object datum) {
-    return reflectData.getSchema(datum.getClass()).getType() == Type.RECORD;
-  }
-
-  @Override
-  protected Schema getRecordSchema(Object record) {
-    return reflectData.getSchema(record.getClass());
-  }
-
 }
 

Modified: hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectRequestor.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectRequestor.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectRequestor.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectRequestor.java Wed Sep  2 18:10:02 2009
@@ -40,12 +40,12 @@
   
   public ReflectRequestor(Class<?> iface, Transceiver transceiver)
     throws IOException {
-    this(iface, transceiver, new ReflectData());
+    this(iface, transceiver, ReflectData.get());
   }
 
   protected ReflectRequestor(Protocol protocol, Transceiver transceiver)
     throws IOException {
-    this(protocol, transceiver, new ReflectData());
+    this(protocol, transceiver, ReflectData.get());
   }
 
   public ReflectRequestor(Class<?> iface, Transceiver transceiver, ReflectData reflectData)
@@ -92,7 +92,7 @@
   /** Create a proxy instance whose methods invoke RPCs. */
   public static Object getClient(Class<?> iface, Transceiver transciever)
     throws IOException {
-    return getClient(iface, transciever, new ReflectData());
+    return getClient(iface, transciever, ReflectData.get());
   }
 
   /** Create a proxy instance whose methods invoke RPCs. */

Modified: hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectResponder.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectResponder.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectResponder.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectResponder.java Wed Sep  2 18:10:02 2009
@@ -42,7 +42,7 @@
   protected String packageName;
 
   public ReflectResponder(Class iface, Object impl) {
-    this(iface, impl, new ReflectData());
+    this(iface, impl, ReflectData.get());
   }
   
   public ReflectResponder(Class iface, Object impl, ReflectData reflectData) {

Modified: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java Wed Sep  2 18:10:02 2009
@@ -154,7 +154,7 @@
         line(d+1,"public "+unbox(field.getValue(),fieldName)+" "+fieldName+";");
       }
       // schema method
-      line(d+1, "public Schema schema() { return _SCHEMA; }");
+      line(d+1, "public Schema getSchema() { return _SCHEMA; }");
       // get method
       line(d+1, "public Object get(int _field) {");
       line(d+2, "switch (_field) {");

Added: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificData.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificData.java?rev=810638&view=auto
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificData.java (added)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificData.java Wed Sep  2 18:10:02 2009
@@ -0,0 +1,67 @@
+/**
+ * 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.specific;
+
+import java.util.Map;
+
+import org.apache.avro.Schema;
+import org.apache.avro.reflect.ReflectData;
+
+/** Utilities for generated Java classes and interfaces. */
+public class SpecificData extends ReflectData {
+
+  private static final SpecificData INSTANCE = new SpecificData();
+
+  protected SpecificData() {}
+  
+  /** Return the singleton instance. */
+  public static SpecificData get() { return INSTANCE; }
+
+  @Override
+  protected boolean isRecord(Object datum) {
+    return datum instanceof SpecificRecord;
+  }
+
+  @Override
+  protected Schema getRecordSchema(Object record) {
+    return ((SpecificRecord)record).getSchema();
+  }
+
+  @Override
+  public int compare(Object o1, Object o2, Schema s) {
+    switch (s.getType()) {
+    case RECORD:
+      SpecificRecord r1 = (SpecificRecord)o1;
+      SpecificRecord r2 = (SpecificRecord)o2;
+      int i = 0;
+      for (Map.Entry<String, Schema> e : s.getFieldSchemas()) {
+        int compare = compare(r1.get(i), r2.get(i), e.getValue());
+        if (compare != 0) return compare;
+        i++;
+      }
+      return 0;
+    case ENUM:
+      return ((Enum)o1).ordinal() - ((Enum)o2).ordinal();
+    default:
+      return super.compare(o1, o2, s);
+    }
+  }
+
+
+}
+

Modified: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificExceptionBase.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificExceptionBase.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificExceptionBase.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificExceptionBase.java Wed Sep  2 18:10:02 2009
@@ -25,7 +25,7 @@
 public abstract class SpecificExceptionBase extends AvroRemoteException
   implements SpecificRecord {
 
-  public abstract Schema schema();
+  public abstract Schema getSchema();
   public abstract Object get(int field);
   public abstract void set(int field, Object value);
 

Modified: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecord.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecord.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecord.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecord.java Wed Sep  2 18:10:02 2009
@@ -17,12 +17,11 @@
  */
 package org.apache.avro.specific;
 
-import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericContainer;
 
 /** Implemented by generated record classes. Permits efficient access to
  * fields.*/
-public interface SpecificRecord {
-  Schema schema();
+public interface SpecificRecord extends GenericContainer {
   Object get(int field);
   void set(int field, Object value);
 }

Modified: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecordBase.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecordBase.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecordBase.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRecordBase.java Wed Sep  2 18:10:02 2009
@@ -20,8 +20,10 @@
 import org.apache.avro.Schema;
 
 /** Base class for generated record classes. */
-public abstract class SpecificRecordBase implements SpecificRecord {
-  public abstract Schema schema();
+public abstract class SpecificRecordBase
+  implements SpecificRecord, Comparable<SpecificRecord> {
+
+  public abstract Schema getSchema();
   public abstract Object get(int field);
   public abstract void set(int field, Object value);
 
@@ -34,9 +36,9 @@
     if (!(o instanceof SpecificRecord)) return false;
 
     SpecificRecord r2 = (SpecificRecord)o;
-    if (!r1.schema().equals(r2.schema())) return false;
+    if (!r1.getSchema().equals(r2.getSchema())) return false;
 
-    int end = r1.schema().getFields().size();
+    int end = r1.getSchema().getFields().size();
     for (int i = 0; i < end; i++) {
       Object v1 = r1.get(i);
       Object v2 = r2.get(i);
@@ -55,11 +57,16 @@
 
   static int hashCode(SpecificRecord r) {
     int result = 0;
-    int end = r.schema().getFields().size();
+    int end = r.getSchema().getFields().size();
     for (int i = 0; i < end; i++)
       result += r.get(i).hashCode();
     return result;
   }
 
+  @SuppressWarnings(value="unchecked")
+  public int compareTo(SpecificRecord that) {
+    return SpecificData.get().compare(this, that, this.getSchema());
+  }
+
 }
 

Modified: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRequestor.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRequestor.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRequestor.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificRequestor.java Wed Sep  2 18:10:02 2009
@@ -26,7 +26,6 @@
 import org.apache.avro.io.DatumReader;
 import org.apache.avro.io.DatumWriter;
 import org.apache.avro.ipc.Transceiver;
-import org.apache.avro.reflect.ReflectData;
 import org.apache.avro.reflect.ReflectRequestor;
 
 /** {@link org.apache.avro.ipc.Requestor Requestor} for generated interfaces. */
@@ -34,12 +33,13 @@
   
   public SpecificRequestor(Class<?> iface, Transceiver transceiver)
     throws IOException {
-    this(iface, transceiver, new ReflectData());
+    this(iface, transceiver, SpecificData.get());
   }
 
-  public SpecificRequestor(Class<?> iface, Transceiver transceiver, ReflectData reflectData)
+  public SpecificRequestor(Class<?> iface, Transceiver transceiver,
+                           SpecificData specificData)
     throws IOException {
-    this(reflectData.getProtocol(iface), transceiver);
+    this(specificData.getProtocol(iface), transceiver);
   }
   
   private SpecificRequestor(Protocol protocol, Transceiver transceiver)
@@ -58,13 +58,14 @@
   /** Create a proxy instance whose methods invoke RPCs. */
   public static Object getClient(Class<?> iface, Transceiver transciever)
     throws IOException {
-    return getClient(iface, transciever, new ReflectData());
+    return getClient(iface, transciever, SpecificData.get());
   }
 
   /** Create a proxy instance whose methods invoke RPCs. */
-  public static Object getClient(Class<?> iface, Transceiver transciever, ReflectData reflectData)
+  public static Object getClient(Class<?> iface, Transceiver transciever,
+                                 SpecificData specificData)
     throws IOException {
-    Protocol protocol = reflectData.getProtocol(iface);
+    Protocol protocol = specificData.getProtocol(iface);
     return Proxy.newProxyInstance(iface.getClassLoader(),
                                   new Class[] { iface },
                                   new SpecificRequestor(protocol, transciever));

Modified: hadoop/avro/trunk/src/java/org/apache/avro/util/Utf8.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/util/Utf8.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/util/Utf8.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/util/Utf8.java Wed Sep  2 18:10:02 2009
@@ -19,8 +19,10 @@
 
 import java.io.UnsupportedEncodingException;
 
+import org.apache.avro.io.BinaryData;
+
 /** A Utf8 string. */
-public class Utf8 {
+public class Utf8 implements Comparable<Utf8> {
   private static final byte[] EMPTY = new byte[0];
 
   byte[] bytes = EMPTY;
@@ -77,6 +79,9 @@
     return hash;
   }
 
-}
-
+  public int compareTo(Utf8 that) {
+    return BinaryData.compareBytes(this.bytes, 0, this.length,
+                                   that.bytes, 0, that.length);
+  }
 
+}

Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/RandomData.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/RandomData.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/RandomData.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/RandomData.java Wed Sep  2 18:10:02 2009
@@ -71,7 +71,8 @@
       return symbols.get(random.nextInt(symbols.size()));
     case ARRAY:
       int length = (random.nextInt(5)+2)-d;
-      GenericArray<Object> array = new GenericData.Array(length<=0?0:length);
+      GenericArray<Object> array =
+        new GenericData.Array(length<=0?0:length, schema);
       for (int i = 0; i < length; i++)
         array.add(generate(schema.getElementType(), random, d+1));
       return array;

Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/TestCompare.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/TestCompare.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/TestCompare.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/TestCompare.java Wed Sep  2 18:10:02 2009
@@ -30,18 +30,22 @@
 import org.apache.avro.generic.GenericArray;
 import org.apache.avro.generic.GenericData;
 import org.apache.avro.generic.GenericDatumWriter;
+import org.apache.avro.specific.SpecificData;
+import org.apache.avro.specific.SpecificDatumWriter;
 import org.apache.avro.io.BinaryData;
 import org.apache.avro.io.DatumWriter;
 import org.apache.avro.io.Encoder;
 import org.apache.avro.io.BinaryEncoder;
 import org.apache.avro.util.Utf8;
 
+import org.apache.avro.test.Simple;
+
 public class TestCompare {
 
   @Test
   public void testNull() throws Exception {
     Schema schema = Schema.parse("\"null\"");
-    byte[] b = render(null, schema);
+    byte[] b = render(null, schema, new GenericDatumWriter<Object>());
     assertEquals(0, BinaryData.compare(b, 0, b, 0, schema));
   }
 
@@ -95,15 +99,16 @@
 
   @Test
   public void testArray() throws Exception {
-    GenericArray<Long> a1 = new GenericData.Array<Long>(1);
+    String json = "{\"type\":\"array\", \"items\": \"long\"}";
+    Schema schema = Schema.parse(json);
+    GenericArray<Long> a1 = new GenericData.Array<Long>(1, schema);
     a1.add(1L);
-    GenericArray<Long> a2 = new GenericData.Array<Long>(1);
+    GenericArray<Long> a2 = new GenericData.Array<Long>(1, schema);
     a2.add(1L);
     a2.add(0L);
-    check("{\"type\":\"array\", \"items\": \"long\"}", a1, a2);
+    check(json, a1, a2);
   }
 
-
   @Test
   public void testRecord() throws Exception {
     String recordJson = "{\"type\":\"record\", \"name\":\"Test\", \"fields\":"
@@ -133,25 +138,70 @@
 
   @Test
   public void testUnion() throws Exception {
-    check("[\"string\", \"long\"]", new Utf8("a"), new Utf8("b"));
-    check("[\"string\", \"long\"]", new Long(1), new Long(2));
-    check("[\"string\", \"long\"]", new Utf8("a"), new Long(1));
+    check("[\"string\", \"long\"]", new Utf8("a"), new Utf8("b"), false);
+    check("[\"string\", \"long\"]", new Long(1), new Long(2), false);
+    check("[\"string\", \"long\"]", new Utf8("a"), new Long(1), false);
   }
 
+  @Test
+  public void testSpecificRecord() throws Exception {
+    Simple.TestRecord s1 = new Simple.TestRecord();
+    Simple.TestRecord s2 = new Simple.TestRecord();
+    s1.name = new Utf8("foo");
+    s2.name = new Utf8("foo");
+    s1.kind = Simple.Kind.BAR;
+    s2.kind = Simple.Kind.BAR;
+    s1.hash = new Simple.MD5();
+    s1.hash.bytes(new byte[] {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5});
+    s2.hash = new Simple.MD5();
+    s2.hash.bytes(new byte[] {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,6});
+    check(Simple.TestRecord._SCHEMA, s1, s2, true,
+          new SpecificDatumWriter(Simple.TestRecord._SCHEMA),
+          SpecificData.get());
+  }  
+
   private static void check(String schemaJson, Object o1, Object o2)
     throws Exception {
-    Schema schema = Schema.parse(schemaJson);
-    byte[] b1 = render(o1, schema);
-    byte[] b2 = render(o2, schema);
+    check(schemaJson, o1, o2, true);
+  }
+
+  private static void check(String schemaJson, Object o1, Object o2,
+                            boolean comparable)
+    throws Exception {
+    check(Schema.parse(schemaJson), o1, o2, comparable,
+          new GenericDatumWriter<Object>(), GenericData.get());
+  }
+
+  private static void check(Schema schema, Object o1, Object o2,
+                            boolean comparable,
+                            DatumWriter<Object> writer,
+                            GenericData comparator)
+    throws Exception {
+
+    byte[] b1 = render(o1, schema, writer);
+    byte[] b2 = render(o2, schema, writer);
     assertEquals(-1, BinaryData.compare(b1, 0, b2, 0, schema));
     assertEquals(1, BinaryData.compare(b2, 0, b1, 0, schema));
     assertEquals(0, BinaryData.compare(b1, 0, b1, 0, schema));
     assertEquals(0, BinaryData.compare(b2, 0, b2, 0, schema));
+
+    assertEquals(-1, compare(o1, o2, schema, comparable, comparator));
+    assertEquals(1, compare(o2, o1, schema, comparable, comparator));
+    assertEquals(0, compare(o1, o1, schema, comparable, comparator));
+    assertEquals(0, compare(o2, o2, schema, comparable, comparator));
+  }
+
+  @SuppressWarnings(value="unchecked")
+  private static int compare(Object o1, Object o2, Schema schema,
+                             boolean comparable, GenericData comparator) {
+    return comparable
+      ? ((Comparable)o1).compareTo(o2)
+      : comparator.compare(o1, o2, schema);
   }
 
-  private static byte[] render(Object datum, Schema schema)
+  private static byte[] render(Object datum, Schema schema,
+                               DatumWriter<Object> writer)
     throws IOException {
-    DatumWriter<Object> writer = new GenericDatumWriter<Object>();
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     writer.setSchema(schema);
     writer.write(datum, new BinaryEncoder(out));

Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/TestDataFileReflect.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/TestDataFileReflect.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/TestDataFileReflect.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/TestDataFileReflect.java Wed Sep  2 18:10:02 2009
@@ -47,7 +47,7 @@
   public void testMultiReflectWithUnionBeforeWriting() throws IOException {
     FileOutputStream fos = new FileOutputStream(FILE);
 
-    ReflectData reflectData = new ReflectData();
+    ReflectData reflectData = ReflectData.get();
     List<Schema> schemas = Arrays.asList(new Schema[] {
         reflectData.getSchema(FooRecord.class),
         reflectData.getSchema(BarRecord.class) });
@@ -83,7 +83,7 @@
   public void testMultiReflectWithUntionAfterWriting() throws IOException {
     FileOutputStream fos = new FileOutputStream(FILE);
 
-    ReflectData reflectData = new ReflectData();
+    ReflectData reflectData = ReflectData.get();
     List<Schema> schemas = new ArrayList<Schema>();
     schemas.add(reflectData.getSchema(FooRecord.class));
     Schema union = Schema.createUnion(schemas);
@@ -129,7 +129,7 @@
   public void testNull() throws IOException {
     FileOutputStream fos = new FileOutputStream(FILE);
 
-    ReflectData reflectData = ReflectData.newNullAllowingInstance();
+    ReflectData reflectData = ReflectData.AllowNull.get();
     Schema schema = reflectData.getSchema(BarRecord.class);
     DataFileWriter<Object> writer = new DataFileWriter<Object>(schema, fos,
         new ReflectDatumWriter(schema, reflectData));

Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/TestReflect.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/TestReflect.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/TestReflect.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/TestReflect.java Wed Sep  2 18:10:02 2009
@@ -53,17 +53,17 @@
   @Test
   public void testSchema() throws IOException {
     assertEquals(PROTOCOL.getTypes().get("TestRecord"),
-                 new ReflectData().getSchema(TestRecord.class));
+                 ReflectData.get().getSchema(TestRecord.class));
   }
 
   @Test
   public void testProtocol() throws IOException {
-    assertEquals(PROTOCOL, new ReflectData().getProtocol(Simple.class));
+    assertEquals(PROTOCOL, ReflectData.get().getProtocol(Simple.class));
   }
 
   @Test
   public void testRecord() throws IOException {
-    Schema schm = new ReflectData().getSchema(SampleRecord.class);
+    Schema schm = ReflectData.get().getSchema(SampleRecord.class);
     String prefix = getPrefix(SampleRecord.class);
     ReflectDatumWriter writer = new ReflectDatumWriter(schm);
     ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -80,7 +80,7 @@
 
   @Test
   public void testRecordWithNull() throws IOException {
-    ReflectData reflectData = ReflectData.newNullAllowingInstance();
+    ReflectData reflectData = ReflectData.AllowNull.get();
     Schema schm = reflectData.getSchema(AnotherSampleRecord.class);
     String prefix = getPrefix(AnotherSampleRecord.class);
     ReflectDatumWriter writer = new ReflectDatumWriter(schm);

Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java?rev=810638&r1=810637&r2=810638&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java Wed Sep  2 18:10:02 2009
@@ -89,9 +89,11 @@
 
   @Test
   public void testArray() throws Exception {
-    GenericArray<Long> array = new GenericData.Array<Long>(1);
+    String json = "{\"type\":\"array\", \"items\": \"long\"}";
+    Schema schema = Schema.parse(json);
+    GenericArray<Long> array = new GenericData.Array<Long>(1, schema);
     array.add(1L);
-    check("{\"type\":\"array\", \"items\": \"long\"}", "[1]", array);
+    check(json, "[1]", array);
   }
 
   @Test
@@ -194,15 +196,15 @@
     Schema schema = Schema.parse(jsonSchema);
     //System.out.println(schema);
     for (Object datum : new RandomData(schema, COUNT)) {
-      //System.out.println(GenericData.toString(datum));
+      //System.out.println(GenericData.get().toString(datum));
 
       if (induce) {
-        Schema induced = GenericData.induce(datum);
+        Schema induced = GenericData.get().induce(datum);
         assertEquals("Induced schema does not match.", schema, induced);
       }
         
       assertTrue("Datum does not validate against schema "+datum,
-                 GenericData.validate(schema, datum));
+                 GenericData.get().validate(schema, datum));
 
       checkBinary(schema, datum,
                   new GenericDatumWriter<Object>(),



Mime
View raw message