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/09/10 20:31:49 UTC
svn commit: r1383026 - in /avro/trunk: CHANGES.txt
lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
lang/java/avro/src/test/java/org/apache/avro/TestReflect.java
Author: cutting
Date: Mon Sep 10 18:31:48 2012
New Revision: 1383026
URL: http://svn.apache.org/viewvc?rev=1383026&view=rev
Log:
AVRO-1146. Java: Serialize several built-in Java classes as strings, including BigDecimal, BigInteger, URI, URL, Date and File. Contributed by Alexandre Normand and cutting.
Modified:
avro/trunk/CHANGES.txt
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestReflect.java
Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1383026&r1=1383025&r2=1383026&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Mon Sep 10 18:31:48 2012
@@ -6,6 +6,10 @@ Avro 1.7.2 (unreleased)
IMPROVEMENTS
+ AVRO-1146. Java: Serialize several built-in Java classes as
+ strings, including BigDecimal, BigInteger, URI, URL, Date and
+ File. (Alexandre Normand and cutting)
+
BUG FIXES
AVRO-1128. Java: Fix SpecificRecordBase#equals() to work for
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=1383026&r1=1383025&r2=1383026&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 Mon Sep 10 18:31:48 2012
@@ -33,6 +33,8 @@ import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
import org.apache.avro.AvroRemoteException;
import org.apache.avro.AvroRuntimeException;
@@ -74,7 +76,22 @@ public class ReflectData extends Specifi
private static final ReflectData INSTANCE = new ReflectData();
- protected ReflectData() {}
+ /** Read/write some common builtin classes as strings. Representing these as
+ * strings isn't always best, as they aren't always ordered ideally, but at
+ * least they're stored. Also note that, for compatibility, only classes
+ * that wouldn't be otherwise correctly readable or writable should be added
+ * here, e.g., those without a no-arg constructor or those whose fields are
+ * all transient. */
+ private Set<Class> stringableClasses = new HashSet<Class>(); {
+ stringableClasses.add(java.math.BigDecimal.class);
+ stringableClasses.add(java.math.BigInteger.class);
+ stringableClasses.add(java.net.URI.class);
+ stringableClasses.add(java.net.URL.class);
+ stringableClasses.add(java.io.File.class);
+ stringableClasses.add(java.util.Date.class);
+ }
+
+ public ReflectData() {}
/** Construct with a particular classloader. */
public ReflectData(ClassLoader classLoader) {
@@ -84,6 +101,13 @@ public class ReflectData extends Specifi
/** Return the singleton instance. */
public static ReflectData get() { return INSTANCE; }
+ /** Cause a class to be treated as though it had an {@link Stringable}
+ ** annotation. */
+ public ReflectData addStringable(Class c) {
+ stringableClasses.add(c);
+ return this;
+ }
+
@Override
public DatumReader createDatumReader(Schema schema) {
return new ReflectDatumReader(schema, schema, this);
@@ -215,7 +239,11 @@ public class ReflectData extends Specifi
if (collectionClass != null)
return collectionClass;
return java.lang.reflect.Array.newInstance(getClass(schema.getElementType()),0).getClass();
- case STRING: return String.class;
+ case STRING:
+ Class stringClass = getClassProp(schema, CLASS_PROP);
+ if (stringClass != null)
+ return stringClass;
+ return String.class;
case BYTES: return BYTES_CLASS;
case INT:
String intClass = schema.getProp(CLASS_PROP);
@@ -263,8 +291,12 @@ public class ReflectData extends Specifi
return result;
} else if (type instanceof Class) { // Class
Class<?> c = (Class<?>)type;
- if (c.isPrimitive() || Number.class.isAssignableFrom(c)
- || c == Void.class || c == Boolean.class) // primitive
+ if (c.isPrimitive() || // primitives
+ c == Void.class || c == Boolean.class ||
+ c == Integer.class || c == Long.class ||
+ c == Float.class || c == Double.class ||
+ c == Byte.class || c == Short.class ||
+ c == Character.class)
return super.createSchema(type, names);
if (c.isArray()) { // array
Class component = c.getComponentType();
@@ -294,7 +326,8 @@ public class ReflectData extends Specifi
Union union = c.getAnnotation(Union.class);
if (union != null) { // union annotated
return getAnnotatedUnion(union, names);
- } else if (c.isAnnotationPresent(Stringable.class)){ // Stringable
+ } else if (c.isAnnotationPresent(Stringable.class) || // Stringable
+ stringableClasses.contains(c)) {
Schema result = Schema.create(Schema.Type.STRING);
result.addProp(CLASS_PROP, c.getName());
return result;
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=1383026&r1=1383025&r2=1383026&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 Mon Sep 10 18:31:48 2012
@@ -603,6 +603,25 @@ public class TestReflect {
checkBinary(schema, null);
}
+ /** Test stringable classes. */
+ @Test public void testStringables() throws Exception {
+ checkStringable(java.math.BigDecimal.class, "10");
+ checkStringable(java.math.BigInteger.class, "20");
+ checkStringable(java.net.URI.class, "foo://bar:9000/baz");
+ checkStringable(java.net.URL.class, "http://bar:9000/baz");
+ checkStringable(java.io.File.class, "foo.bar");
+ checkStringable(java.util.Date.class, "Sat, 12 Aug 1995 13:30:00 GMT");
+ }
+
+ public void checkStringable(Class c, String value) throws Exception {
+ ReflectData data = new ReflectData().get();
+ Schema schema = data.getSchema(c);
+ assertEquals
+ ("{\"type\":\"string\",\"java-class\":\""+c.getName()+"\"}",
+ schema.toString());
+ checkBinary(schema, c.getConstructor(String.class).newInstance(value));
+ }
+
public static void checkBinary(Schema schema, Object datum)
throws IOException {
ReflectDatumWriter<Object> writer = new ReflectDatumWriter<Object>(schema);