You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by cu...@apache.org on 2012/05/17 23:12:44 UTC
svn commit: r1339864 - in /avro/trunk: ./
lang/java/avro/src/main/java/org/apache/avro/reflect/
lang/java/avro/src/test/java/org/apache/avro/
lang/java/avro/src/test/java/org/apache/avro/reflect/
lang/java/avro/src/test/java/org/apache/avro/specific/ l...
Author: cutting
Date: Thu May 17 21:12:43 2012
New Revision: 1339864
URL: http://svn.apache.org/viewvc?rev=1339864&view=rev
Log:
AVRO-1046. Java: Fix ReflectDatumReader to be able to read generic and specific arrays.
Added:
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java (with props)
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflectDatumReader.java (with props)
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificDatumReader.java (with props)
avro/trunk/lang/java/avro/src/test/resources/
avro/trunk/lang/java/avro/src/test/resources/FooBarSpecificRecord.avsc
Modified:
avro/trunk/CHANGES.txt
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectDatumReader.java
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestReflect.java
Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1339864&r1=1339863&r2=1339864&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Thu May 17 21:12:43 2012
@@ -65,6 +65,9 @@ Avro 1.7.0 (unreleased)
backing array. Also fix reflection to correctly read ByteBuffer
fields. (cutting)
+ AVRO-1046. Java: Fix ReflectDatumReader to be able to read generic
+ or specific arrays. (cutting)
+
Avro 1.6.3 (5 March 2012)
AVRO-1077. Missing 'inline' for union set function. (thiru)
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=1339864&r1=1339863&r2=1339864&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 Thu May 17 21:12:43 2012
@@ -268,6 +268,7 @@ public class ReflectData extends Specifi
return result;
}
Schema result = Schema.createArray(createSchema(component, names));
+ result.addProp(CLASS_PROP, c.getName());
setElement(result, component);
return result;
}
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=1339864&r1=1339863&r2=1339864&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 Thu May 17 21:12:43 2012
@@ -59,9 +59,16 @@ public class ReflectDatumReader<T> exten
@Override
@SuppressWarnings(value="unchecked")
protected Object newArray(Object old, int size, Schema schema) {
- ReflectData data = ReflectData.get();
- Class collectionClass = ReflectData.getClassProp(schema, ReflectData.CLASS_PROP);
- if (collectionClass != null) {
+ Class collectionClass =
+ ReflectData.getClassProp(schema, ReflectData.CLASS_PROP);
+ Class elementClass =
+ ReflectData.getClassProp(schema, ReflectData.ELEMENT_PROP);
+
+ if (collectionClass == null && elementClass == null)
+ return super.newArray(old, size, schema); // use specific/generic
+
+ ReflectData data = (ReflectData)getData();
+ if (collectionClass != null && !collectionClass.isArray()) {
if (old instanceof Collection) {
((Collection)old).clear();
return old;
@@ -70,7 +77,7 @@ public class ReflectDatumReader<T> exten
return new ArrayList();
return data.newInstance(collectionClass, schema);
}
- Class elementClass = ReflectData.getClassProp(schema, ReflectData.ELEMENT_PROP);
+
if (elementClass == null)
elementClass = data.getClass(schema.getElementType());
return Array.newInstance(elementClass, size);
Added: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java?rev=1339864&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java (added)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java Thu May 17 21:12:43 2012
@@ -0,0 +1,169 @@
+/**
+ * Autogenerated by Avro
+ *
+ * DO NOT EDIT DIRECTLY
+ */
+package org.apache.avro;
+@SuppressWarnings("all")
+public class FooBarSpecificRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
+ public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"FooBarSpecificRecord\",\"namespace\":\"org.apache.avro\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"relatedids\",\"type\":{\"type\":\"array\",\"items\":\"int\"}}]}");
+ @Deprecated public int id;
+ @Deprecated public java.util.List<java.lang.Integer> relatedids;
+ public org.apache.avro.Schema getSchema() { return SCHEMA$; }
+ // Used by DatumWriter. Applications should not call.
+ public java.lang.Object get(int field$) {
+ switch (field$) {
+ case 0: return id;
+ case 1: return relatedids;
+ default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+ }
+ }
+ // Used by DatumReader. Applications should not call.
+ @SuppressWarnings(value="unchecked")
+ public void put(int field$, java.lang.Object value$) {
+ switch (field$) {
+ case 0: id = (java.lang.Integer)value$; break;
+ case 1: relatedids = (java.util.List<java.lang.Integer>)value$; break;
+ default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+ }
+ }
+
+ /**
+ * Gets the value of the 'id' field.
+ */
+ public java.lang.Integer getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the 'id' field.
+ * @param value the value to set.
+ */
+ public void setId(java.lang.Integer value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the 'relatedids' field.
+ */
+ public java.util.List<java.lang.Integer> getRelatedids() {
+ return relatedids;
+ }
+
+ /**
+ * Sets the value of the 'relatedids' field.
+ * @param value the value to set.
+ */
+ public void setRelatedids(java.util.List<java.lang.Integer> value) {
+ this.relatedids = value;
+ }
+
+ /** Creates a new FooBarSpecificRecord RecordBuilder */
+ public static org.apache.avro.FooBarSpecificRecord.Builder newBuilder() {
+ return new org.apache.avro.FooBarSpecificRecord.Builder();
+ }
+
+ /** Creates a new FooBarSpecificRecord RecordBuilder by copying an existing Builder */
+ public static org.apache.avro.FooBarSpecificRecord.Builder newBuilder(org.apache.avro.FooBarSpecificRecord.Builder other) {
+ return new org.apache.avro.FooBarSpecificRecord.Builder(other);
+ }
+
+ /** Creates a new FooBarSpecificRecord RecordBuilder by copying an existing FooBarSpecificRecord instance */
+ public static org.apache.avro.FooBarSpecificRecord.Builder newBuilder(org.apache.avro.FooBarSpecificRecord other) {
+ return new org.apache.avro.FooBarSpecificRecord.Builder(other);
+ }
+
+ /**
+ * RecordBuilder for FooBarSpecificRecord instances.
+ */
+ public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<FooBarSpecificRecord>
+ implements org.apache.avro.data.RecordBuilder<FooBarSpecificRecord> {
+
+ private int id;
+ private java.util.List<java.lang.Integer> relatedids;
+
+ /** Creates a new Builder */
+ private Builder() {
+ super(org.apache.avro.FooBarSpecificRecord.SCHEMA$);
+ }
+
+ /** Creates a Builder by copying an existing Builder */
+ private Builder(org.apache.avro.FooBarSpecificRecord.Builder other) {
+ super(other);
+ }
+
+ /** Creates a Builder by copying an existing FooBarSpecificRecord instance */
+ private Builder(org.apache.avro.FooBarSpecificRecord other) {
+ super(org.apache.avro.FooBarSpecificRecord.SCHEMA$);
+ if (isValidValue(fields()[0], other.id)) {
+ this.id = (java.lang.Integer) data().deepCopy(fields()[0].schema(), other.id);
+ fieldSetFlags()[0] = true;
+ }
+ if (isValidValue(fields()[1], other.relatedids)) {
+ this.relatedids = (java.util.List<java.lang.Integer>) data().deepCopy(fields()[1].schema(), other.relatedids);
+ fieldSetFlags()[1] = true;
+ }
+ }
+
+ /** Gets the value of the 'id' field */
+ public java.lang.Integer getId() {
+ return id;
+ }
+
+ /** Sets the value of the 'id' field */
+ public org.apache.avro.FooBarSpecificRecord.Builder setId(int value) {
+ validate(fields()[0], value);
+ this.id = value;
+ fieldSetFlags()[0] = true;
+ return this;
+ }
+
+ /** Checks whether the 'id' field has been set */
+ public boolean hasId() {
+ return fieldSetFlags()[0];
+ }
+
+ /** Clears the value of the 'id' field */
+ public org.apache.avro.FooBarSpecificRecord.Builder clearId() {
+ fieldSetFlags()[0] = false;
+ return this;
+ }
+
+ /** Gets the value of the 'relatedids' field */
+ public java.util.List<java.lang.Integer> getRelatedids() {
+ return relatedids;
+ }
+
+ /** Sets the value of the 'relatedids' field */
+ public org.apache.avro.FooBarSpecificRecord.Builder setRelatedids(java.util.List<java.lang.Integer> value) {
+ validate(fields()[1], value);
+ this.relatedids = value;
+ fieldSetFlags()[1] = true;
+ return this;
+ }
+
+ /** Checks whether the 'relatedids' field has been set */
+ public boolean hasRelatedids() {
+ return fieldSetFlags()[1];
+ }
+
+ /** Clears the value of the 'relatedids' field */
+ public org.apache.avro.FooBarSpecificRecord.Builder clearRelatedids() {
+ relatedids = null;
+ fieldSetFlags()[1] = false;
+ return this;
+ }
+
+ @Override
+ public FooBarSpecificRecord build() {
+ try {
+ FooBarSpecificRecord record = new FooBarSpecificRecord();
+ record.id = fieldSetFlags()[0] ? this.id : (java.lang.Integer) defaultValue(fields()[0]);
+ record.relatedids = fieldSetFlags()[1] ? this.relatedids : (java.util.List<java.lang.Integer>) defaultValue(fields()[1]);
+ return record;
+ } catch (Exception e) {
+ throw new org.apache.avro.AvroRuntimeException(e);
+ }
+ }
+ }
+}
Propchange: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/FooBarSpecificRecord.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestReflect.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestReflect.java?rev=1339864&r1=1339863&r2=1339864&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestReflect.java (original)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestReflect.java Thu May 17 21:12:43 2012
@@ -145,7 +145,7 @@ public class TestReflect {
@Test public void testArray() throws Exception {
check(R1.class.getDeclaredField("arrayField").getGenericType(),
- "{\"type\":\"array\",\"items\":\"string\"}");
+ "{\"type\":\"array\",\"items\":\"string\",\"java-class\":\"[Ljava.lang.String;\"}");
}
@Test public void testList() throws Exception {
check(R1.class.getDeclaredField("listField").getGenericType(),
Added: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflectDatumReader.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflectDatumReader.java?rev=1339864&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflectDatumReader.java (added)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflectDatumReader.java Thu May 17 21:12:43 2012
@@ -0,0 +1,179 @@
+package org.apache.avro.reflect;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.avro.FooBarSpecificRecord;
+import org.apache.avro.io.Decoder;
+import org.apache.avro.io.DecoderFactory;
+import org.apache.avro.io.Encoder;
+import org.apache.avro.io.EncoderFactory;
+import org.apache.avro.specific.TestSpecificDatumReader;
+import org.junit.Test;
+
+public class TestReflectDatumReader {
+
+ @Test
+ public void testRead_SpecificDataRecord() throws IOException {
+ FooBarSpecificRecord specificRecord = FooBarSpecificRecord.newBuilder().setId(42)
+ .setRelatedids(Arrays.asList(1, 2, 3)).build();
+ byte[] specificRecordBytes = TestSpecificDatumReader.serializeRecord(specificRecord);
+
+ Decoder decoder = DecoderFactory.get().binaryDecoder(specificRecordBytes, null);
+ ReflectDatumReader<FooBarSpecificRecord> reflectDatumReader = new ReflectDatumReader<FooBarSpecificRecord>(
+ FooBarSpecificRecord.class);
+
+ FooBarSpecificRecord deserialized = new FooBarSpecificRecord();
+ reflectDatumReader.read(deserialized, decoder);
+
+ assertEquals(specificRecord, deserialized);
+ }
+
+ private static <T> byte[] serializeWithReflectDatumWriter(T toSerialize, Class<T> toSerializeClass)
+ throws IOException {
+ ReflectDatumWriter<T> datumWriter = new ReflectDatumWriter<T>(toSerializeClass);
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ Encoder encoder = EncoderFactory.get().binaryEncoder(byteArrayOutputStream, null);
+ datumWriter.write(toSerialize, encoder);
+ encoder.flush();
+ return byteArrayOutputStream.toByteArray();
+ }
+
+ @Test
+ public void testRead_PojoWithList() throws IOException {
+ PojoWithList pojoWithList = new PojoWithList();
+ pojoWithList.setId(42);
+ pojoWithList.setRelatedIds(Arrays.asList(1, 2, 3));
+
+ byte[] serializedBytes = serializeWithReflectDatumWriter(pojoWithList, PojoWithList.class);
+
+ Decoder decoder = DecoderFactory.get().binaryDecoder(serializedBytes, null);
+ ReflectDatumReader<PojoWithList> reflectDatumReader = new ReflectDatumReader<PojoWithList>(
+ PojoWithList.class);
+
+ PojoWithList deserialized = new PojoWithList();
+ reflectDatumReader.read(deserialized, decoder);
+
+ assertEquals(pojoWithList, deserialized);
+
+ }
+
+ @Test
+ public void testRead_PojoWithArray() throws IOException {
+ PojoWithArray pojoWithArray = new PojoWithArray();
+ pojoWithArray.setId(42);
+ pojoWithArray.setRelatedIds(new int[] { 1, 2, 3 });
+
+ byte[] serializedBytes = serializeWithReflectDatumWriter(pojoWithArray, PojoWithArray.class);
+
+ Decoder decoder = DecoderFactory.get().binaryDecoder(serializedBytes, null);
+ ReflectDatumReader<PojoWithArray> reflectDatumReader = new ReflectDatumReader<PojoWithArray>(
+ PojoWithArray.class);
+
+ PojoWithArray deserialized = new PojoWithArray();
+ reflectDatumReader.read(deserialized, decoder);
+
+ assertEquals(pojoWithArray, deserialized);
+ }
+
+ public static class PojoWithList {
+ private int id;
+ private List<Integer> relatedIds;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public List<Integer> getRelatedIds() {
+ return relatedIds;
+ }
+
+ public void setRelatedIds(List<Integer> relatedIds) {
+ this.relatedIds = relatedIds;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ result = prime * result + ((relatedIds == null) ? 0 : relatedIds.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PojoWithList other = (PojoWithList) obj;
+ if (id != other.id)
+ return false;
+ if (relatedIds == null) {
+ if (other.relatedIds != null)
+ return false;
+ } else if (!relatedIds.equals(other.relatedIds))
+ return false;
+ return true;
+ }
+ }
+
+ public static class PojoWithArray {
+ private int id;
+ private int[] relatedIds;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int[] getRelatedIds() {
+ return relatedIds;
+ }
+
+ public void setRelatedIds(int[] relatedIds) {
+ this.relatedIds = relatedIds;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ result = prime * result + Arrays.hashCode(relatedIds);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PojoWithArray other = (PojoWithArray) obj;
+ if (id != other.id)
+ return false;
+ if (!Arrays.equals(relatedIds, other.relatedIds))
+ return false;
+ return true;
+ }
+
+ }
+}
Propchange: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflectDatumReader.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificDatumReader.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificDatumReader.java?rev=1339864&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificDatumReader.java (added)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificDatumReader.java Thu May 17 21:12:43 2012
@@ -0,0 +1,47 @@
+package org.apache.avro.specific;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.avro.FooBarSpecificRecord;
+import org.apache.avro.FooBarSpecificRecord.Builder;
+import org.apache.avro.io.Decoder;
+import org.apache.avro.io.DecoderFactory;
+import org.apache.avro.io.Encoder;
+import org.apache.avro.io.EncoderFactory;
+import org.junit.Test;
+
+public class TestSpecificDatumReader {
+
+ public static byte[] serializeRecord(FooBarSpecificRecord fooBarSpecificRecord) throws IOException {
+ SpecificDatumWriter<FooBarSpecificRecord> datumWriter =
+ new SpecificDatumWriter<FooBarSpecificRecord>(FooBarSpecificRecord.SCHEMA$);
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ Encoder encoder = EncoderFactory.get().binaryEncoder(byteArrayOutputStream, null);
+ datumWriter.write(fooBarSpecificRecord, encoder);
+ encoder.flush();
+ return byteArrayOutputStream.toByteArray();
+ }
+
+ @Test
+ public void testRead() throws IOException {
+ Builder newBuilder = FooBarSpecificRecord.newBuilder();
+ newBuilder.setId(42);
+ newBuilder.setRelatedids(Arrays.asList(1,2,3));
+ FooBarSpecificRecord specificRecord = newBuilder.build();
+
+ byte[] recordBytes = serializeRecord(specificRecord);
+
+ Decoder decoder = DecoderFactory.get().binaryDecoder(recordBytes, null);
+ SpecificDatumReader<FooBarSpecificRecord> specificDatumReader = new SpecificDatumReader<FooBarSpecificRecord>(FooBarSpecificRecord.SCHEMA$);
+ FooBarSpecificRecord deserialized = new FooBarSpecificRecord();
+ specificDatumReader.read(deserialized, decoder);
+
+ assertEquals(specificRecord, deserialized);
+
+ }
+
+}
Propchange: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificDatumReader.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: avro/trunk/lang/java/avro/src/test/resources/FooBarSpecificRecord.avsc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/resources/FooBarSpecificRecord.avsc?rev=1339864&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/test/resources/FooBarSpecificRecord.avsc (added)
+++ avro/trunk/lang/java/avro/src/test/resources/FooBarSpecificRecord.avsc Thu May 17 21:12:43 2012
@@ -0,0 +1,10 @@
+{
+ "type": "record",
+ "name": "FooBarSpecificRecord",
+ "namespace": "org.apache.avro",
+ "fields": [
+ {"name": "id", "type": "int"},
+ {"name": "relatedids", "type":
+ {"type": "array", "items": "int"}}
+ ]
+}