Skip to content

Commit

Permalink
AVRO-246. Java: Fix union dispatch to consider full schema name for r…
Browse files Browse the repository at this point in the history
…ecords, enums and fixed.

git-svn-id: https://svn.apache.org/repos/asf/avro/trunk@1074319 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
cutting committed Feb 24, 2011
1 parent 8b173f0 commit 5076849
Show file tree
Hide file tree
Showing 23 changed files with 130 additions and 416 deletions.
5 changes: 5 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ Avro 1.5.0 (unreleased)
AVRO-741. C: Minor API change to handling of bytes data.
(Douglas Creager via brucem)

AVRO-246. Java: Add required Schema parameter to GenericData.Fixed
and GenericData.EnumSymbol constructors. Also fix union dispatch
to conform to specification, using full schema name for records,
enums and fixed.

NEW FEATURES

AVRO-684. Java: Add command-line "recodec" tool to change file
Expand Down
4 changes: 2 additions & 2 deletions lang/java/avro/src/main/java/org/apache/avro/Schema.java
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ public String getNamespace() {
}

/** If this is a record, enum or fixed, returns its namespace-qualified name,
* if any. */
* otherwise returns the name of the primitive type. */
public String getFullName() {
throw new AvroRuntimeException("Not a named type: "+this);
return getName();
}

/** If this is a record, enum or fixed, add an alias. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,25 @@ public String toString() {

/** Default implementation of {@link GenericFixed}. */
public static class Fixed implements GenericFixed, Comparable<Fixed> {
private Schema schema;
private byte[] bytes;

public Fixed(Schema schema) { bytes(new byte[schema.getFixedSize()]); }
public Fixed(byte[] bytes) { bytes(bytes); }
public Fixed(Schema schema) { setSchema(schema); }

public Fixed(Schema schema, byte[] bytes) {
this.schema = schema;
this.bytes = bytes;
}

protected Fixed() {}

protected void setSchema(Schema schema) {
this.schema = schema;
this.bytes = new byte[schema.getFixedSize()];
}

@Override public Schema getSchema() { return schema; }

public void bytes(byte[] bytes) { this.bytes = bytes; }

public byte[] bytes() { return bytes; }
Expand All @@ -219,8 +232,15 @@ public int compareTo(Fixed that) {

/** Default implementation of {@link GenericEnumSymbol}. */
public static class EnumSymbol implements GenericEnumSymbol {
private Schema schema;
private String symbol;
public EnumSymbol(String symbol) { this.symbol = symbol; }

public EnumSymbol(Schema schema, String symbol) {
this.schema = schema;
this.symbol = symbol;
}

@Override public Schema getSchema() { return schema; }

@Override
public boolean equals(Object o) {
Expand Down Expand Up @@ -468,12 +488,17 @@ 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);
return (schema.getFullName() == null)
? getRecordSchema(datum).getFullName() == null
: schema.getFullName().equals(getRecordSchema(datum).getFullName());
case ENUM:
if (!isEnum(datum)) return false;
return schema.getFullName().equals(getEnumSchema(datum).getFullName());
case ARRAY: return isArray(datum);
case MAP: return isMap(datum);
case FIXED: return isFixed(datum);
case FIXED:
if (!isFixed(datum)) return false;
return schema.getFullName().equals(getFixedSchema(datum).getFullName());
case STRING: return isString(datum);
case BYTES: return isBytes(datum);
case INT: return datum instanceof Integer;
Expand Down Expand Up @@ -508,6 +533,13 @@ protected boolean isEnum(Object datum) {
return datum instanceof GenericEnumSymbol;
}

/** Called to obtain the schema of a enum. By default calls
* {GenericContainer#getSchema(). May be overridden for alternate enum
* representations. */
protected Schema getEnumSchema(Object enu) {
return ((GenericContainer)enu).getSchema();
}

/** Called by the default implementation of {@link #instanceOf}.*/
protected boolean isMap(Object datum) {
return datum instanceof Map;
Expand All @@ -518,6 +550,13 @@ protected boolean isFixed(Object datum) {
return datum instanceof GenericFixed;
}

/** Called to obtain the schema of a fixed. By default calls
* {GenericContainer#getSchema(). May be overridden for alternate fixed
* representations. */
protected Schema getFixedSchema(Object fixed) {
return ((GenericContainer)fixed).getSchema();
}

/** Called by the default implementation of {@link #instanceOf}.*/
protected boolean isString(Object datum) {
return datum instanceof CharSequence;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ protected Object readEnum(Schema expected, Decoder in) throws IOException {
/** Called to create an enum value. May be overridden for alternate enum
* representations. By default, returns a GenericEnumSymbol. */
protected Object createEnum(String symbol, Schema schema) {
return new GenericData.EnumSymbol(symbol);
return new GenericData.EnumSymbol(schema, symbol);
}

/** Called to read an array instance. May be overridden for alternate array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ protected void write(Schema schema, Object datum, Encoder out)
default: error(schema,datum);
}
} catch (NullPointerException e) {
throw npe(e, " of "+schema.getName());
throw npe(e, " of "+schema.getFullName());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package org.apache.avro.generic;

/** An enum symbol. */
public interface GenericEnumSymbol {
public interface GenericEnumSymbol extends GenericContainer {
/** Return the symbol. */
String toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package org.apache.avro.generic;

/** Fixed-size data. */
public interface GenericFixed {
public interface GenericFixed extends GenericContainer {
/** Return the data. */
byte[] bytes();
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ public Symbol generate(Schema writer, Schema reader,
case BYTES:
return Symbol.BYTES;
case FIXED:
if (writer.getName().equals(reader.getName())
if (writer.getFullName().equals(reader.getFullName())
&& writer.getFixedSize() == reader.getFixedSize()) {
return Symbol.seq(new Symbol.IntCheckAction(writer.getFixedSize()),
Symbol.FIXED);
}
break;

case ENUM:
if (writer.getName() == null
|| writer.getName().equals(reader.getName())) {
if (writer.getFullName() == null
|| writer.getFullName().equals(reader.getFullName())) {
return Symbol.seq(mkEnumAdjust(writer.getEnumSymbols(),
reader.getEnumSymbols()), Symbol.ENUM);
}
Expand Down Expand Up @@ -190,7 +190,7 @@ private Symbol resolveUnion(Schema writer, Schema reader,
int i = 0;
for (Schema w : alts) {
symbols[i] = generate(w, reader, seen);
labels[i] = w.getName();
labels[i] = w.getFullName();
i++;
}
return Symbol.seq(Symbol.alt(symbols, labels),
Expand Down Expand Up @@ -416,9 +416,12 @@ private static int bestBranch(Schema r, Schema w) {
int j = 0;
for (Schema b : r.getTypes()) {
if (vt == b.getType())
if (vt == Schema.Type.RECORD) {
String vname = w.getName();
if (vname == null || vname.equals(b.getName()))
if (vt == Schema.Type.RECORD || vt == Schema.Type.ENUM ||
vt == Schema.Type.FIXED) {
String vname = w.getFullName();
String bname = b.getFullName();
if ((vname != null && vname.equals(bname))
|| vname == bname && vt == Schema.Type.RECORD)
return j;
} else
return j;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public Symbol generate(Schema sc, Map<LitS, Symbol> seen) {
int i = 0;
for (Schema b : sc.getTypes()) {
symbols[i] = generate(b, seen);
labels[i] = b.getName();
labels[i] = b.getFullName();
i++;
}
return Symbol.seq(Symbol.alt(symbols, labels), Symbol.UNION);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ protected void write(Schema schema, Object datum, Encoder out)
super.write(schema, datum, out);
} catch (NullPointerException e) { // improve error message
NullPointerException result =
new NullPointerException("in "+schema.getName()+" "+e.getMessage());
new NullPointerException("in "+schema.getFullName()+" "+e.getMessage());
result.initCause(e);
throw result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ protected boolean isEnum(Object datum) {
return datum instanceof Enum || super.isEnum(datum);
}

@Override
protected Schema getEnumSchema(Object datum) {
return (datum instanceof Enum)
? getSchema(datum.getClass())
: super.getEnumSchema(datum);
}

private Map<String,Class> classCache = new ConcurrentHashMap<String,Class>();

private static final Class NO_CLASS = new Object(){}.getClass();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
/** Base class for generated fixed-sized data classes. */
public abstract class SpecificFixed extends GenericData.Fixed {
public SpecificFixed() {
bytes(new byte[getClass().getAnnotation(FixedSize.class).value()]);
setSchema(SpecificData.get().getSchema(getClass()));
}
}

5 changes: 3 additions & 2 deletions lang/java/avro/src/test/java/org/apache/avro/RandomData.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ private static Object generate(Schema schema, Random random, int d) {
return record;
case ENUM:
List<String> symbols = schema.getEnumSymbols();
return new GenericData.EnumSymbol(symbols.get(random.nextInt(symbols.size())));
return new GenericData.EnumSymbol
(schema, symbols.get(random.nextInt(symbols.size())));
case ARRAY:
int length = (random.nextInt(5)+2)-d;
GenericArray<Object> array =
Expand All @@ -93,7 +94,7 @@ private static Object generate(Schema schema, Random random, int d) {
case FIXED:
byte[] bytes = new byte[schema.getFixedSize()];
random.nextBytes(bytes);
return new GenericData.Fixed(bytes);
return new GenericData.Fixed(schema, bytes);
case STRING: return randomUtf8(random, 40);
case BYTES: return randomBytes(random, 40);
case INT: return random.nextInt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public void testToStringIsJson() throws JsonParseException, IOException {

GenericRecord r = new GenericData.Record(schema);
r.put(stringField.name(), "hello\nthere\"\tyou}");
r.put(enumField.name(), new GenericData.EnumSymbol("a"));
r.put(enumField.name(), new GenericData.EnumSymbol(enumField.schema(),"a"));

String json = r.toString();
JsonFactory factory = new JsonFactory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ package $schema.getNamespace();
#end
public enum ${this.mangle($schema.getName())} {
#foreach ($symbol in ${schema.getEnumSymbols()})${this.mangle($symbol)}#if ($velocityHasNext), #end#end

;
public static final org.apache.avro.Schema SCHEMA$ = org.apache.avro.Schema.parse("${this.javaEscape($schema.toString())}");
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ package $schema.getNamespace();
/** $schema.getDoc() */
#end
@org.apache.avro.specific.FixedSize($schema.getFixedSize())
public class ${this.mangle($schema.getName())} extends org.apache.avro.specific.SpecificFixed {}
public class ${this.mangle($schema.getName())} extends org.apache.avro.specific.SpecificFixed {
public static final org.apache.avro.Schema SCHEMA$ = org.apache.avro.Schema.parse("${this.javaEscape($schema.toString())}");
}
5 changes: 3 additions & 2 deletions lang/java/ipc/src/test/java/org/apache/avro/RandomData.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ private static Object generate(Schema schema, Random random, int d) {
return record;
case ENUM:
List<String> symbols = schema.getEnumSymbols();
return new GenericData.EnumSymbol(symbols.get(random.nextInt(symbols.size())));
return new GenericData.EnumSymbol
(schema, symbols.get(random.nextInt(symbols.size())));
case ARRAY:
int length = (random.nextInt(5)+2)-d;
GenericArray<Object> array =
Expand All @@ -93,7 +94,7 @@ private static Object generate(Schema schema, Random random, int d) {
case FIXED:
byte[] bytes = new byte[schema.getFixedSize()];
random.nextBytes(bytes);
return new GenericData.Fixed(bytes);
return new GenericData.Fixed(schema, bytes);
case STRING: return randomUtf8(random, 40);
case BYTES: return randomBytes(random, 40);
case INT: return random.nextInt();
Expand Down
8 changes: 5 additions & 3 deletions lang/java/ipc/src/test/java/org/apache/avro/TestCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ public void testEnum() throws Exception {

@Test
public void testFixed() throws Exception {
check("{\"type\": \"fixed\", \"name\":\"Test\", \"size\": 1}",
new GenericData.Fixed(new byte[]{(byte)'a'}),
new GenericData.Fixed(new byte[]{(byte)'b'}));
String json = "{\"type\": \"fixed\", \"name\":\"Test\", \"size\": 1}";
Schema schema = Schema.parse(json);
check(json,
new GenericData.Fixed(schema, new byte[]{(byte)'a'}),
new GenericData.Fixed(schema, new byte[]{(byte)'b'}));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,11 @@ public void testEcho() throws IOException {
GenericRecord record =
new GenericData.Record(PROTOCOL.getType("TestRecord"));
record.put("name", new Utf8("foo"));
record.put("kind", new GenericData.EnumSymbol("BAR"));
record.put("kind", new GenericData.EnumSymbol
(PROTOCOL.getType("Kind"), "BAR"));
record.put("hash", new GenericData.Fixed
(new byte[]{0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5}));
(PROTOCOL.getType("MD5"),
new byte[]{0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5}));
GenericRecord params =
new GenericData.Record(PROTOCOL.getMessages().get("echo").getRequest());
params.put("record", record);
Expand Down
Loading

0 comments on commit 5076849

Please sign in to comment.