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 2010/09/13 21:21:11 UTC
svn commit: r996649 - in /avro/trunk: CHANGES.txt
doc/src/content/xdocs/idl.xml lang/java/src/java/org/apache/avro/Schema.java
lang/java/src/java/org/apache/avro/idl/idl.jj
lang/java/src/test/idl/input/simple.avdl
lang/java/src/test/idl/output/simple.avpr
Author: cutting
Date: Mon Sep 13 19:21:10 2010
New Revision: 996649
URL: http://svn.apache.org/viewvc?rev=996649&view=rev
Log:
AVRO-634. IDL: Add support for aliases.
Modified:
avro/trunk/CHANGES.txt
avro/trunk/doc/src/content/xdocs/idl.xml
avro/trunk/lang/java/src/java/org/apache/avro/Schema.java
avro/trunk/lang/java/src/java/org/apache/avro/idl/idl.jj
avro/trunk/lang/java/src/test/idl/input/simple.avdl
avro/trunk/lang/java/src/test/idl/output/simple.avpr
Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=996649&r1=996648&r2=996649&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Mon Sep 13 19:21:10 2010
@@ -11,6 +11,8 @@ Avro 1.4.1 (unreleased)
AVRO-655. Change build so that 'dist' target no longer also runs C
and C++ unit tests. (cutting)
+ AVRO-634. IDL: Add support for aliases. (cutting)
+
BUG FIXES
AVRO-666. Remove an extraneous pdb.set_trace() that crept into schema.py
Modified: avro/trunk/doc/src/content/xdocs/idl.xml
URL: http://svn.apache.org/viewvc/avro/trunk/doc/src/content/xdocs/idl.xml?rev=996649&r1=996648&r2=996649&view=diff
==============================================================================
--- avro/trunk/doc/src/content/xdocs/idl.xml (original)
+++ avro/trunk/doc/src/content/xdocs/idl.xml Mon Sep 13 19:21:10 2010
@@ -352,6 +352,14 @@ protocol MyProto {
defined in <code>someOtherNamespace</code> and <code>Bar</code> will be defined in <code>firstNamespace</code>
as it inherits its default from its container.
</p>
+ <p>Type and field aliases are specified with
+ the <code>@aliases</code> annotation as follows:</p>
+ <source>
+@aliases(["org.old.OldRecord", "org.ancient.AncientRecord"])
+record MyRecord {
+ string @aliases(["oldField", "ancientField"]) myNewField;
+}
+ </source>
</section>
</section>
<section id="example">
@@ -363,6 +371,8 @@ protocol MyProto {
*/
@namespace("org.apache.avro.test")
protocol Simple {
+
+ @aliases(["org.foo.KindOf"])
enum Kind {
FOO,
BAR, // the bar enum value
@@ -380,7 +390,7 @@ protocol Simple {
MD5 hash;
- union { MD5, null} nullableHash;
+ union { MD5, null} @aliases(["hash"]) nullableHash;
array<long> arrayOfLongs;
}
Modified: avro/trunk/lang/java/src/java/org/apache/avro/Schema.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/src/java/org/apache/avro/Schema.java?rev=996649&r1=996648&r2=996649&view=diff
==============================================================================
--- avro/trunk/lang/java/src/java/org/apache/avro/Schema.java (original)
+++ avro/trunk/lang/java/src/java/org/apache/avro/Schema.java Mon Sep 13 19:21:10 2010
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -400,6 +401,11 @@ public abstract class Schema {
public synchronized void addProp(String name, String value) {
props.add(name, value);
}
+ public void addAlias(String alias) {
+ if (aliases == null)
+ this.aliases = new LinkedHashSet<String>();
+ aliases.add(alias);
+ }
public boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof Field)) return false;
@@ -476,11 +482,11 @@ public abstract class Schema {
public String getFullName() { return name.full; }
public void addAlias(String alias) {
if (aliases == null)
- this.aliases = new HashSet<Name>();
+ this.aliases = new LinkedHashSet<Name>();
aliases.add(new Name(alias, name.space));
}
public Set<String> getAliases() {
- Set<String> result = new HashSet<String>();
+ Set<String> result = new LinkedHashSet<String>();
if (aliases != null)
for (Name alias : aliases)
result.add(alias.full);
@@ -625,6 +631,13 @@ public abstract class Schema {
}
if (f.order() != Field.Order.ASCENDING)
gen.writeStringField("order", f.order().name);
+ if (f.aliases != null) {
+ gen.writeFieldName("aliases");
+ gen.writeStartArray();
+ for (String alias : f.aliases)
+ gen.writeString(alias);
+ gen.writeEndArray();
+ }
f.props.write(gen);
gen.writeEndObject();
}
@@ -1052,7 +1065,7 @@ public abstract class Schema {
return null;
if (!aliasesNode.isArray())
throw new SchemaParseException("aliases not an array: "+node);
- Set<String> aliases = new HashSet<String>();
+ Set<String> aliases = new LinkedHashSet<String>();
for (JsonNode aliasNode : aliasesNode) {
if (!aliasNode.isTextual())
throw new SchemaParseException("alias not a string: "+aliasNode);
Modified: avro/trunk/lang/java/src/java/org/apache/avro/idl/idl.jj
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/src/java/org/apache/avro/idl/idl.jj?rev=996649&r1=996648&r2=996649&view=diff
==============================================================================
--- avro/trunk/lang/java/src/java/org/apache/avro/idl/idl.jj (original)
+++ avro/trunk/lang/java/src/java/org/apache/avro/idl/idl.jj Mon Sep 13 19:21:10 2010
@@ -96,6 +96,33 @@ public class Idl
this.inputDir = inputFile.getParentFile();
}
+ private ParseException error(String message, Token token) {
+ return new ParseException
+ (message+", at line "+token.beginLine+", column "+token.beginColumn);
+ }
+
+ private String getTextProp(String key, Map<String,JsonNode> props,
+ Token token) throws ParseException {
+ JsonNode value = props.get(key);
+ if (value.isTextual())
+ return value.getTextValue();
+ throw error(key+" property must be textual: "+value, token);
+ }
+
+ private List<String> getTextProps(String key, Map<String,JsonNode> props,
+ Token token) throws ParseException {
+ JsonNode value = props.get(key);
+ if (!value.isArray())
+ throw error(key+" property must be array: "+value, token);
+ List<String> values = new ArrayList<String>();
+ for (JsonNode n : value)
+ if (n.isTextual())
+ values.add(n.getTextValue());
+ else
+ throw error(key+" values must be textual: "+n, token);
+ return values;
+ }
+
}
PARSER_END(Idl)
@@ -941,15 +968,14 @@ Protocol CompilationUnit():
Schema NamedSchemaDeclaration():
{
Schema s;
- Map<String, String> props = new HashMap<String, String>();
+ Map<String, JsonNode> props = new LinkedHashMap<String, JsonNode>();
String savedSpace = this.namespace;
}
{
( SchemaProperty(props) )*
{
- if (props.containsKey("namespace")) {
- this.namespace = props.get("namespace");
- }
+ if (props.containsKey("namespace"))
+ this.namespace = getTextProp("namespace", props, token);
}
(
s = FixedDeclaration()
@@ -958,6 +984,16 @@ Schema NamedSchemaDeclaration():
)
{
this.namespace = savedSpace;
+
+ for (String key : props.keySet())
+ if ("namespace".equals(key)) { // already handled: ignore
+ } else if ("aliases".equals(key)) { // aliases
+ for (String alias : getTextProps("aliases", props, token))
+ s.addAlias(alias);
+ } else if (props.get(key).isTextual()) { // ignore other non-textual
+ s.addProp(key, getTextProp(key, props, token));
+ }
+
return s;
}
}
@@ -991,14 +1027,13 @@ Protocol ProtocolDeclaration():
{
String name;
Protocol p;
- Map<String, String> props = new HashMap<String, String>();
+ Map<String, JsonNode> props = new LinkedHashMap<String, JsonNode>();
}
{
( SchemaProperty(props) )*
{
- if (props.containsKey("namespace")) {
- namespace = props.get("namespace");
- }
+ if (props.containsKey("namespace"))
+ namespace = getTextProp("namespace", props, token);
}
"protocol"
name = Identifier()
@@ -1091,7 +1126,7 @@ Protocol ImportIdl() : {
try {
return new Idl(new File(inputDir, importFile)).CompilationUnit();
} catch (IOException e) {
- throw new ParseException("Error importing "+importFile+": "+e);
+ throw error("Error importing "+importFile+": "+e, token);
}
}
}
@@ -1106,7 +1141,7 @@ Protocol ImportProtocol() : {
try {
return Protocol.parse(new File(inputDir, importFile));
} catch (IOException e) {
- throw new ParseException("Error importing "+importFile+": "+e);
+ throw error("Error importing "+importFile+": "+e, token);
}
}
}
@@ -1120,7 +1155,7 @@ Schema ImportSchema() : {
try {
return Schema.parse(new File(inputDir, importFile));
} catch (IOException e) {
- throw new ParseException("Error importing "+importFile+": "+e);
+ throw error("Error importing "+importFile+": "+e, token);
}
}
}
@@ -1167,19 +1202,16 @@ Schema RecordDeclaration():
}
}
-void SchemaProperty(Map<String, String> properties):
+void SchemaProperty(Map<String, JsonNode> properties):
{
String key;
- String val;
+ JsonNode val;
}
{
- "@" key = Identifier() "(" val = JsonString() ")"
+ "@" key = Identifier() "(" val = Json() ")"
{
- if (properties.containsKey(key)) {
- throw new ParseException("Property '" + key + "' already specified " +
- " at line " + token.beginLine + ", column " +
- token.beginColumn);
- }
+ if (properties.containsKey(key))
+ throw error("Property '" + key + "' already specified", token);
properties.put(key, val);
}
}
@@ -1188,7 +1220,7 @@ void SchemaProperty(Map<String, String>
void FieldDeclaration(List<Field> fields):
{
Schema type;
- Map<String, String> props = new HashMap<String, String>();
+ Map<String, JsonNode> props = new LinkedHashMap<String, JsonNode>();
}
{
// TODO should we be able to specify properties on any Type?
@@ -1199,9 +1231,8 @@ void FieldDeclaration(List<Field> fields
VariableDeclarator(type, fields) ( "," VariableDeclarator(type, fields) )*
";"
{
- for (Map.Entry<String, String> propEntry : props.entrySet()) {
- type.addProp(propEntry.getKey(), propEntry.getValue());
- }
+ for (String key : props.keySet())
+ type.addProp(key, getTextProp(key, props, token));
}
}
@@ -1209,7 +1240,7 @@ void VariableDeclarator(Schema type, Lis
{
String name;
JsonNode defaultValue = null;
- Map<String, String> props = new HashMap<String, String>();
+ Map<String, JsonNode> props = new LinkedHashMap<String, JsonNode>();
}
{
( SchemaProperty(props) )*
@@ -1220,13 +1251,18 @@ void VariableDeclarator(Schema type, Lis
{
Field.Order order = Field.Order.ASCENDING;
- for (Map.Entry<String, String> prop : props.entrySet())
- if ("order".equals(prop.getKey()))
- order = Field.Order.valueOf(prop.getValue().toUpperCase());
+ for (String key : props.keySet())
+ if ("order".equals(key))
+ order = Field.Order.valueOf(getTextProp(key,props,token).toUpperCase());
Field field = new Field(name, type, null, defaultValue, order);
- for (Map.Entry<String, String> prop : props.entrySet())
- if (!"order".equals(prop.getKey()))
- field.addProp(prop.getKey(), prop.getValue());
+ for (String key : props.keySet())
+ if ("order".equals(key)) { // already handled: ignore
+ } else if ("aliases".equals(key)) { // aliases
+ for (String alias : getTextProps("aliases", props, token))
+ field.addAlias(alias);
+ } else if (props.get(key).isTextual()) { // ignore other non-textual
+ field.addProp(key, getTextProp(key, props, token));
+ }
fields.add(field);
}
}
@@ -1250,9 +1286,7 @@ Message MessageDeclaration(Protocol p):
{
Schema errors = Schema.createUnion(errorSchemata);
if (oneWay && response.getType() != Type.NULL)
- throw new ParseException("One-way message'" + name + "' must return void"
- + " at line " + token.beginLine + ", column " +
- token.beginColumn);
+ throw error("One-way message'"+name+"' must return void", token);
return oneWay
? p.createMessage(name, null, request)
: p.createMessage(name, null, request, response, errors);
@@ -1349,11 +1383,8 @@ Schema ReferenceType():
if ((name.indexOf('.') == -1) && namespace != null)
name = namespace + "." + name;
Schema type = names.get(name);
- if (type == null) {
- throw new ParseException("Undefined name '" + name + "'" +
- " at line " + token.beginLine + ", column " +
- token.beginColumn);
- }
+ if (type == null)
+ throw error("Undefined name '" + name + "'", token);
return type;
}
}
Modified: avro/trunk/lang/java/src/test/idl/input/simple.avdl
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/src/test/idl/input/simple.avdl?rev=996649&r1=996648&r2=996649&view=diff
==============================================================================
--- avro/trunk/lang/java/src/test/idl/input/simple.avdl (original)
+++ avro/trunk/lang/java/src/test/idl/input/simple.avdl Mon Sep 13 19:21:10 2010
@@ -21,6 +21,7 @@
*/
@namespace("org.apache.avro.test")
protocol Simple {
+ @aliases(["org.foo.KindOf"])
enum Kind {
FOO,
BAR, // the bar enum value
@@ -36,7 +37,7 @@ protocol Simple {
@foo("bar") MD5 hash;
- union { MD5, null} nullableHash;
+ union { MD5, null} @aliases(["hash", "hsh"]) nullableHash;
}
error TestError {
Modified: avro/trunk/lang/java/src/test/idl/output/simple.avpr
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/src/test/idl/output/simple.avpr?rev=996649&r1=996648&r2=996649&view=diff
==============================================================================
--- avro/trunk/lang/java/src/test/idl/output/simple.avpr (original)
+++ avro/trunk/lang/java/src/test/idl/output/simple.avpr Mon Sep 13 19:21:10 2010
@@ -4,7 +4,8 @@
"types" : [ {
"type" : "enum",
"name" : "Kind",
- "symbols" : [ "FOO", "BAR", "BAZ" ]
+ "symbols" : [ "FOO", "BAR", "BAZ" ],
+ "aliases" : [ "org.foo.KindOf" ]
}, {
"type" : "fixed",
"name" : "MD5",
@@ -27,7 +28,8 @@
"type" : "MD5"
}, {
"name" : "nullableHash",
- "type" : [ "MD5", "null" ]
+ "type" : [ "MD5", "null" ],
+ "aliases" : [ "hash", "hsh" ]
} ]
}, {
"type" : "error",