avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From th...@apache.org
Subject [04/36] avro git commit: [add] AVRO-1723 and AVRO-1667
Date Fri, 19 May 2017 17:12:18 GMT
[add] AVRO-1723 and AVRO-1667

Project: http://git-wip-us.apache.org/repos/asf/avro/repo
Commit: http://git-wip-us.apache.org/repos/asf/avro/commit/fd6c4228
Tree: http://git-wip-us.apache.org/repos/asf/avro/tree/fd6c4228
Diff: http://git-wip-us.apache.org/repos/asf/avro/diff/fd6c4228

Branch: refs/heads/master
Commit: fd6c4228fbecc6eff3e3ecd5ee27d2ceb46339ff
Parents: 482adcf
Author: Zoltan Farkas <zolyfarkas@yahoo.com>
Authored: Wed Nov 18 17:44:50 2015 -0500
Committer: Zoltan Farkas <zolyfarkas@yahoo.com>
Committed: Thu Mar 17 09:56:09 2016 -0400

----------------------------------------------------------------------
 .../java/org/apache/avro/io/parsing/Symbol.java |  88 +++----
 .../avro/compiler/idl/SchemaResolver.java       | 229 +++++++++++++++++++
 .../javacc/org/apache/avro/compiler/idl/idl.jj  |   7 +-
 .../java/compiler/src/test/idl/input/cycle.avdl |  24 ++
 .../compiler/src/test/idl/output/cycle.avpr     |  55 +++++
 .../org/apache/avro/compiler/idl/TestCycle.java | 105 +++++++++
 lang/java/ipc/nb-configuration.xml              |  18 ++
 7 files changed, 480 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/avro/blob/fd6c4228/lang/java/avro/src/main/java/org/apache/avro/io/parsing/Symbol.java
----------------------------------------------------------------------
diff --git a/lang/java/avro/src/main/java/org/apache/avro/io/parsing/Symbol.java b/lang/java/avro/src/main/java/org/apache/avro/io/parsing/Symbol.java
index 80ae644..11e0737 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/io/parsing/Symbol.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/io/parsing/Symbol.java
@@ -60,7 +60,7 @@ public abstract class Symbol {
    * the symbols that forms the production for this symbol. The
    * sequence is in the reverse order of production. This is useful
    * for easy copying onto parsing stack.
-   * 
+   *
    * Please note that this is a final. So the production for a symbol
    * should be known before that symbol is constructed. This requirement
    * cannot be met for those symbols which are recursive (e.g. a record that
@@ -77,8 +77,8 @@ public abstract class Symbol {
   protected Symbol(Kind kind) {
     this(kind, null);
   }
-    
-    
+
+
   protected Symbol(Kind kind, Symbol[] production) {
     this.production = production;
     this.kind = kind;
@@ -120,7 +120,7 @@ public abstract class Symbol {
   static Symbol error(String e) {
     return new ErrorAction(e);
   }
-  
+
   /**
    * A convenience method to construct a ResolvingAction.
    * @param w The writer symbol
@@ -129,32 +129,32 @@ public abstract class Symbol {
   static Symbol resolve(Symbol w, Symbol r) {
     return new ResolvingAction(w, r);
   }
-  
+
   private static class Fixup {
-    public final Symbol[] symbols;
-    public final int pos;
-    
+    public  Symbol[] symbols;
+    public  int pos;
+
     public Fixup(Symbol[] symbols, int pos) {
       this.symbols = symbols;
       this.pos = pos;
     }
   }
-  
+
   public Symbol flatten(Map<Sequence, Sequence> map,
       Map<Sequence, List<Fixup>> map2) {
     return this;
   }
-  
+
   public int flattenedSize() {
     return 1;
   }
-  
+
   /**
    * Flattens the given sub-array of symbols into an sub-array of symbols. Every
    * <tt>Sequence</tt> in the input are replaced by its production recursively.
    * Non-<tt>Sequence</tt> symbols, they internally have other symbols
    * those internal symbols also get flattened.
-   * 
+   *
    * The algorithm does a few tricks to handle recursive symbol definitions.
    * In order to avoid infinite recursion with recursive symbols, we have a map
    * of Symbol->Symbol. Before fully constructing a flattened symbol for a
@@ -168,7 +168,7 @@ public abstract class Symbol {
    * has not not be fully constructed yet, we copy a bunch of <tt>null</tt>s.
    * Fix-up remembers all those <tt>null</tt> patches. The fix-ups gets finally
    * filled when we know the symbols to occupy those patches.
-   *  
+   *
    * @param in  The array of input symbols to flatten
    * @param start The position where the input sub-array starts.
    * @param out The output that receives the flattened list of symbols. The
@@ -246,7 +246,7 @@ public abstract class Symbol {
 
   public static class ImplicitAction extends Symbol {
     /**
-     * Set to <tt>true</tt> if and only if this implicit action is 
+     * Set to <tt>true</tt> if and only if this implicit action is
      * a trailing action. That is, it is an action that follows
      * real symbol. E.g {@link Symbol#DEFAULT_END_ACTION}.
      */
@@ -255,13 +255,13 @@ public abstract class Symbol {
     private ImplicitAction() {
       this(false);
     }
-    
+
     private ImplicitAction(boolean isTrailing) {
       super(Kind.IMPLICIT_ACTION);
       this.isTrailing = isTrailing;
     }
   }
-  
+
   protected static class Root extends Symbol {
     private Root(Symbol... symbols) {
       super(Kind.ROOT, makeProduction(symbols));
@@ -276,7 +276,7 @@ public abstract class Symbol {
       return result;
     }
   }
-  
+
   protected static class Sequence extends Symbol implements Iterable<Symbol> {
     private Sequence(Symbol[] productions) {
       super(Kind.SEQUENCE, productions);
@@ -285,19 +285,19 @@ public abstract class Symbol {
     public Symbol get(int index) {
       return production[index];
     }
-    
+
     public int size() {
       return production.length;
     }
-    
+
     public Iterator<Symbol> iterator() {
       return new Iterator<Symbol>() {
         private int pos = production.length;
-        
+
         public boolean hasNext() {
           return 0 < pos;
         }
-        
+
         public Symbol next() {
           if (0 < pos) {
             return production[--pos];
@@ -305,7 +305,7 @@ public abstract class Symbol {
             throw new NoSuchElementException();
           }
         }
-        
+
         public void remove() {
           throw new UnsupportedOperationException();
         }
@@ -320,7 +320,7 @@ public abstract class Symbol {
         map.put(this, result);
         List<Fixup> l = new ArrayList<Fixup>();
         map2.put(result, l);
-        
+
         flatten(production, 0,
             result.production, 0, map, map2);
         for (Fixup f : l) {
@@ -340,19 +340,19 @@ public abstract class Symbol {
 
   public static class Repeater extends Symbol {
     public final Symbol end;
-   
+
     private Repeater(Symbol end, Symbol... sequenceToRepeat) {
       super(Kind.REPEATER, makeProduction(sequenceToRepeat));
       this.end = end;
       production[0] = this;
     }
-    
+
     private static Symbol[] makeProduction(Symbol[] p) {
       Symbol[] result = new Symbol[p.length + 1];
       System.arraycopy(p, 0, result, 1, p.length);
       return result;
     }
-    
+
     @Override
     public Repeater flatten(Map<Sequence, Sequence> map,
         Map<Sequence, List<Fixup>> map2) {
@@ -363,9 +363,9 @@ public abstract class Symbol {
     }
 
   }
-  
+
   /**
-   * Returns true if the Parser contains any Error symbol, indicating that it may fail 
+   * Returns true if the Parser contains any Error symbol, indicating that it may fail
    * for some inputs.
    */
   public static boolean hasErrors(Symbol symbol) {
@@ -388,7 +388,7 @@ public abstract class Symbol {
       throw new RuntimeException("unknown symbol kind: " + symbol.kind);
     }
   }
-  
+
   private static boolean hasErrors(Symbol root, Symbol[] symbols) {
     if(null != symbols) {
       for(Symbol s: symbols) {
@@ -402,7 +402,7 @@ public abstract class Symbol {
     }
     return false;
   }
-    
+
   public static class Alternative extends Symbol {
     public final Symbol[] symbols;
     public final String[] labels;
@@ -411,15 +411,15 @@ public abstract class Symbol {
       this.symbols = symbols;
       this.labels = labels;
     }
-    
+
     public Symbol getSymbol(int index) {
       return symbols[index];
     }
-    
+
     public String getLabel(int index) {
       return labels[index];
     }
-    
+
     public int size() {
       return symbols.length;
     }
@@ -468,7 +468,7 @@ public abstract class Symbol {
   public static EnumAdjustAction enumAdjustAction(int rsymCount, Object[] adj) {
     return new EnumAdjustAction(rsymCount, adj);
   }
-  
+
   public static class EnumAdjustAction extends IntCheckAction {
     public final Object[] adjustments;
     @Deprecated public EnumAdjustAction(int rsymCount, Object[] adjustments) {
@@ -492,7 +492,7 @@ public abstract class Symbol {
       this.writer = writer;
       this.reader = reader;
     }
-    
+
     @Override
     public ResolvingAction flatten(Map<Sequence, Sequence> map,
         Map<Sequence, List<Fixup>> map2) {
@@ -501,7 +501,7 @@ public abstract class Symbol {
     }
 
   }
-  
+
   public static SkipAction skipAction(Symbol symToSkip) {
     return new SkipAction(symToSkip);
   }
@@ -512,7 +512,7 @@ public abstract class Symbol {
       super(true);
       this.symToSkip = symToSkip;
     }
-    
+
     @Override
     public SkipAction flatten(Map<Sequence, Sequence> map,
         Map<Sequence, List<Fixup>> map2) {
@@ -524,7 +524,7 @@ public abstract class Symbol {
   public static FieldAdjustAction fieldAdjustAction(int rindex, String fname) {
     return new FieldAdjustAction(rindex, fname);
   }
-  
+
   public static class FieldAdjustAction extends ImplicitAction {
     public final int rindex;
     public final String fname;
@@ -533,7 +533,7 @@ public abstract class Symbol {
       this.fname = fname;
     }
   }
-  
+
   public static FieldOrderAction fieldOrderAction(Schema.Field[] fields) {
     return new FieldOrderAction(fields);
   }
@@ -567,13 +567,13 @@ public abstract class Symbol {
       this.rindex = rindex;
       this.symToParse = symToParse;
     }
-    
+
     @Override
     public UnionAdjustAction flatten(Map<Sequence, Sequence> map,
         Map<Sequence, List<Fixup>> map2) {
       return new UnionAdjustAction(rindex, symToParse.flatten(map, map2));
     }
-    
+
   }
 
   /** For JSON. */
@@ -587,11 +587,11 @@ public abstract class Symbol {
       super(symbols.size());
       this.symbols = symbols;
     }
-    
+
     public String getLabel(int n) {
       return symbols.get(n);
     }
-    
+
     public int findLabel(String l) {
       if (l != null) {
         for (int i = 0; i < symbols.size(); i++) {
@@ -633,7 +633,7 @@ public abstract class Symbol {
   public static final Symbol RECORD_END = new ImplicitAction(true);
   public static final Symbol UNION_END = new ImplicitAction(true);
   public static final Symbol FIELD_END = new ImplicitAction(true);
-  
+
   public static final Symbol DEFAULT_END_ACTION = new ImplicitAction(true);
   public static final Symbol MAP_KEY_MARKER =
     new Symbol.Terminal("map-key-marker");

http://git-wip-us.apache.org/repos/asf/avro/blob/fd6c4228/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java
----------------------------------------------------------------------
diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java
b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java
new file mode 100644
index 0000000..df0c7ac
--- /dev/null
+++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.compiler.idl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.avro.JsonProperties;
+import org.apache.avro.LogicalType;
+import org.apache.avro.Protocol;
+import org.apache.avro.Schema;
+import org.codehaus.jackson.JsonNode;
+
+/**
+ *
+ * @author zoly
+ */
+final class SchemaResolver {
+
+    private SchemaResolver() { }
+
+    private static final String UR_SCHEMA_ATTR = "org.apache.avro.compiler.idl.unresolved.name";
+
+    static Schema unresolvedSchema(final String name) {
+        Schema schema = Schema.createRecord("UnresolvedSchema", "unresolved schema",
+                "org.apache.avro.compiler", false, Collections.EMPTY_LIST);
+        schema.addProp(UR_SCHEMA_ATTR, name);
+        return schema;
+    }
+
+    static boolean isUnresolvedSchema(final Schema schema) {
+        return (schema.getType() == Schema.Type.RECORD && schema.getProp(UR_SCHEMA_ATTR)
!= null);
+    }
+
+    static String getUnresolvedSchemaName(final Schema schema) {
+        String name = schema.getProp(UR_SCHEMA_ATTR);
+        if (name == null) {
+            throw new IllegalArgumentException("Schema " + schema + " is not a unresolved
schema");
+        } else {
+            return name;
+        }
+    }
+
+
+
+    static Protocol resolve(final Protocol protocol) {
+        Protocol result = new Protocol(protocol.getName(), protocol.getDoc(), protocol.getNamespace());
+        final Collection<Schema> types = protocol.getTypes();
+        List<Schema> newSchemas = new ArrayList(types.size());
+        Map<String, Schema> processed =  new HashMap<String, Schema>();
+        for (Schema schema : types) {
+            newSchemas.add(resolve(schema, protocol, processed));
+        }
+        result.setTypes(newSchemas);
+
+        for (Map.Entry<String, Protocol.Message> entry : protocol.getMessages().entrySet())
{
+            Protocol.Message value = entry.getValue();
+            Protocol.Message nvalue;
+            if (value.isOneWay()) {
+                Schema request = value.getRequest();
+                nvalue = result.createMessage(value.getName(), value.getDoc(),
+                        value.getObjectProps(), intern(request, processed));
+            } else {
+                Schema request = value.getRequest();
+                Schema response = value.getResponse();
+                Schema errors = value.getErrors();
+                nvalue = result.createMessage(value.getName(), value.getDoc(),
+                        value.getObjectProps(), intern(request, processed),
+                        intern(response, processed), intern(errors, processed));
+            }
+            result.getMessages().put(entry.getKey(), nvalue);
+        }
+        copyProps(protocol, result);
+        return result;
+    }
+
+    private static void copyProps(final JsonProperties from, final JsonProperties to) {
+        for (Map.Entry<String, JsonNode> entry : from.getJsonProps().entrySet()) {
+            to.addProp(entry.getKey(), entry.getValue());
+        }
+    }
+
+
+    static Schema resolve(final Schema schema, final Protocol protocol, final Map<String,
Schema> processed) {
+        final String fullName = schema.getFullName();
+        if (fullName != null && processed.containsKey(fullName)) {
+            return processed.get(schema.getFullName());
+        } else if (isUnresolvedSchema(schema)) {
+            final String unresolvedSchemaName = getUnresolvedSchemaName(schema);
+            Schema type = protocol.getType(unresolvedSchemaName);
+            if (type == null) {
+                throw new IllegalArgumentException("Cannot resolve " + unresolvedSchemaName);
+            }
+            return resolve(type, protocol, processed);
+        } else {
+            switch (schema.getType()) {
+                case RECORD:
+                    Schema createRecord = Schema.createRecord(schema.getName(), schema.getDoc(),
schema.getNamespace(),
+                    schema.isError());
+                    processed.put(schema.getFullName(), createRecord);
+                    final List<Schema.Field> currFields = schema.getFields();
+                    List<Schema.Field> newFields = new ArrayList<Schema.Field>(currFields.size());
+                    for (Schema.Field field : currFields) {
+                        Schema.Field nf = new Schema.Field(field.name(), resolve(field.schema(),
protocol, processed),
+                                field.doc(), field.defaultVal(), field.order());
+                        for (String alias : field.aliases()) {
+                            nf.addAlias(alias);
+                        }
+                        newFields.add(nf);
+                    }
+                    createRecord.setFields(newFields);
+                    final LogicalType lt = schema.getLogicalType();
+                    if (lt != null) {
+                        lt.addToSchema(createRecord);
+                    }
+                    copyProps(schema, createRecord);
+                    return createRecord;
+                case MAP:
+                    Schema result = Schema.createMap(resolve(schema.getValueType(), protocol,
processed));
+                    copyProps(schema, result);
+                    return result;
+                case ARRAY:
+                    Schema aresult = Schema.createArray(resolve(schema.getElementType(),
protocol, processed));
+                    copyProps(schema, aresult);
+                    return aresult;
+                case UNION:
+                    final List<Schema> uTypes = schema.getTypes();
+                    List<Schema> newTypes = new ArrayList<Schema>(uTypes.size());
+                    for (Schema s : uTypes) {
+                        newTypes.add(resolve(s, protocol, processed));
+                    }
+                    Schema bresult =  Schema.createUnion(newTypes);
+                    copyProps(schema, bresult);
+                    return bresult;
+                case ENUM:
+                case FIXED:
+                case STRING:
+                case BYTES:
+                case INT:
+                case LONG:
+                case FLOAT:
+                case DOUBLE:
+                case BOOLEAN:
+                case NULL:
+                    return schema;
+                default:
+                    throw new RuntimeException("Unknown type: " + schema);
+            }
+        }
+    }
+
+    public static Schema intern(final Schema schema, final Map<String, Schema> processed)
{
+        if (schema == null) {
+            return null;
+        }
+        final String fullName = schema.getFullName();
+        if (fullName != null && processed.containsKey(fullName)) {
+            return processed.get(schema.getFullName());
+        } else {
+            switch (schema.getType()) {
+                case RECORD:
+                    Schema createRecord = Schema.createRecord(schema.getName(), schema.getDoc(),
schema.getNamespace(),
+                    schema.isError());
+                    processed.put(schema.getFullName(), createRecord);
+                    final List<Schema.Field> currFields = schema.getFields();
+                    List<Schema.Field> newFields = new ArrayList<Schema.Field>(currFields.size());
+                    for (Schema.Field field : currFields) {
+                        Schema.Field nf = new Schema.Field(field.name(), intern(field.schema(),
processed),
+                                field.doc(), field.defaultVal(), field.order());
+                        for (String alias : field.aliases()) {
+                            nf.addAlias(alias);
+                        }
+                        newFields.add(nf);
+                    }
+                    createRecord.setFields(newFields);
+                    final LogicalType lt = schema.getLogicalType();
+                    if (lt != null) {
+                        lt.addToSchema(createRecord);
+                    }
+                    copyProps(schema, createRecord);
+                    return createRecord;
+                case MAP:
+                    return Schema.createMap(intern(schema.getValueType(), processed));
+                case ARRAY:
+                    return Schema.createArray(intern(schema.getElementType(), processed));
+                case UNION:
+                    final List<Schema> uTypes = schema.getTypes();
+                    List<Schema> newTypes = new ArrayList<Schema>(uTypes.size());
+                    for (Schema s : uTypes) {
+                        newTypes.add(intern(s, processed));
+                    }
+                    return Schema.createUnion(newTypes);
+                case ENUM:
+                case FIXED:
+                case STRING:
+                case BYTES:
+                case INT:
+                case LONG:
+                case FLOAT:
+                case DOUBLE:
+                case BOOLEAN:
+                case NULL:
+                    return schema;
+                default:
+                    throw new RuntimeException("Unknown type: " + schema);
+            }
+        }
+    }
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/avro/blob/fd6c4228/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
----------------------------------------------------------------------
diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
index 8f60b83..a8f0623 100644
--- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
+++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
@@ -999,7 +999,7 @@ Protocol CompilationUnit():
   ( < "\u001a" > )?
   ( <STUFF_TO_IGNORE: ~[]> )?
   <EOF>
-  { return p; }
+  { return SchemaResolver.resolve(p); }
 }
 
 /*
@@ -1465,7 +1465,10 @@ Schema ReferenceType():
       name = namespace + "." + name;
     Schema type = names.get(name);
     if (type == null)
-      throw error("Undefined name '" + name + "'", token);
+      //throw error("Undefined name '" + name + "'", token);
+    {
+      type = SchemaResolver.unresolvedSchema(name);
+    }
     return type;
   }
 }

http://git-wip-us.apache.org/repos/asf/avro/blob/fd6c4228/lang/java/compiler/src/test/idl/input/cycle.avdl
----------------------------------------------------------------------
diff --git a/lang/java/compiler/src/test/idl/input/cycle.avdl b/lang/java/compiler/src/test/idl/input/cycle.avdl
new file mode 100644
index 0000000..f434431
--- /dev/null
+++ b/lang/java/compiler/src/test/idl/input/cycle.avdl
@@ -0,0 +1,24 @@
+@namespace("org.apache.avro.gen")
+protocol Cycle {
+
+    record SampleNode {
+      int count = 0;
+      array<SamplePair> subNodes;
+    }
+
+    record Method {
+      string declaringClass;
+      string methodName;
+    }
+
+    record SamplePair {
+      Method method;
+      SampleNode node;
+    }
+
+    record SelfRef {
+      string something;
+      array<SelfRef> subNodes = [];
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/avro/blob/fd6c4228/lang/java/compiler/src/test/idl/output/cycle.avpr
----------------------------------------------------------------------
diff --git a/lang/java/compiler/src/test/idl/output/cycle.avpr b/lang/java/compiler/src/test/idl/output/cycle.avpr
new file mode 100644
index 0000000..53658af
--- /dev/null
+++ b/lang/java/compiler/src/test/idl/output/cycle.avpr
@@ -0,0 +1,55 @@
+{
+  "protocol" : "Cycle",
+  "namespace" : "org.apache.avro.gen",
+  "types" : [ {
+    "type" : "record",
+    "name" : "SampleNode",
+    "fields" : [ {
+      "name" : "count",
+      "type" : "int",
+      "default" : 0
+    }, {
+      "name" : "subNodes",
+      "type" : {
+        "type" : "array",
+        "items" : {
+          "type" : "record",
+          "name" : "SamplePair",
+          "fields" : [ {
+            "name" : "method",
+            "type" : {
+              "type" : "record",
+              "name" : "Method",
+              "fields" : [ {
+                "name" : "declaringClass",
+                "type" : "string"
+              }, {
+                "name" : "methodName",
+                "type" : "string"
+              } ]
+            }
+          }, {
+            "name" : "node",
+            "type" : "SampleNode"
+          } ]
+        }
+      }
+    } ]
+  }, {
+    "type" : "record",
+    "name" : "SelfRef",
+    "fields" : [ {
+      "name" : "something",
+      "type" : "string"
+    }, {
+      "name" : "subNodes",
+      "type" : {
+        "type" : "array",
+        "items" : "SelfRef"
+      },
+      "default" : [ ]
+    } ]
+  } ],
+  "messages" : { }
+}
+

http://git-wip-us.apache.org/repos/asf/avro/blob/fd6c4228/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestCycle.java
----------------------------------------------------------------------
diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestCycle.java
b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestCycle.java
new file mode 100644
index 0000000..a38e978
--- /dev/null
+++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestCycle.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.compiler.idl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import junit.framework.Assert;
+import org.apache.avro.Protocol;
+import org.apache.avro.Schema;
+import org.apache.avro.compiler.specific.SpecificCompiler;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericDatumWriter;
+import org.apache.avro.generic.GenericRecordBuilder;
+import org.apache.avro.io.BinaryDecoder;
+import org.apache.avro.io.BinaryEncoder;
+import org.apache.avro.io.DecoderFactory;
+import org.apache.avro.io.EncoderFactory;
+import org.junit.Test;
+
+/**
+ *
+ * @author zoly
+ */
+public class TestCycle {
+
+    @Test
+    public void testCycleGeneration() throws ParseException, IOException {
+        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        Idl idl = new Idl(cl.getResourceAsStream("input/cycle.avdl"),
+                "UTF-8");
+        Protocol protocol = idl.CompilationUnit();
+        String json = protocol.toString();
+        System.out.println(json);
+
+        SpecificCompiler compiler = new SpecificCompiler(protocol);
+        compiler.setStringType(GenericData.StringType.String);
+        File output = new File("./target");
+        compiler.compileToDestination(null, output);
+
+        Map<String, Schema> schemas = new HashMap<String, Schema>();
+        for (Schema schema : protocol.getTypes()) {
+            final String name = schema.getName();
+            schemas.put(name, schema);
+        }
+
+        GenericRecordBuilder rb2 = new GenericRecordBuilder(schemas.get("SampleNode"));
+        rb2.set("count", 10);
+        rb2.set("subNodes", Collections.EMPTY_LIST);
+        GenericData.Record node = rb2.build();
+
+        GenericRecordBuilder mb = new GenericRecordBuilder(schemas.get("Method"));
+        mb.set("declaringClass", "Test");
+        mb.set("methodName", "test");
+        GenericData.Record method = mb.build();
+
+        GenericRecordBuilder spb = new GenericRecordBuilder(schemas.get("SamplePair"));
+        spb.set("method", method);
+        spb.set("node", node);
+        GenericData.Record sp = spb.build();
+
+
+        GenericRecordBuilder rb = new GenericRecordBuilder(schemas.get("SampleNode"));
+        rb.set("count", 10);
+        rb.set("subNodes", Arrays.asList(sp));
+        GenericData.Record record = rb.build();
+
+        serDeserRecord(record);
+
+    }
+
+    private static void serDeserRecord(GenericData.Record data) throws IOException {
+        ByteArrayOutputStream bab = new ByteArrayOutputStream();
+        GenericDatumWriter writer = new GenericDatumWriter(data.getSchema());
+        final BinaryEncoder directBinaryEncoder = EncoderFactory.get().directBinaryEncoder(bab,
null);
+        writer.write(data, directBinaryEncoder);
+        directBinaryEncoder.flush();
+        ByteArrayInputStream bis = new ByteArrayInputStream(bab.toByteArray(), 0, bab.size());
+        GenericDatumReader reader = new GenericDatumReader(data.getSchema());
+        BinaryDecoder directBinaryDecoder = DecoderFactory.get().directBinaryDecoder(bis,
null);
+        GenericData.Record read = (GenericData.Record) reader.read(null, directBinaryDecoder);
+        Assert.assertEquals(data.toString(), read.toString());
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/avro/blob/fd6c4228/lang/java/ipc/nb-configuration.xml
----------------------------------------------------------------------
diff --git a/lang/java/ipc/nb-configuration.xml b/lang/java/ipc/nb-configuration.xml
new file mode 100644
index 0000000..93af9a7
--- /dev/null
+++ b/lang/java/ipc/nb-configuration.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-shared-configuration>
+    <!--
+This file contains additional configuration written by modules in the NetBeans IDE.
+The configuration is intended to be shared among all the users of project and
+therefore it is assumed to be part of version control checkout.
+Without this configuration present, some functionality in the IDE may be limited or fail
altogether.
+-->
+    <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
+        <!--
+Properties that influence various parts of the IDE, especially code formatting and the like.

+You can copy and paste the single properties, into the pom.xml file and the IDE will pick
them up.
+That way multiple projects can share the same settings (useful for formatting rules for example).
+Any value defined here will override the pom.xml file value but is only applicable to the
current project.
+-->
+        <netbeans.hint.jdkPlatform>JDK_1.6</netbeans.hint.jdkPlatform>
+    </properties>
+</project-shared-configuration>


Mime
View raw message