Implemented ordering of yang module data nodes. Added Comparators utility class. 44/544/3
authorMartin Vitez <mvitez@cisco.com>
Tue, 2 Jul 2013 12:13:48 +0000 (14:13 +0200)
committerMartin Vitez <mvitez@cisco.com>
Wed, 3 Jul 2013 09:16:44 +0000 (11:16 +0200)
Added checking for duplicate nodes. Added getParent() method to Builder interface.
Removed unused TypeDefinitionAwareBuilder interface.
Fixed bug in processing augmentation of choice node.
Added more logs, javadocs, tests.

Change-Id: I6d7a504cdb516c267d42b99091120649027b453d
Signed-off-by: Martin Vitez <mvitez@cisco.com>
52 files changed:
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/binary-type-test-models/binary-type-test.yang
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/AbstractDataNodeContainerBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/AbstractSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/AbstractTypeAwareBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/Builder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/GroupingBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/TypeDefinitionAwareBuilder.java [deleted file]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AnyXmlBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AugmentationSchemaBuilderImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ChoiceBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ChoiceCaseBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ConstraintsBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ContainerSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/DeviationBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ExtensionBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/FeatureBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/GroupingBuilderImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/IdentitySchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/IdentityrefTypeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/LeafListSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/LeafSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ListSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ModuleBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/NotificationBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/RpcDefinitionBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/TypeDefinitionBuilderImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UnionTypeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UnknownSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UsesNodeBuilderImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserListenerImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/Comparators.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySort.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ParserUtils.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/RefineHolder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/YangModelBuilderUtil.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserNegativeTest.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserTest.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/util/ModuleDependencySortTest.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile3.yang
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container-leaf.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container-list.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/identity.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/typedef.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/testfile0.yang
opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AugmentationSchema.java
opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/DataNodeContainer.java
opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/GroupingDefinition.java
opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Module.java
opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/UsesNode.java

index d6722be..6e804a1 100644 (file)
@@ -15,7 +15,9 @@ import org.opendaylight.controller.yang.model.api.DataSchemaNode;
 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
 
 public abstract class AbstractDataNodeContainerBuilder implements DataNodeContainerBuilder {
-    private final QName qname;
+    protected final int line;
+    protected final QName qname;
+    protected Builder parent;
 
     protected Set<DataSchemaNode> childNodes;
     protected final Set<DataSchemaNodeBuilder> addedChildNodes = new HashSet<DataSchemaNodeBuilder>();
@@ -23,10 +25,26 @@ public abstract class AbstractDataNodeContainerBuilder implements DataNodeContai
     protected Set<GroupingDefinition> groupings;
     protected final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
 
-    protected AbstractDataNodeContainerBuilder(QName qname) {
+    protected AbstractDataNodeContainerBuilder(final int line, final QName qname) {
+        this.line = line;
         this.qname = qname;
     }
 
+    @Override
+    public int getLine() {
+        return line;
+    }
+
+    @Override
+    public Builder getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(final Builder parent) {
+        this.parent = parent;
+    }
+
     @Override
     public QName getQName() {
         return qname;
@@ -37,6 +55,10 @@ public abstract class AbstractDataNodeContainerBuilder implements DataNodeContai
         return childNodes;
     }
 
+    public void setChildNodes(Set<DataSchemaNode> childNodes) {
+        this.childNodes = childNodes;
+    }
+
     @Override
     public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
         return addedChildNodes;
@@ -47,15 +69,15 @@ public abstract class AbstractDataNodeContainerBuilder implements DataNodeContai
         addedChildNodes.add(childNode);
     }
 
-    public void setChildNodes(Set<DataSchemaNode> childNodes) {
-        this.childNodes = childNodes;
-    }
-
     @Override
     public Set<GroupingDefinition> getGroupings() {
         return groupings;
     }
 
+    public void setGroupings(final Set<GroupingDefinition> groupings) {
+        this.groupings = groupings;
+    }
+
     public Set<GroupingBuilder> getGroupingBuilders() {
         return addedGroupings;
     }
@@ -65,8 +87,4 @@ public abstract class AbstractDataNodeContainerBuilder implements DataNodeContai
         addedGroupings.add(grouping);
     }
 
-    public void setGroupings(final Set<GroupingDefinition> groupings) {
-        this.groupings = groupings;
-    }
-
 }
index c8e6968..1963c6c 100644 (file)
@@ -21,15 +21,16 @@ import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBui
 public abstract class AbstractSchemaNodeBuilder implements SchemaNodeBuilder {\r
     protected final int line;\r
     protected final QName qname;\r
-    protected SchemaPath path;\r
+    protected Builder parent;\r
+    protected SchemaPath schemaPath;\r
     protected String description;\r
     protected String reference;\r
     protected Status status = Status.CURRENT;\r
     protected final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();\r
 \r
-    protected AbstractSchemaNodeBuilder(final QName qname, final int line) {\r
-        this.qname = qname;\r
+    protected AbstractSchemaNodeBuilder(final int line, final QName qname) {\r
         this.line = line;\r
+        this.qname = qname;\r
     }\r
 \r
     @Override\r
@@ -41,12 +42,22 @@ public abstract class AbstractSchemaNodeBuilder implements SchemaNodeBuilder {
         return qname;\r
     }\r
 \r
+    @Override\r
+    public Builder getParent() {\r
+        return parent;\r
+    }\r
+\r
+    @Override\r
+    public void setParent(final Builder parent) {\r
+        this.parent = parent;\r
+    }\r
+\r
     public SchemaPath getPath() {\r
-        return path;\r
+        return schemaPath;\r
     }\r
 \r
     public void setPath(SchemaPath schemaPath) {\r
-        this.path = schemaPath;\r
+        this.schemaPath = schemaPath;\r
     }\r
 \r
     public String getDescription() {\r
index 05ef4c5..caf71ec 100644 (file)
@@ -7,16 +7,44 @@
  */
 package org.opendaylight.controller.yang.parser.builder.api;
 
+import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
 
 /**
  * Basic implementation for TypeAwareBuilder builders.
  */
 public abstract class AbstractTypeAwareBuilder implements TypeAwareBuilder {
-
+    protected final int line;
+    protected final QName qname;
+    protected Builder parent;
     protected TypeDefinition<?> type;
     protected TypeDefinitionBuilder typedef;
 
+    public AbstractTypeAwareBuilder(final int line, final QName qname) {
+        this.line = line;
+        this.qname = qname;
+    }
+
+    @Override
+    public int getLine() {
+        return line;
+    }
+
+    @Override
+    public Builder getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(final Builder parent) {
+        this.parent = parent;
+    }
+
+    @Override
+    public QName getQName() {
+        return qname;
+    }
+
     @Override
     public TypeDefinition<?> getType() {
         return type;
index 1d199c2..4500b13 100644 (file)
@@ -14,6 +14,28 @@ import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBui
  */
 public interface Builder {
 
+    /**
+     * Get current line in yang file.
+     *
+     * @return current line in yang file
+     */
+    int getLine();
+
+    /**
+     * Get parent node of this node.
+     *
+     * @return parent node builder or null if this is top level node
+     */
+    Builder getParent();
+
+    /**
+     * Set parent of this node.
+     *
+     * @param parent
+     *            parent node builder
+     */
+    void setParent(Builder parent);
+
     /**
      * Build YANG data model node.
      *
@@ -25,8 +47,6 @@ public interface Builder {
      */
     Object build();
 
-    int getLine();
-
     void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode);
 
 }
index 20d9417..2806994 100644 (file)
@@ -16,7 +16,7 @@ import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBui
 /**
  * Interface for builders of 'grouping' statement.
  */
-public interface GroupingBuilder extends DataNodeContainerBuilder, SchemaNodeBuilder, TypeDefinitionAwareBuilder, GroupingMember {
+public interface GroupingBuilder extends DataNodeContainerBuilder, SchemaNodeBuilder, GroupingMember {
 
     GroupingDefinition build();
 
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/TypeDefinitionAwareBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/TypeDefinitionAwareBuilder.java
deleted file mode 100644 (file)
index 0156c24..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.yang.parser.builder.api;
-
-/**
- * Builders of all nodes, which can have 'typedef' statement must implement this interface.
- * [module, submodule, container, list, grouping, rpc, input, output, notification]
- */
-public interface TypeDefinitionAwareBuilder {
-
-       void addTypedef(TypeDefinitionBuilder typedefBuilder);
-
-}
index d5f3c52..dd89060 100644 (file)
@@ -21,47 +21,46 @@ import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBui
 import org.opendaylight.controller.yang.parser.builder.api.ConfigNode;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class AnyXmlBuilder extends AbstractSchemaNodeBuilder implements DataSchemaNodeBuilder, GroupingMember,
         ConfigNode {
     private boolean built;
     private final AnyXmlSchemaNodeImpl instance;
     private final ConstraintsBuilder constraints;
-
     private List<UnknownSchemaNode> unknownNodes;
 
     private Boolean configuration;
     private boolean augmenting;
     private boolean addedByUses;
 
-    public AnyXmlBuilder(final QName qname, final SchemaPath schemaPath, final int line) {
-        super(qname, line);
-        this.path = schemaPath;
+    public AnyXmlBuilder(final int line, final QName qname, final SchemaPath schemaPath) {
+        super(line, qname);
+        this.schemaPath = schemaPath;
         instance = new AnyXmlSchemaNodeImpl(qname);
         constraints = new ConstraintsBuilder(line);
     }
 
     public AnyXmlBuilder(final AnyXmlBuilder builder) {
-        super(builder.qname, builder.line);
+        super(builder.getLine(), builder.getQName());
+        parent = builder.getParent();
         instance = new AnyXmlSchemaNodeImpl(qname);
-        constraints = builder.constraints;
-        path = builder.path;
+        constraints = builder.getConstraints();
+        schemaPath = builder.getPath();
         unknownNodes = builder.unknownNodes;
-        for (UnknownSchemaNodeBuilder un : builder.addedUnknownNodes) {
-            addedUnknownNodes.add(un);
-        }
-        description = builder.description;
-        reference = builder.reference;
-        status = builder.status;
-        configuration = builder.configuration;
-        augmenting = builder.augmenting;
-        addedByUses = builder.addedByUses;
+        addedUnknownNodes.addAll(builder.getUnknownNodes());
+        description = builder.getDescription();
+        reference = builder.getReference();
+        status = builder.getStatus();
+        configuration = builder.isConfiguration();
+        augmenting = builder.isAugmenting();
+        addedByUses = builder.isAddedByUses();
     }
 
     @Override
     public AnyXmlSchemaNode build() {
         if (!built) {
-            instance.setPath(path);
+            instance.setPath(schemaPath);
             instance.setConstraints(constraints.build());
             instance.setDescription(description);
             instance.setReference(reference);
@@ -77,6 +76,7 @@ public final class AnyXmlBuilder extends AbstractSchemaNodeBuilder implements Da
                     unknownNodes.add(b.build());
                 }
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             built = true;
@@ -127,6 +127,48 @@ public final class AnyXmlBuilder extends AbstractSchemaNodeBuilder implements Da
         this.configuration = configuration;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.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;
+        }
+        AnyXmlBuilder other = (AnyXmlBuilder) obj;
+        if (schemaPath == null) {
+            if (other.schemaPath != null) {
+                return false;
+            }
+        } else if (!schemaPath.equals(other.schemaPath)) {
+            return false;
+        }
+        if (parent == null) {
+            if (other.parent != null) {
+                return false;
+            }
+        } else if (!parent.equals(other.parent)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "anyxml " + qname.getLocalName();
+    }
+
     private final class AnyXmlSchemaNodeImpl implements AnyXmlSchemaNode {
         private final QName qname;
         private SchemaPath path;
index b18f255..b534ba4 100644 (file)
@@ -9,11 +9,12 @@ package org.opendaylight.controller.yang.parser.builder.impl;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
@@ -32,6 +33,7 @@ import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 import org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
@@ -39,7 +41,7 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
     private boolean built;
     private final AugmentationSchemaImpl instance;
     private final int line;
-    private final Builder parent;
+    private Builder parent;
 
     private String whenCondition;
     private String description;
@@ -56,12 +58,10 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
     private boolean resolved;
 
-    AugmentationSchemaBuilderImpl(final String augmentTargetStr, final int line, final Builder parent) {
+    AugmentationSchemaBuilderImpl(final int line, final String augmentTargetStr) {
         this.augmentTargetStr = augmentTargetStr;
         this.line = line;
-        this.parent = parent;
-        final SchemaPath targetPath = YangModelBuilderUtil
-                .parseAugmentPath(augmentTargetStr);
+        final SchemaPath targetPath = YangModelBuilderUtil.parseAugmentPath(augmentTargetStr);
         dirtyAugmentTarget = targetPath;
         instance = new AugmentationSchemaImpl(targetPath);
     }
@@ -76,6 +76,10 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
         return parent;
     }
 
+    @Override
+    public void setParent(final Builder parent) {
+        this.parent = parent;
+    }
 
     @Override
     public void addChildNode(DataSchemaNodeBuilder childNode) {
@@ -145,14 +149,15 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
             instance.setWhenCondition(whenStmt);
 
             // CHILD NODES
-            final Map<QName, DataSchemaNode> childs = new HashMap<QName, DataSchemaNode>();
+            final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
             for (DataSchemaNodeBuilder node : childNodes) {
                 childs.put(node.getQName(), node.build());
             }
             instance.setChildNodes(childs);
 
             // GROUPINGS
-            final Set<GroupingDefinition> groupingDefinitions = new HashSet<GroupingDefinition>();
+            final Set<GroupingDefinition> groupingDefinitions = new TreeSet<GroupingDefinition>(
+                    Comparators.SCHEMA_NODE_COMP);
             for (GroupingBuilder builder : groupings) {
                 groupingDefinitions.add(builder.build());
             }
@@ -170,6 +175,7 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             built = true;
@@ -202,8 +208,7 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
 
     @Override
     public void addTypedef(TypeDefinitionBuilder type) {
-        throw new YangParseException(line,
-                "Augmentation can not contains typedef statement.");
+        throw new YangParseException(line, "Augmentation can not contains typedef statement.");
     }
 
     @Override
@@ -218,7 +223,7 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
 
     @Override
     public void setStatus(Status status) {
-        if(status != null) {
+        if (status != null) {
             this.status = status;
         }
     }
@@ -251,13 +256,9 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
     public int hashCode() {
         final int prime = 17;
         int result = 1;
-        result = prime
-                * result
-                + ((augmentTargetStr == null) ? 0 : augmentTargetStr.hashCode());
-        result = prime * result
-                + ((whenCondition == null) ? 0 : whenCondition.hashCode());
-        result = prime * result
-                + ((childNodes == null) ? 0 : childNodes.hashCode());
+        result = prime * result + ((augmentTargetStr == null) ? 0 : augmentTargetStr.hashCode());
+        result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
+        result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode());
         return result;
     }
 
@@ -297,6 +298,10 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
         return true;
     }
 
+    public String toString() {
+        return "augment " + augmentTargetStr;
+    }
+
     private final class AugmentationSchemaImpl implements AugmentationSchema {
         private SchemaPath targetPath;
         private RevisionAwareXPath whenCondition;
@@ -332,7 +337,9 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
 
         @Override
         public Set<DataSchemaNode> getChildNodes() {
-            return new HashSet<DataSchemaNode>(childNodes.values());
+            final Set<DataSchemaNode> result = new TreeSet<DataSchemaNode>(Comparators.SCHEMA_NODE_COMP);
+            result.addAll(childNodes.values());
+            return result;
         }
 
         private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
@@ -399,12 +406,12 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
             this.status = status;
         }
 
+        @Override
         public List<UnknownSchemaNode> getUnknownSchemaNodes() {
             return unknownNodes;
         }
 
-        private void setUnknownSchemaNodes(
-                List<UnknownSchemaNode> unknownSchemaNodes) {
+        private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
             if (unknownSchemaNodes != null) {
                 this.unknownNodes = unknownSchemaNodes;
             }
@@ -431,12 +438,9 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
         public int hashCode() {
             final int prime = 17;
             int result = 1;
-            result = prime * result
-                    + ((targetPath == null) ? 0 : targetPath.hashCode());
-            result = prime * result
-                    + ((whenCondition == null) ? 0 : whenCondition.hashCode());
-            result = prime * result
-                    + ((childNodes == null) ? 0 : childNodes.hashCode());
+            result = prime * result + ((targetPath == null) ? 0 : targetPath.hashCode());
+            result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
+            result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode());
             return result;
         }
 
@@ -478,8 +482,7 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
 
         @Override
         public String toString() {
-            StringBuilder sb = new StringBuilder(
-                    AugmentationSchemaImpl.class.getSimpleName());
+            StringBuilder sb = new StringBuilder(AugmentationSchemaImpl.class.getSimpleName());
             sb.append("[");
             sb.append("targetPath=" + targetPath);
             sb.append(", when=" + whenCondition);
index 0761618..1b4283a 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
@@ -27,6 +28,7 @@ import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBui
 import org.opendaylight.controller.yang.parser.builder.api.ConfigNode;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 import org.opendaylight.controller.yang.parser.util.ParserUtils;
 
 public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements DataSchemaNodeBuilder,
@@ -47,17 +49,18 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
     private final Set<ChoiceCaseBuilder> addedCases = new HashSet<ChoiceCaseBuilder>();
     private String defaultCase;
 
-    public ChoiceBuilder(final QName qname, final int line) {
-        super(qname, line);
+    public ChoiceBuilder(final int line, final QName qname) {
+        super(line, qname);
         instance = new ChoiceNodeImpl(qname);
         constraints = new ConstraintsBuilder(line);
     }
 
     public ChoiceBuilder(ChoiceBuilder b) {
-        super(b.getQName(), b.getLine());
+        super(b.getLine(), b.getQName());
+        parent = b.getParent();
         instance = new ChoiceNodeImpl(qname);
-        constraints = b.constraints;
-        path = b.getPath();
+        constraints = b.getConstraints();
+        schemaPath = b.getPath();
         description = b.getDescription();
         reference = b.getReference();
         status = b.getStatus();
@@ -75,7 +78,7 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
     @Override
     public ChoiceNode build() {
         if (!isBuilt) {
-            instance.setPath(path);
+            instance.setPath(schemaPath);
             instance.setDescription(description);
             instance.setReference(reference);
             instance.setStatus(status);
@@ -87,7 +90,7 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
 
             // CASES
             if (cases == null) {
-                cases = new HashSet<ChoiceCaseNode>();
+                cases = new TreeSet<ChoiceCaseNode>(Comparators.SCHEMA_NODE_COMP);
                 for (ChoiceCaseBuilder caseBuilder : addedCases) {
                     cases.add(caseBuilder.build());
                 }
@@ -107,6 +110,7 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                     unknownNodes.add(b.build());
                 }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
             instance.setUnknownSchemaNodes(unknownNodes);
 
@@ -127,7 +131,11 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
 
     public void addChildNode(DataSchemaNodeBuilder childNode) {
         if (!(childNode instanceof ChoiceCaseBuilder)) {
-            ChoiceCaseBuilder caseBuilder = new ChoiceCaseBuilder(this, childNode.getQName(), childNode.getLine());
+            ChoiceCaseBuilder caseBuilder = new ChoiceCaseBuilder(childNode.getLine(), childNode.getQName());
+            if(childNode.isAugmenting()) {
+                caseBuilder.setAugmenting(true);
+                childNode.setAugmenting(false);
+            }
             caseBuilder.setPath(childNode.getPath());
             SchemaPath newPath = ParserUtils.createSchemaPath(childNode.getPath(), childNode.getQName().getLocalName());
             childNode.setPath(newPath);
@@ -142,6 +150,7 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
         this.cases = cases;
     }
 
+    @Override
     public boolean isAugmenting() {
         return augmenting;
     }
@@ -200,6 +209,48 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
         this.defaultCase = defaultCase;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.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;
+        }
+        ChoiceBuilder other = (ChoiceBuilder) obj;
+        if (schemaPath == null) {
+            if (other.schemaPath != null) {
+                return false;
+            }
+        } else if (!schemaPath.equals(other.schemaPath)) {
+            return false;
+        }
+        if (parent == null) {
+            if (other.parent != null) {
+                return false;
+            }
+        } else if (!parent.equals(other.parent)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "choice " + qname.getLocalName();
+    }
+
     public final class ChoiceNodeImpl implements ChoiceNode {
         private final QName qname;
         private SchemaPath path;
index cfd3866..e6c81ab 100644 (file)
@@ -2,11 +2,11 @@ package org.opendaylight.controller.yang.parser.builder.impl;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
@@ -25,14 +25,13 @@ import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBui
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
 public final class ChoiceCaseBuilder extends AbstractDataNodeContainerBuilder implements DataSchemaNodeBuilder,
         AugmentationTargetBuilder {
     private boolean isBuilt;
     private final ChoiceCaseNodeImpl instance;
-    private final ChoiceBuilder parent;
-    private final int line;
     // SchemaNode args
     private SchemaPath schemaPath;
     private String description;
@@ -47,10 +46,8 @@ public final class ChoiceCaseBuilder extends AbstractDataNodeContainerBuilder im
     // AugmentationTarget args
     private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
 
-    ChoiceCaseBuilder(final ChoiceBuilder parent, final QName qname, final int line) {
-        super(qname);
-        this.parent = parent;
-        this.line = line;
+    ChoiceCaseBuilder(final int line, final QName qname) {
+        super(line, qname);
         instance = new ChoiceCaseNodeImpl(qname);
         constraints = new ConstraintsBuilder(line);
     }
@@ -66,7 +63,7 @@ public final class ChoiceCaseBuilder extends AbstractDataNodeContainerBuilder im
             instance.setAugmenting(augmenting);
 
             // CHILD NODES
-            final Map<QName, DataSchemaNode> childs = new HashMap<QName, DataSchemaNode>();
+            final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
             for (DataSchemaNodeBuilder node : addedChildNodes) {
                 childs.put(node.getQName(), node.build());
             }
@@ -84,6 +81,7 @@ public final class ChoiceCaseBuilder extends AbstractDataNodeContainerBuilder im
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             // AUGMENTATIONS
@@ -105,15 +103,6 @@ public final class ChoiceCaseBuilder extends AbstractDataNodeContainerBuilder im
         build();
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
-    public ChoiceBuilder getParent() {
-        return parent;
-    }
-
     public SchemaPath getPath() {
         return schemaPath;
     }
@@ -199,6 +188,48 @@ public final class ChoiceCaseBuilder extends AbstractDataNodeContainerBuilder im
         addedAugmentations.add(augment);
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.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;
+        }
+        ChoiceCaseBuilder other = (ChoiceCaseBuilder) obj;
+        if (schemaPath == null) {
+            if (other.schemaPath != null) {
+                return false;
+            }
+        } else if (!schemaPath.equals(other.schemaPath)) {
+            return false;
+        }
+        if (parent == null) {
+            if (other.parent != null) {
+                return false;
+            }
+        } else if (!parent.equals(other.parent)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "case " + getQName().getLocalName();
+    }
+
     public final class ChoiceCaseNodeImpl implements ChoiceCaseNode {
         private final QName qname;
         private SchemaPath path;
index ebfe520..1351f56 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.yang.parser.util.YangParseException;
 public final class ConstraintsBuilder implements Builder {
     private final ConstraintDefinitionImpl instance;
     private final int line;
+    private Builder parent;
     private final Set<MustDefinition> mustDefinitions;
     private String whenCondition;
     private boolean mandatory;
@@ -54,6 +55,16 @@ public final class ConstraintsBuilder implements Builder {
         return line;
     }
 
+    @Override
+    public Builder getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(final Builder parent) {
+        this.parent = parent;
+    }
+
     @Override
     public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode) {
         throw new YangParseException(line, "Can not add unknown node to constraints.");
@@ -99,6 +110,7 @@ public final class ConstraintsBuilder implements Builder {
         this.mandatory = mandatory;
     }
 
+
     private final class ConstraintDefinitionImpl implements ConstraintDefinition {
         private RevisionAwareXPath whenCondition;
         private Set<MustDefinition> mustConstraints;
@@ -227,7 +239,6 @@ public final class ConstraintsBuilder implements Builder {
             sb.append("]");
             return sb.toString();
         }
-
     }
 
 }
index a194dea..545abea 100644 (file)
@@ -9,11 +9,12 @@ package org.opendaylight.controller.yang.parser.builder.impl;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
@@ -33,15 +34,14 @@ import org.opendaylight.controller.yang.parser.builder.api.ConfigNode;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
-import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionAwareBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerBuilder implements
-        TypeDefinitionAwareBuilder, AugmentationTargetBuilder, DataSchemaNodeBuilder, GroupingMember, ConfigNode {
+        AugmentationTargetBuilder, DataSchemaNodeBuilder, GroupingMember, ConfigNode {
     private boolean isBuilt;
     private final ContainerSchemaNodeImpl instance;
-    private final int line;
 
     // SchemaNode args
     private SchemaPath schemaPath;
@@ -66,17 +66,15 @@ public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerB
     // ContainerSchemaNode args
     private boolean presence;
 
-    public ContainerSchemaNodeBuilder(final QName qname, final SchemaPath schemaPath, final int line) {
-        super(qname);
+    public ContainerSchemaNodeBuilder(final int line, final QName qname, final SchemaPath schemaPath) {
+        super(line, qname);
         this.schemaPath = schemaPath;
-        this.line = line;
         instance = new ContainerSchemaNodeImpl(qname);
         constraints = new ConstraintsBuilder(line);
     }
 
     public ContainerSchemaNodeBuilder(final ContainerSchemaNodeBuilder b) {
-        super(b.getQName());
-        line = b.getLine();
+        super(b.getLine(), b.getQName());
         instance = new ContainerSchemaNodeImpl(b.getQName());
         constraints = b.getConstraints();
         schemaPath = b.getPath();
@@ -112,14 +110,15 @@ public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerB
             instance.setAugmenting(augmenting);
             instance.setAddedByUses(addedByUses);
 
-            // if this builder represents rpc input or output, it can has configuration value set to null
-            if(configuration == null) {
+            // if this builder represents rpc input or output, it can has
+            // configuration value set to null
+            if (configuration == null) {
                 configuration = false;
             }
             instance.setConfiguration(configuration);
 
             // CHILD NODES
-            final Map<QName, DataSchemaNode> childs = new HashMap<QName, DataSchemaNode>();
+            final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
             if (childNodes == null) {
                 for (DataSchemaNodeBuilder node : addedChildNodes) {
                     childs.put(node.getQName(), node.build());
@@ -133,7 +132,7 @@ public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerB
 
             // GROUPINGS
             if (groupings == null) {
-                groupings = new HashSet<GroupingDefinition>();
+                groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
                 for (GroupingBuilder builder : addedGroupings) {
                     groupings.add(builder.build());
                 }
@@ -142,7 +141,7 @@ public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerB
 
             // TYPEDEFS
             if (typedefs == null) {
-                typedefs = new HashSet<TypeDefinition<?>>();
+                typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
                 for (TypeDefinitionBuilder entry : addedTypedefs) {
                     typedefs.add(entry.build());
                 }
@@ -173,6 +172,7 @@ public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerB
                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                     unknownNodes.add(b.build());
                 }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
             instance.setUnknownSchemaNodes(unknownNodes);
 
@@ -190,11 +190,6 @@ public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerB
         build();
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
     @Override
     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
         return addedTypedefs;
@@ -332,9 +327,46 @@ public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerB
         this.unknownNodes = unknownNodes;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.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;
+        }
+        ContainerSchemaNodeBuilder other = (ContainerSchemaNodeBuilder) obj;
+        if (schemaPath == null) {
+            if (other.schemaPath != null) {
+                return false;
+            }
+        } else if (!schemaPath.equals(other.schemaPath)) {
+            return false;
+        }
+        if (parent == null) {
+            if (other.parent != null) {
+                return false;
+            }
+        } else if (!parent.equals(other.parent)) {
+            return false;
+        }
+        return true;
+    }
+
     @Override
     public String toString() {
-        return "container " + getQName().getLocalName();
+        return "container " + qname.getLocalName();
     }
 
     public final class ContainerSchemaNodeImpl implements ContainerSchemaNode {
index 790275c..9b52d61 100644 (file)
@@ -16,12 +16,14 @@ import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.parser.builder.api.Builder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 import org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
 public final class DeviationBuilder implements Builder {
-    private final DeviationImpl instance;
     private final int line;
+    private Builder parent;
+    private final DeviationImpl instance;
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
 
     DeviationBuilder(final String targetPathStr, final int line) {
@@ -38,6 +40,7 @@ public final class DeviationBuilder implements Builder {
         for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
             unknownNodes.add(b.build());
         }
+        Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
         instance.setUnknownSchemaNodes(unknownNodes);
 
         return instance;
@@ -48,6 +51,16 @@ public final class DeviationBuilder implements Builder {
         return line;
     }
 
+    @Override
+    public Builder getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(final Builder parent) {
+        this.parent = parent;
+    }
+
     @Override
     public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode) {
         addedUnknownNodes.add(unknownNode);
index 65fd1c4..a0ee47f 100644 (file)
@@ -17,31 +17,32 @@ import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
     private boolean isBuilt;
     private final ExtensionDefinitionImpl instance;
-    private final List<UnknownSchemaNodeBuilder> addedExtensions = new ArrayList<UnknownSchemaNodeBuilder>();
 
-    ExtensionBuilder(final QName qname, final int line) {
-        super(qname, line);
+    ExtensionBuilder(final int line, final QName qname) {
+        super(line, qname);
         instance = new ExtensionDefinitionImpl(qname);
     }
 
     @Override
     public ExtensionDefinition build() {
-        if(!isBuilt) {
-            instance.setPath(path);
+        if (!isBuilt) {
+            instance.setPath(schemaPath);
             instance.setDescription(description);
             instance.setReference(reference);
             instance.setStatus(status);
 
             // UNKNOWN NODES
-            final List<UnknownSchemaNode> extensions = new ArrayList<UnknownSchemaNode>();
-            for (UnknownSchemaNodeBuilder e : addedExtensions) {
-                extensions.add(e.build());
+            final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+            for (UnknownSchemaNodeBuilder un : addedUnknownNodes) {
+                unknownNodes.add(un.build());
             }
-            instance.setUnknownSchemaNodes(extensions);
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+            instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
         }
@@ -49,11 +50,6 @@ public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
         return instance;
     }
 
-
-    public void addExtension(UnknownSchemaNodeBuilder extension) {
-        addedExtensions.add(extension);
-    }
-
     public void setYinElement(boolean yin) {
         instance.setYinElement(yin);
     }
@@ -62,7 +58,6 @@ public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
         instance.setArgument(argument);
     }
 
-
     private final class ExtensionDefinitionImpl implements ExtensionDefinition {
         private final QName qname;
         private String argument;
@@ -70,8 +65,7 @@ public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
         private String description;
         private String reference;
         private Status status = Status.CURRENT;
-        private List<UnknownSchemaNode> unknownNodes = Collections
-                .emptyList();
+        private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
         private boolean yin;
 
         private ExtensionDefinitionImpl(QName qname) {
@@ -126,9 +120,8 @@ public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
             return unknownNodes;
         }
 
-        private void setUnknownSchemaNodes(
-                List<UnknownSchemaNode> unknownNodes) {
-            if(unknownNodes != null) {
+        private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+            if (unknownNodes != null) {
                 this.unknownNodes = unknownNodes;
             }
         }
@@ -156,8 +149,7 @@ public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
             final int prime = 31;
             int result = 1;
             result = prime * result + ((qname == null) ? 0 : qname.hashCode());
-            result = prime * result
-                    + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+            result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
             return result;
         }
 
@@ -192,10 +184,9 @@ public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
 
         @Override
         public String toString() {
-            StringBuilder sb = new StringBuilder(
-                    ExtensionDefinitionImpl.class.getSimpleName());
+            StringBuilder sb = new StringBuilder(ExtensionDefinitionImpl.class.getSimpleName());
             sb.append("[");
-            sb.append("argument="+ argument);
+            sb.append("argument=" + argument);
             sb.append(", qname=" + qname);
             sb.append(", schemaPath=" + schemaPath);
             sb.append(", extensionSchemaNodes=" + unknownNodes);
index 758478b..c5dd60a 100644 (file)
@@ -17,20 +17,21 @@ import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class FeatureBuilder extends AbstractSchemaNodeBuilder {
     private boolean isBuilt;
     private final FeatureDefinitionImpl instance;
 
-    FeatureBuilder(final QName qname, final int line) {
-        super(qname, line);
+    FeatureBuilder(final int line, final QName qname) {
+        super(line, qname);
         instance = new FeatureDefinitionImpl(qname);
     }
 
     @Override
     public FeatureDefinitionImpl build() {
         if (!isBuilt) {
-            instance.setPath(path);
+            instance.setPath(schemaPath);
             instance.setDescription(description);
             instance.setReference(reference);
             instance.setStatus(status);
@@ -40,6 +41,7 @@ public final class FeatureBuilder extends AbstractSchemaNodeBuilder {
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
index 1cfba25..0f7179e 100644 (file)
@@ -14,6 +14,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
@@ -23,12 +24,15 @@ import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.Builder;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class GroupingBuilderImpl implements GroupingBuilder {
+    private Builder parent;
     private boolean isBuilt;
     private final GroupingDefinitionImpl instance;
     private final int line;
@@ -62,6 +66,7 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
 
     public GroupingBuilderImpl(GroupingBuilder builder) {
         qname = builder.getQName();
+        parent = builder.getParent();
         instance = new GroupingDefinitionImpl(qname);
         line = builder.getLine();
         schemaPath = builder.getPath();
@@ -100,8 +105,8 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
             instance.setChildNodes(childs);
 
             // GROUPINGS
-            if(groupings == null) {
-                groupings = new HashSet<GroupingDefinition>();
+            if (groupings == null) {
+                groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
                 for (GroupingBuilder builder : addedGroupings) {
                     groupings.add(builder.build());
                 }
@@ -109,8 +114,8 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
             instance.setGroupings(groupings);
 
             // TYPEDEFS
-            if(typedefs == null) {
-                typedefs = new HashSet<TypeDefinition<?>>();
+            if (typedefs == null) {
+                typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
                 for (TypeDefinitionBuilder entry : addedTypedefs) {
                     typedefs.add(entry.build());
                 }
@@ -118,7 +123,7 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
             instance.setTypeDefinitions(typedefs);
 
             // USES
-            if(usesNodes == null) {
+            if (usesNodes == null) {
                 usesNodes = new HashSet<UsesNode>();
                 for (UsesNodeBuilder builder : addedUsesNodes) {
                     usesNodes.add(builder.build());
@@ -127,11 +132,12 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
             instance.setUses(usesNodes);
 
             // UNKNOWN NODES
-            if(unknownNodes == null) {
+            if (unknownNodes == null) {
                 unknownNodes = new ArrayList<UnknownSchemaNode>();
                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                     unknownNodes.add(b.build());
                 }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
             instance.setUnknownSchemaNodes(unknownNodes);
 
@@ -146,6 +152,16 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
         return line;
     }
 
+    @Override
+    public Builder getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(final Builder parent) {
+        this.parent = parent;
+    }
+
     @Override
     public QName getQName() {
         return qname;
@@ -293,7 +309,6 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
         this.unknownNodes = unknownNodes;
     }
 
-
     private final class GroupingDefinitionImpl implements GroupingDefinition {
         private final QName qname;
         private SchemaPath path;
@@ -363,7 +378,9 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
 
         @Override
         public Set<DataSchemaNode> getChildNodes() {
-            return new HashSet<DataSchemaNode>(childNodes.values());
+            final Set<DataSchemaNode> result = new TreeSet<DataSchemaNode>(Comparators.SCHEMA_NODE_COMP);
+            result.addAll(childNodes.values());
+            return result;
         }
 
         private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
@@ -465,8 +482,7 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
 
         @Override
         public String toString() {
-            StringBuilder sb = new StringBuilder(
-                    GroupingDefinitionImpl.class.getSimpleName());
+            StringBuilder sb = new StringBuilder(GroupingDefinitionImpl.class.getSimpleName());
             sb.append("[");
             sb.append("qname=" + qname);
             sb.append("]");
index 9cce264..14fca7d 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class IdentitySchemaNodeBuilder extends AbstractSchemaNodeBuilder {
     private boolean isBuilt;
@@ -25,15 +26,15 @@ public final class IdentitySchemaNodeBuilder extends AbstractSchemaNodeBuilder {
     private IdentitySchemaNode baseIdentity;
     private String baseIdentityName;
 
-    IdentitySchemaNodeBuilder(final QName qname, final int line) {
-        super(qname, line);
+    IdentitySchemaNodeBuilder(final int line, final QName qname) {
+        super(line, qname);
         instance = new IdentitySchemaNodeImpl(qname);
     }
 
     @Override
     public IdentitySchemaNode build() {
         if (!isBuilt) {
-            instance.setPath(path);
+            instance.setPath(schemaPath);
             instance.setDescription(description);
             instance.setReference(reference);
             instance.setStatus(status);
@@ -51,6 +52,7 @@ public final class IdentitySchemaNodeBuilder extends AbstractSchemaNodeBuilder {
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
index ea504af..3b50596 100644 (file)
@@ -32,13 +32,12 @@ import org.opendaylight.controller.yang.parser.util.YangParseException;
 public final class IdentityrefTypeBuilder extends AbstractTypeAwareBuilder implements TypeDefinitionBuilder {
     private static final String NAME = "identityref";
 
-    private final int line;
     private final String baseString;
     private final SchemaPath schemaPath;
     private QName baseQName;
 
     IdentityrefTypeBuilder(final String baseString, final SchemaPath schemaPath, final int line) {
-        this.line = line;
+        super(line, null);
         this.baseString = baseString;
         this.schemaPath = schemaPath;
     }
@@ -56,11 +55,6 @@ public final class IdentityrefTypeBuilder extends AbstractTypeAwareBuilder imple
         this.baseQName = baseQName;
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
     @Override
     public TypeDefinition<?> getType() {
         return null;
index 9bbe5e9..555a326 100644 (file)
@@ -22,14 +22,13 @@ import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuil
 import org.opendaylight.controller.yang.parser.builder.api.ConfigNode;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder implements DataSchemaNodeBuilder,
         GroupingMember, ConfigNode {
     private boolean isBuilt;
     private final LeafListSchemaNodeImpl instance;
-    private final int line;
     // SchemaNode args
-    private final QName qname;
     private SchemaPath schemaPath;
     private String description;
     private String reference;
@@ -44,17 +43,15 @@ public final class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder im
     // LeafListSchemaNode args
     private boolean userOrdered;
 
-    public LeafListSchemaNodeBuilder(final QName qname, final SchemaPath schemaPath, final int line) {
-        this.qname = qname;
+    public LeafListSchemaNodeBuilder(final int line, final QName qname, final SchemaPath schemaPath) {
+        super(line, qname);
         this.schemaPath = schemaPath;
-        this.line = line;
         instance = new LeafListSchemaNodeImpl(qname);
         constraints = new ConstraintsBuilder(line);
     }
 
     public LeafListSchemaNodeBuilder(final LeafListSchemaNodeBuilder b) {
-        qname = b.getQName();
-        line = b.getLine();
+        super(b.getLine(), b.getQName());
         instance = new LeafListSchemaNodeImpl(qname);
 
         type = b.getType();
@@ -98,6 +95,7 @@ public final class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder im
                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                     unknownNodes.add(b.build());
                 }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
             instance.setUnknownSchemaNodes(unknownNodes);
 
@@ -106,16 +104,6 @@ public final class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder im
         return instance;
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
-    @Override
-    public QName getQName() {
-        return qname;
-    }
-
     public SchemaPath getPath() {
         return schemaPath;
     }
@@ -208,6 +196,48 @@ public final class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder im
         this.unknownNodes = unknownNodes;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.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;
+        }
+        LeafListSchemaNodeBuilder other = (LeafListSchemaNodeBuilder) obj;
+        if (schemaPath == null) {
+            if (other.schemaPath != null) {
+                return false;
+            }
+        } else if (!schemaPath.equals(other.schemaPath)) {
+            return false;
+        }
+        if (parent == null) {
+            if (other.parent != null) {
+                return false;
+            }
+        } else if (!parent.equals(other.parent)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "leaf-list " + qname.getLocalName();
+    }
+
     private final class LeafListSchemaNodeImpl implements LeafListSchemaNode {
         private final QName qname;
         private SchemaPath path;
index 54720b4..071447b 100644 (file)
@@ -22,15 +22,14 @@ import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuil
 import org.opendaylight.controller.yang.parser.builder.api.ConfigNode;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implements DataSchemaNodeBuilder,
         GroupingMember, ConfigNode {
     private boolean isBuilt;
     private final LeafSchemaNodeImpl instance;
-    private final int line;
     // SchemaNode args
-    private final QName qname;
-    private SchemaPath path;
+    private SchemaPath schemaPath;
     private String description;
     private String reference;
     private Status status = Status.CURRENT;
@@ -46,19 +45,17 @@ public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implem
     private String unitsStr;
 
     public LeafSchemaNodeBuilder(final QName qname, final SchemaPath schemaPath, final int line) {
-        this.qname = qname;
-        this.path = schemaPath;
-        this.line = line;
+        super(line, qname);
+        this.schemaPath = schemaPath;
         instance = new LeafSchemaNodeImpl(qname);
         constraints = new ConstraintsBuilder(line);
     }
 
     public LeafSchemaNodeBuilder(final LeafSchemaNodeBuilder b) {
-        qname = b.getQName();
-        line = b.getLine();
+        super(b.getLine(), b.getQName());
         instance = new LeafSchemaNodeImpl(qname);
         constraints = b.getConstraints();
-        path = b.getPath();
+        schemaPath = b.getPath();
 
         type = b.getType();
         typedef = b.getTypedef();
@@ -79,7 +76,7 @@ public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implem
     @Override
     public LeafSchemaNode build() {
         if (!isBuilt) {
-            instance.setPath(path);
+            instance.setPath(schemaPath);
             instance.setConstraints(constraints.build());
             instance.setDescription(description);
             instance.setReference(reference);
@@ -103,6 +100,7 @@ public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implem
                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                     unknownNodes.add(b.build());
                 }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
             instance.setUnknownSchemaNodes(unknownNodes);
 
@@ -111,23 +109,13 @@ public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implem
         return instance;
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
-    @Override
-    public QName getQName() {
-        return qname;
-    }
-
     public SchemaPath getPath() {
-        return path;
+        return schemaPath;
     }
 
     @Override
     public void setPath(final SchemaPath path) {
-        this.path = path;
+        this.schemaPath = path;
     }
 
     @Override
@@ -221,6 +209,43 @@ public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implem
         this.unitsStr = unitsStr;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.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;
+        }
+        LeafSchemaNodeBuilder other = (LeafSchemaNodeBuilder) obj;
+        if (schemaPath == null) {
+            if (other.schemaPath != null) {
+                return false;
+            }
+        } else if (!schemaPath.equals(other.schemaPath)) {
+            return false;
+        }
+        if (parent == null) {
+            if (other.parent != null) {
+                return false;
+            }
+        } else if (!parent.equals(other.parent)) {
+            return false;
+        }
+        return true;
+    }
+
     @Override
     public String toString() {
         return "leaf " + qname.getLocalName();
index ce87e3b..a99e6a7 100644 (file)
@@ -9,11 +9,12 @@ package org.opendaylight.controller.yang.parser.builder.impl;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
@@ -33,15 +34,14 @@ import org.opendaylight.controller.yang.parser.builder.api.ConfigNode;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
-import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionAwareBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilder implements DataSchemaNodeBuilder,
-        AugmentationTargetBuilder, TypeDefinitionAwareBuilder, GroupingMember, ConfigNode {
+        AugmentationTargetBuilder, GroupingMember, ConfigNode {
     private boolean isBuilt;
     private final ListSchemaNodeImpl instance;
-    private final int line;
     // SchemaNode args
     private SchemaPath schemaPath;
     private String description;
@@ -66,17 +66,15 @@ public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilde
     private List<QName> keyDefinition = Collections.emptyList();
     private boolean userOrdered;
 
-    public ListSchemaNodeBuilder(final QName qname, final SchemaPath schemaPath, final int line) {
-        super(qname);
+    public ListSchemaNodeBuilder(final int line, final QName qname, final SchemaPath schemaPath) {
+        super(line, qname);
         this.schemaPath = schemaPath;
-        this.line = line;
         instance = new ListSchemaNodeImpl(qname);
         constraints = new ConstraintsBuilder(line);
     }
 
     public ListSchemaNodeBuilder(final ListSchemaNodeBuilder b) {
-        super(b.getQName());
-        line = b.getLine();
+        super(b.getLine(), b.getQName());
         instance = new ListSchemaNodeImpl(b.getQName());
         constraints = b.getConstraints();
         schemaPath = b.getPath();
@@ -116,7 +114,7 @@ public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilde
             instance.setUserOrdered(userOrdered);
 
             // CHILD NODES
-            final Map<QName, DataSchemaNode> childs = new HashMap<QName, DataSchemaNode>();
+            final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
             if (childNodes == null) {
                 for (DataSchemaNodeBuilder node : addedChildNodes) {
                     childs.put(node.getQName(), node.build());
@@ -130,7 +128,7 @@ public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilde
 
             // TYPEDEFS
             if (typedefs == null) {
-                typedefs = new HashSet<TypeDefinition<?>>();
+                typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
                 for (TypeDefinitionBuilder entry : addedTypedefs) {
                     typedefs.add(entry.build());
                 }
@@ -148,7 +146,7 @@ public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilde
 
             // GROUPINGS
             if (groupings == null) {
-                groupings = new HashSet<GroupingDefinition>();
+                groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
                 for (GroupingBuilder builder : addedGroupings) {
                     groupings.add(builder.build());
                 }
@@ -170,6 +168,7 @@ public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilde
                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                     unknownNodes.add(b.build());
                 }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
             instance.setUnknownSchemaNodes(unknownNodes);
 
@@ -187,11 +186,6 @@ public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilde
         build();
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
     @Override
     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
         return addedTypedefs;
@@ -334,6 +328,48 @@ public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilde
         this.unknownNodes = unknownNodes;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.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;
+        }
+        ListSchemaNodeBuilder other = (ListSchemaNodeBuilder) obj;
+        if (schemaPath == null) {
+            if (other.schemaPath != null) {
+                return false;
+            }
+        } else if (!schemaPath.equals(other.schemaPath)) {
+            return false;
+        }
+        if (parent == null) {
+            if (other.parent != null) {
+                return false;
+            }
+        } else if (!parent.equals(other.parent)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "list " + qname.getLocalName();
+    }
+
     public final class ListSchemaNodeImpl implements ListSchemaNode {
         private final QName qname;
         private SchemaPath path;
index 0a9b6dd..57e87b3 100644 (file)
@@ -13,10 +13,13 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
@@ -41,9 +44,9 @@ import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
-import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionAwareBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 import org.opendaylight.controller.yang.parser.util.RefineHolder;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
@@ -67,17 +70,19 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
      * Holds all child (DataSchemaNode) nodes: anyxml, choice, case, container,
      * list, leaf, leaf-list.
      */
-    private final Map<List<String>, DataSchemaNodeBuilder> childNodes = new HashMap<List<String>, DataSchemaNodeBuilder>();
+    private final Set<DataSchemaNodeBuilder> childNodes = new HashSet<DataSchemaNodeBuilder>();
 
-    private final Map<List<String>, GroupingBuilder> addedGroupings = new HashMap<List<String>, GroupingBuilder>();
+    private final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
     private final List<AugmentationSchemaBuilder> addedAugments = new ArrayList<AugmentationSchemaBuilder>();
-    private final Map<List<String>, UsesNodeBuilder> addedUsesNodes = new HashMap<List<String>, UsesNodeBuilder>();
-    private final Map<List<String>, RpcDefinitionBuilder> addedRpcs = new HashMap<List<String>, RpcDefinitionBuilder>();
+    private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<AugmentationSchemaBuilder>();
+    private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
+    private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<UsesNodeBuilder>();
+    private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<RpcDefinitionBuilder>();
     private final Set<NotificationBuilder> addedNotifications = new HashSet<NotificationBuilder>();
     private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<IdentitySchemaNodeBuilder>();
-    private final Map<List<String>, FeatureBuilder> addedFeatures = new HashMap<List<String>, FeatureBuilder>();
+    private final Set<FeatureBuilder> addedFeatures = new HashSet<FeatureBuilder>();
     private final Map<List<String>, DeviationBuilder> addedDeviations = new HashMap<List<String>, DeviationBuilder>();
-    private final Map<List<String>, TypeDefinitionBuilder> addedTypedefs = new HashMap<List<String>, TypeDefinitionBuilder>();
+    private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
     private final Map<List<String>, UnionTypeBuilder> addedUnionTypes = new HashMap<List<String>, UnionTypeBuilder>();
     private final List<ExtensionBuilder> addedExtensions = new ArrayList<ExtensionBuilder>();
     private final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes = new HashMap<List<String>, List<UnknownSchemaNodeBuilder>>();
@@ -102,27 +107,43 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         instance.setNamespace(namespace);
 
         // TYPEDEFS
-        final Set<TypeDefinition<?>> typedefs = buildModuleTypedefs(addedTypedefs);
+        final Set<TypeDefinition<?>> typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
+        for (TypeDefinitionBuilder tdb : addedTypedefs) {
+            typedefs.add(tdb.build());
+        }
         instance.setTypeDefinitions(typedefs);
 
         // CHILD NODES
-        final Map<QName, DataSchemaNode> children = buildModuleChildNodes(childNodes);
+        final Map<QName, DataSchemaNode> children = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+        for (DataSchemaNodeBuilder child : childNodes) {
+            children.put(child.getQName(), child.build());
+        }
         instance.setChildNodes(children);
 
         // GROUPINGS
-        final Set<GroupingDefinition> groupings = buildModuleGroupings(addedGroupings);
+        final Set<GroupingDefinition> groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
+        for (GroupingBuilder gb : addedGroupings) {
+            groupings.add(gb.build());
+        }
         instance.setGroupings(groupings);
 
         // USES
-        final Set<UsesNode> usesDefinitions = buildUsesNodes(addedUsesNodes);
+        final Set<UsesNode> usesDefinitions = new HashSet<UsesNode>();
+        for (UsesNodeBuilder unb : addedUsesNodes) {
+            usesDefinitions.add(unb.build());
+        }
         instance.setUses(usesDefinitions);
 
         // FEATURES
-        final Set<FeatureDefinition> features = buildModuleFeatures(addedFeatures);
+        final Set<FeatureDefinition> features = new TreeSet<FeatureDefinition>(Comparators.SCHEMA_NODE_COMP);
+        for (FeatureBuilder fb : addedFeatures) {
+            features.add(fb.build());
+        }
         instance.setFeatures(features);
 
         // NOTIFICATIONS
-        final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
+        final Set<NotificationDefinition> notifications = new TreeSet<NotificationDefinition>(
+                Comparators.SCHEMA_NODE_COMP);
         for (NotificationBuilder entry : addedNotifications) {
             notifications.add(entry.build());
         }
@@ -136,7 +157,10 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         instance.setAugmentations(augmentations);
 
         // RPCs
-        final Set<RpcDefinition> rpcs = buildModuleRpcs(addedRpcs);
+        final Set<RpcDefinition> rpcs = new TreeSet<RpcDefinition>(Comparators.SCHEMA_NODE_COMP);
+        for (RpcDefinitionBuilder rpc : addedRpcs) {
+            rpcs.add(rpc.build());
+        }
         instance.setRpcs(rpcs);
 
         // DEVIATIONS
@@ -148,15 +172,16 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
 
         // EXTENSIONS
         final List<ExtensionDefinition> extensions = new ArrayList<ExtensionDefinition>();
-        for (ExtensionBuilder b : addedExtensions) {
-            extensions.add(b.build());
+        for (ExtensionBuilder eb : addedExtensions) {
+            extensions.add(eb.build());
         }
+        Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
         instance.setExtensionSchemaNodes(extensions);
 
         // IDENTITIES
-        final Set<IdentitySchemaNode> identities = new HashSet<IdentitySchemaNode>();
-        for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
-            identities.add(idBuilder.build());
+        final Set<IdentitySchemaNode> identities = new TreeSet<IdentitySchemaNode>(Comparators.SCHEMA_NODE_COMP);
+        for (IdentitySchemaNodeBuilder id : addedIdentities) {
+            identities.add(id.build());
         }
         instance.setIdentities(identities);
 
@@ -172,6 +197,16 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         return 0;
     }
 
+    @Override
+    public Builder getParent() {
+        return null;
+    }
+
+    @Override
+    public void setParent(Builder parent) {
+        throw new YangParseException(name, 0, "Can not set parent to module");
+    }
+
     @Override
     public QName getQName() {
         return new QName(namespace, revision, prefix, name);
@@ -184,16 +219,7 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
 
     @Override
     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
-        final Set<TypeDefinitionBuilder> typeDefinitions = new HashSet<TypeDefinitionBuilder>();
-        for (final Map.Entry<List<String>, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) {
-            final List<String> key = entry.getKey();
-            final TypeDefinitionBuilder typedefBuilder = entry.getValue();
-            if (key.size() == 2) {
-                typeDefinitions.add(typedefBuilder);
-
-            }
-        }
-        return typeDefinitions;
+        return addedTypedefs;
     }
 
     public void enterNode(final Builder node) {
@@ -220,14 +246,6 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         }
     }
 
-    public Builder getModuleNode(final List<String> path) {
-        return childNodes.get(path);
-    }
-
-    public GroupingBuilder getGrouping(final List<String> path) {
-        return addedGroupings.get(path);
-    }
-
     @Override
     public Set<GroupingDefinition> getGroupings() {
         return Collections.emptySet();
@@ -235,17 +253,7 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
 
     @Override
     public Set<GroupingBuilder> getGroupingBuilders() {
-        final Set<GroupingBuilder> result = new HashSet<GroupingBuilder>();
-        for (Map.Entry<List<String>, GroupingBuilder> entry : addedGroupings.entrySet()) {
-            if (entry.getKey().size() == 2) {
-                result.add(entry.getValue());
-            }
-        }
-        return result;
-    }
-
-    public Builder getModuleTypedef(final List<String> path) {
-        return addedTypedefs.get(path);
+        return addedGroupings;
     }
 
     @Override
@@ -254,31 +262,23 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
     }
 
     public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
-        final Set<DataSchemaNodeBuilder> children = new HashSet<DataSchemaNodeBuilder>();
-        for (Map.Entry<List<String>, DataSchemaNodeBuilder> entry : childNodes.entrySet()) {
-            final List<String> path = entry.getKey();
-            final DataSchemaNodeBuilder child = entry.getValue();
-            if (path.size() == 2) {
-                children.add(child);
-            }
-        }
-        return children;
+        return childNodes;
     }
 
     public Map<List<String>, TypeAwareBuilder> getDirtyNodes() {
         return dirtyNodes;
     }
 
-    public List<AugmentationSchemaBuilder> getAugments() {
-        return addedAugments;
+    public List<AugmentationSchemaBuilder> getAllAugments() {
+        return allAugments;
     }
 
     public Set<IdentitySchemaNodeBuilder> getIdentities() {
         return addedIdentities;
     }
 
-    public Map<List<String>, UsesNodeBuilder> getUsesNodes() {
-        return addedUsesNodes;
+    public List<UsesNodeBuilder> getAllUsesNodes() {
+        return allUsesNodes;
     }
 
     public List<UnknownSchemaNodeBuilder> getUnknownNodes() {
@@ -289,26 +289,6 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         return result;
     }
 
-    public Set<TypeDefinitionBuilder> getModuleTypedefs() {
-        final Set<TypeDefinitionBuilder> typedefs = new HashSet<TypeDefinitionBuilder>();
-        for (Map.Entry<List<String>, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) {
-            if (entry.getKey().size() == 2) {
-                typedefs.add(entry.getValue());
-            }
-        }
-        return typedefs;
-    }
-
-    public Set<GroupingBuilder> getModuleGroupings() {
-        final Set<GroupingBuilder> groupings = new HashSet<GroupingBuilder>();
-        for (Map.Entry<List<String>, GroupingBuilder> entry : addedGroupings.entrySet()) {
-            if (entry.getKey().size() == 2) {
-                groupings.add(entry.getValue());
-            }
-        }
-        return groupings;
-    }
-
     public String getName() {
         return name;
     }
@@ -381,159 +361,158 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
     }
 
     public ExtensionBuilder addExtension(final QName qname, final int line) {
-        final ExtensionBuilder builder = new ExtensionBuilder(qname, line);
+        final ExtensionBuilder builder = new ExtensionBuilder(line, qname);
         addedExtensions.add(builder);
         return builder;
     }
 
     @Override
     public void addChildNode(DataSchemaNodeBuilder child) {
-        final List<String> pathToChild = new ArrayList<String>();
-        for (QName qname : child.getPath().getPath()) {
-            pathToChild.add(qname.getLocalName());
-        }
-        if (childNodes.containsKey(pathToChild)) {
-            throw new YangParseException(this.name, child.getLine(), "Failed to add child node "
-                    + child.getQName().getLocalName() + ": node already exists in context.");
+        for (DataSchemaNodeBuilder childNode : childNodes) {
+            if (childNode.getQName().getLocalName().equals(child.getQName().getLocalName())) {
+                throw new YangParseException(name, child.getLine(), "Duplicate node found at line "
+                        + childNode.getLine());
+            }
         }
-        childNodes.put(pathToChild, child);
+        childNodes.add(child);
     }
 
-    public ContainerSchemaNodeBuilder addContainerNode(final SchemaPath schemaPath, final QName containerName,
-            final List<String> parentPath, final int line) {
-        final List<String> pathToNode = new ArrayList<String>(parentPath);
-        final ContainerSchemaNodeBuilder containerBuilder = new ContainerSchemaNodeBuilder(containerName, schemaPath, line);
-        updateParent(containerBuilder, line, "container");
+    public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName containerName,
+            final SchemaPath schemaPath) {
+        final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(line, containerName, schemaPath);
 
-        pathToNode.add(containerName.getLocalName());
-        childNodes.put(pathToNode, containerBuilder);
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+        addChildToParent(parent, builder, containerName.getLocalName());
 
-        return containerBuilder;
+        return builder;
     }
 
-    public ListSchemaNodeBuilder addListNode(final SchemaPath schemaPath, final QName listName, final List<String> parentPath, final int line) {
-        final List<String> pathToNode = new ArrayList<String>(parentPath);
-        final ListSchemaNodeBuilder listBuilder = new ListSchemaNodeBuilder(listName, schemaPath, line);
-        updateParent(listBuilder, line, "list");
+    public ListSchemaNodeBuilder addListNode(final int line, final QName listName, final SchemaPath schemaPath) {
+        final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(line, listName, schemaPath);
 
-        pathToNode.add(listName.getLocalName());
-        childNodes.put(pathToNode, listBuilder);
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+        addChildToParent(parent, builder, listName.getLocalName());
 
-        return listBuilder;
+        return builder;
     }
 
-    public LeafSchemaNodeBuilder addLeafNode(final SchemaPath schemaPath, final QName leafName, final List<String> parentPath, final int line) {
-        final List<String> pathToNode = new ArrayList<String>(parentPath);
-        final LeafSchemaNodeBuilder leafBuilder = new LeafSchemaNodeBuilder(leafName, schemaPath, line);
-        updateParent(leafBuilder, line, "leaf");
+    public LeafSchemaNodeBuilder addLeafNode(final int line, final QName leafName, final SchemaPath schemaPath) {
+        final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(leafName, schemaPath, line);
 
-        pathToNode.add(leafName.getLocalName());
-        childNodes.put(pathToNode, leafBuilder);
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+        addChildToParent(parent, builder, leafName.getLocalName());
 
-        return leafBuilder;
+        return builder;
     }
 
-    public LeafListSchemaNodeBuilder addLeafListNode(final SchemaPath schemaPath, final QName qname, final List<String> parentPath, final int line) {
-        final List<String> pathToNode = new ArrayList<String>(parentPath);
-        final LeafListSchemaNodeBuilder leafListBuilder = new LeafListSchemaNodeBuilder(qname, schemaPath, line);
-        updateParent(leafListBuilder, line, "leaf-list");
+    public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName leafListName,
+            final SchemaPath schemaPath) {
+        final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(line, leafListName, schemaPath);
 
-        pathToNode.add(qname.getLocalName());
-        childNodes.put(pathToNode, leafListBuilder);
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+        addChildToParent(parent, builder, leafListName.getLocalName());
 
-        return leafListBuilder;
+        return builder;
     }
 
     @Override
     public void addGrouping(GroupingBuilder groupingBuilder) {
-        final List<String> pathToGroup = new ArrayList<String>();
-        for (QName qname : groupingBuilder.getPath().getPath()) {
-            pathToGroup.add(qname.getLocalName());
-        }
-        if (addedGroupings.containsKey(pathToGroup)) {
-            throw new YangParseException(this.name, groupingBuilder.getLine(), "Failed to add grouping "
-                    + groupingBuilder.getQName().getLocalName() + ": grouping already exists in context.");
+        for (GroupingBuilder gb : addedGroupings) {
+            if (gb.getQName().getLocalName().equals(groupingBuilder.getQName().getLocalName())) {
+                throw new YangParseException(name, groupingBuilder.getLine(), "Duplicate node found at line "
+                        + gb.getLine());
+            }
         }
-        addedGroupings.put(pathToGroup, groupingBuilder);
+        addedGroupings.add(groupingBuilder);
     }
 
-    public GroupingBuilder addGrouping(final QName qname, final List<String> parentPath, final int line) {
-        final List<String> pathToGroup = new ArrayList<String>(parentPath);
+    public GroupingBuilder addGrouping(final int line, final QName qname) {
         final GroupingBuilder builder = new GroupingBuilderImpl(qname, line);
 
-        if (!(actualPath.isEmpty())) {
-            final Builder parent = actualPath.getFirst();
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+
+        if (parent == null) {
+            for (GroupingBuilder child : addedGroupings) {
+                if (child.getQName().getLocalName().equals(qname.getLocalName())) {
+                    throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
+                }
+            }
+            addedGroupings.add(builder);
+        } else {
             if (parent instanceof DataNodeContainerBuilder) {
-                ((DataNodeContainerBuilder) parent).addGrouping(builder);
+                DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
+                for (DataSchemaNodeBuilder child : parentNode.getChildNodeBuilders()) {
+                    if (child.getQName().getLocalName().equals(qname.getLocalName())) {
+                        throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
+                    }
+                }
+                parentNode.addGrouping(builder);
+            } else if (parent instanceof RpcDefinitionBuilder) {
+                RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parent;
+                for (GroupingBuilder child : parentNode.getGroupings()) {
+                    if (child.getQName().getLocalName().equals(qname.getLocalName())) {
+                        throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
+                    }
+                }
+                parentNode.addGrouping(builder);
             } else {
                 throw new YangParseException(name, line, "Unresolved parent of grouping " + qname.getLocalName());
             }
         }
 
-        pathToGroup.add(qname.getLocalName());
-        addedGroupings.put(pathToGroup, builder);
-
         return builder;
     }
 
-    public AugmentationSchemaBuilder addAugment(final String name, final List<String> parentPath, final int line) {
-        final List<String> pathToAugment = new ArrayList<String>(parentPath);
-        Builder parent = null;
-        if (!(actualPath.isEmpty())) {
-            parent = actualPath.getFirst();
-        }
-        final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name, line, parent);
+    public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr) {
+        final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(line, augmentTargetStr);
 
-        // augment can only be in 'module' or 'uses' statement
-        if (parent != null) {
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+
+        if (parent == null) {
+            addedAugments.add(builder);
+        } else {
+            // augment can only be in 'module' or 'uses' statement
             if (parent instanceof UsesNodeBuilder) {
                 ((UsesNodeBuilder) parent).addAugment(builder);
             } else {
-                throw new YangParseException(this.name, line, "Unresolved parent of augment " + name);
+                throw new YangParseException(name, line, "Augment can be declared only under module or uses.");
             }
         }
-
-        pathToAugment.add(name);
-        addedAugments.add(builder);
+        allAugments.add(builder);
 
         return builder;
     }
 
     @Override
     public void addUsesNode(UsesNodeBuilder usesBuilder) {
-        final List<String> pathToTypedef = new ArrayList<String>();
-        for (QName qname : usesBuilder.getParent().getPath().getPath()) {
-            pathToTypedef.add(qname.getLocalName());
-        }
-        if (addedUsesNodes.containsKey(pathToTypedef)) {
-            throw new YangParseException(this.name, usesBuilder.getLine(), "Failed to add uses node "
-                    + usesBuilder.getGroupingName() + ": uses already exists in context.");
-        }
-        addedUsesNodes.put(pathToTypedef, usesBuilder);
+        addedUsesNodes.add(usesBuilder);
+        allUsesNodes.add(usesBuilder);
     }
 
-    public UsesNodeBuilder addUsesNode(final String groupingPathStr, final List<String> parentPath, final int line) {
-        final List<String> pathToUses = new ArrayList<String>(parentPath);
-        Builder parent = null;
-        if (!actualPath.isEmpty()) {
-            parent = actualPath.getFirst();
-        }
-        if (parent != null && !(parent instanceof DataNodeContainerBuilder)) {
-            throw new YangParseException(name, line, "Unresolved parent of uses " + groupingPathStr);
-        }
-        final UsesNodeBuilder usesBuilder;
+    public UsesNodeBuilder addUsesNode(final int line, final String groupingPathStr) {
+        final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(line, groupingPathStr);
+
+        Builder parent = getActualNode();
+        usesBuilder.setParent(parent);
+
         if (parent == null) {
-            usesBuilder = new UsesNodeBuilderImpl(groupingPathStr, line, this);
+            addedUsesNodes.add(usesBuilder);
         } else {
-            usesBuilder = new UsesNodeBuilderImpl(groupingPathStr, line, (DataNodeContainerBuilder) parent);
+            if (!(parent instanceof DataNodeContainerBuilder)) {
+                throw new YangParseException(name, line, "Unresolved parent of uses '" + groupingPathStr + "'.");
+            }
             if (parent instanceof AugmentationSchemaBuilder) {
                 usesBuilder.setAugmenting(true);
             }
             ((DataNodeContainerBuilder) parent).addUsesNode(usesBuilder);
         }
-
-        pathToUses.add(groupingPathStr);
-        addedUsesNodes.put(pathToUses, usesBuilder);
+        allUsesNodes.add(usesBuilder);
         return usesBuilder;
     }
 
@@ -543,40 +522,44 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         if (actualPath.isEmpty()) {
             throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
         } else {
-            final Builder parent = actualPath.getFirst();
+            final Builder parent = getActualNode();
             if (parent instanceof UsesNodeBuilder) {
                 ((UsesNodeBuilder) parent).addRefine(refine);
             } else {
                 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
             }
+            refine.setParent(parent);
         }
 
         path.add(refine.getName());
     }
 
-    public RpcDefinitionBuilder addRpc(final QName qname, final List<String> parentPath, final int line) {
-
-        if (!(actualPath.isEmpty())) {
+    public RpcDefinitionBuilder addRpc(final int line, final QName qname) {
+        Builder parent = getActualNode();
+        if (parent != null) {
             throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
         }
 
-        final List<String> pathToRpc = new ArrayList<String>(parentPath);
-        final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(qname, line);
-
-        pathToRpc.add(qname.getLocalName());
-        addedRpcs.put(pathToRpc, rpcBuilder);
-
+        final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(line, qname);
+        for (RpcDefinitionBuilder rpc : addedRpcs) {
+            if (rpc.getQName().getLocalName().equals(qname.getLocalName())) {
+                throw new YangParseException(name, line, "Duplicate node found at line " + rpc.getLine());
+            }
+        }
+        addedRpcs.add(rpcBuilder);
         return rpcBuilder;
     }
 
     public ContainerSchemaNodeBuilder addRpcInput(final SchemaPath schemaPath, final QName inputQName, final int line) {
-        final Builder parent = actualPath.getFirst();
+        final Builder parent = getActualNode();
         if (!(parent instanceof RpcDefinitionBuilder)) {
             throw new YangParseException(name, line, "input can be defined only in rpc statement");
         }
         final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
 
-        final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(inputQName, schemaPath, line);
+        final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(line, inputQName, schemaPath);
+        inputBuilder.setParent(rpc);
+
         rpc.setInput(inputBuilder);
         return inputBuilder;
     }
@@ -588,7 +571,9 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         }
         final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
 
-        final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(outputQName, schemaPath, line);
+        final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(line, outputQName, schemaPath);
+        outputBuilder.setParent(rpc);
+
         rpc.setOutput(outputBuilder);
         return outputBuilder;
     }
@@ -598,132 +583,132 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         if (!(actualPath.isEmpty())) {
             throw new YangParseException(name, line, "notification can be defined only in module or submodule");
         }
-        final NotificationBuilder builder = new NotificationBuilder(notificationName, line);
+        for (NotificationBuilder nb : addedNotifications) {
+            if (nb.getQName().equals(notificationName)) {
+                throw new YangParseException(name, line, "Duplicate node found at line " + nb.getLine());
+            }
+        }
 
-        final List<String> notificationPath = new ArrayList<String>(parentPath);
-        notificationPath.add(notificationName.getLocalName());
+        final NotificationBuilder builder = new NotificationBuilder(line, notificationName);
         addedNotifications.add(builder);
 
         return builder;
     }
 
-    public FeatureBuilder addFeature(final QName featureName, final List<String> parentPath, final int line) {
-        if (!(actualPath.isEmpty())) {
+    public FeatureBuilder addFeature(final int line, final QName featureName) {
+        Builder parent = getActualNode();
+        if (parent != null) {
             throw new YangParseException(name, line, "feature can be defined only in module or submodule");
         }
 
-        final List<String> pathToFeature = new ArrayList<String>(parentPath);
-        pathToFeature.add(featureName.getLocalName());
-
-        final FeatureBuilder builder = new FeatureBuilder(featureName, line);
-        addedFeatures.put(pathToFeature, builder);
+        final FeatureBuilder builder = new FeatureBuilder(line, featureName);
+        for (FeatureBuilder fb : addedFeatures) {
+            if (fb.getQName().getLocalName().equals(featureName.getLocalName())) {
+                throw new YangParseException(name, line, "Duplicate node found at line " + fb.getLine());
+            }
+        }
+        addedFeatures.add(builder);
         return builder;
     }
 
-    public ChoiceBuilder addChoice(final QName choiceName, final List<String> parentPath, final int line) {
-        final List<String> pathToChoice = new ArrayList<String>(parentPath);
-        final ChoiceBuilder builder = new ChoiceBuilder(choiceName, line);
+    public ChoiceBuilder addChoice(final int line, final QName choiceName) {
+        final ChoiceBuilder builder = new ChoiceBuilder(line, choiceName);
 
-        if (!(actualPath.isEmpty())) {
-            final Builder parent = actualPath.getFirst();
-            if (parent instanceof DataNodeContainerBuilder) {
-                if (parent instanceof AugmentationSchemaBuilder) {
-                    builder.setAugmenting(true);
-                }
-                ((DataNodeContainerBuilder) parent).addChildNode(builder);
-            } else {
-                throw new YangParseException(name, line, "Unresolved parent of choice " + choiceName.getLocalName());
-            }
-        }
-
-        pathToChoice.add(choiceName.getLocalName());
-        childNodes.put(pathToChoice, builder);
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+        addChildToParent(parent, builder, choiceName.getLocalName());
 
         return builder;
     }
 
-    public ChoiceCaseBuilder addCase(final QName caseName, final List<String> parentPath, final int line) {
+    public ChoiceCaseBuilder addCase(final int line, final QName caseName) {
         Builder parent = getActualNode();
-
-        final List<String> pathToCase = new ArrayList<String>(parentPath);
-        ChoiceCaseBuilder builder = null;
-        if (parent instanceof ChoiceBuilder) {
-            builder = new ChoiceCaseBuilder((ChoiceBuilder) parent, caseName, line);
-        } else {
-            builder = new ChoiceCaseBuilder(null, caseName, line);
+        if (parent == null) {
+            throw new YangParseException(name, line, "'case' parent not found");
         }
 
-        if (actualPath.isEmpty()) {
-            throw new YangParseException(name, line, "'case' parent not found");
+        final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(line, caseName);
+        builder.setParent(parent);
+
+        if (parent instanceof ChoiceBuilder) {
+            ((ChoiceBuilder) parent).addChildNode(builder);
+        } else if (parent instanceof AugmentationSchemaBuilder) {
+            ((AugmentationSchemaBuilder) parent).addChildNode(builder);
         } else {
-            if (parent instanceof ChoiceBuilder) {
-                ((ChoiceBuilder) parent).addChildNode(builder);
-            } else if (parent instanceof AugmentationSchemaBuilder) {
-                builder.setAugmenting(true);
-                ((AugmentationSchemaBuilder) parent).addChildNode(builder);
-            } else {
-                throw new YangParseException(name, line, "Unresolved parent of 'case' " + caseName.getLocalName());
-            }
+            throw new YangParseException(name, line, "Unresolved parent of 'case' " + caseName.getLocalName());
         }
 
-        pathToCase.add(caseName.getLocalName());
-        childNodes.put(pathToCase, builder);
-
         return builder;
     }
 
-    public AnyXmlBuilder addAnyXml(final SchemaPath schemaPath, final QName anyXmlName, final List<String> parentPath, final int line) {
-        final List<String> pathToAnyXml = new ArrayList<String>(parentPath);
-        final AnyXmlBuilder builder = new AnyXmlBuilder(anyXmlName, schemaPath, line);
-        updateParent(builder, line, "anyxml");
+    public AnyXmlBuilder addAnyXml(final int line, final QName anyXmlName, final SchemaPath schemaPath) {
+        final AnyXmlBuilder builder = new AnyXmlBuilder(line, anyXmlName, schemaPath);
 
-        pathToAnyXml.add(anyXmlName.getLocalName());
-        childNodes.put(pathToAnyXml, builder);
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+        addChildToParent(parent, builder, anyXmlName.getLocalName());
 
         return builder;
     }
 
     @Override
     public void addTypedef(TypeDefinitionBuilder typedefBuilder) {
-        final List<String> pathToTypedef = new ArrayList<String>();
-        for (QName qname : typedefBuilder.getPath().getPath()) {
-            pathToTypedef.add(qname.getLocalName());
-        }
-        if (addedTypedefs.containsKey(pathToTypedef)) {
-            throw new YangParseException(this.name, typedefBuilder.getLine(), "Failed to add typedef "
-                    + typedefBuilder.getQName().getLocalName() + ": typedef already exists in context.");
+        for (TypeDefinitionBuilder tdb : addedTypedefs) {
+            if (tdb.getQName().getLocalName().equals(typedefBuilder.getQName().getLocalName())) {
+                throw new YangParseException(name, typedefBuilder.getLine(), "Duplicate node found at line "
+                        + tdb.getLine());
+            }
         }
-        addedTypedefs.put(pathToTypedef, typedefBuilder);
+        addedTypedefs.add(typedefBuilder);
     }
 
-    public TypeDefinitionBuilderImpl addTypedef(final QName typeDefName, final List<String> parentPath, final int line) {
-        final List<String> pathToType = new ArrayList<String>(parentPath);
+    public TypeDefinitionBuilderImpl addTypedef(final int line, final QName typeDefName) {
         final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(typeDefName, line);
 
-        if (!(actualPath.isEmpty())) {
-            final Builder parent = actualPath.getFirst();
-            if (parent instanceof TypeDefinitionAwareBuilder) {
-                ((TypeDefinitionAwareBuilder) parent).addTypedef(builder);
+        Builder parent = getActualNode();
+        builder.setParent(parent);
+
+        if (parent == null) {
+            for (TypeDefinitionBuilder tdb : addedTypedefs) {
+                if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
+                    throw new YangParseException(name, builder.getLine(), "Duplicate node found at line "
+                            + tdb.getLine());
+                }
+            }
+            addedTypedefs.add(builder);
+        } else {
+            if (parent instanceof DataNodeContainerBuilder) {
+                DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
+                for (DataSchemaNodeBuilder child : parentNode.getChildNodeBuilders()) {
+                    if (child.getQName().getLocalName().equals(typeDefName.getLocalName())) {
+                        throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
+                    }
+                }
+                parentNode.addTypedef(builder);
+            } else if (parent instanceof RpcDefinitionBuilder) {
+                RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parent;
+                for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
+                    if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
+                        throw new YangParseException(name, builder.getLine(), "Duplicate node found at line "
+                                + tdb.getLine());
+                    }
+                }
+                rpcParent.addTypedef(builder);
             } else {
                 throw new YangParseException(name, line, "Unresolved parent of typedef " + typeDefName.getLocalName());
             }
         }
 
-        pathToType.add(typeDefName.getLocalName());
-        addedTypedefs.put(pathToType, builder);
         return builder;
     }
 
-    public void setType(final TypeDefinition<?> type, final List<String> parentPath) {
-        if (!(actualPath.isEmpty())) {
-            final Builder parent = actualPath.getFirst();
-            if (parent instanceof TypeAwareBuilder) {
-                ((TypeAwareBuilder) parent).setType(type);
-            } else {
-                throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
-                        + "'. Unknown parent node: " + parent);
-            }
+    public void setType(final TypeDefinition<?> type) {
+        Builder parent = getActualNode();
+        if (parent == null || !(parent instanceof TypeAwareBuilder)) {
+            throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
+                    + "'. Unknown parent node: " + parent);
         }
+        ((TypeAwareBuilder) parent).setType(type);
     }
 
     public UnionTypeBuilder addUnionType(final List<String> currentPath, final URI namespace, final Date revision,
@@ -770,7 +755,8 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
     }
 
     public DeviationBuilder addDeviation(final String targetPath, final List<String> parentPath, final int line) {
-        if (!(actualPath.isEmpty())) {
+        Builder parent = getActualNode();
+        if (parent != null) {
             throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
         }
 
@@ -782,39 +768,43 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
     }
 
     public IdentitySchemaNodeBuilder addIdentity(final QName qname, final List<String> parentPath, final int line) {
-        if (!(actualPath.isEmpty())) {
+        Builder parent = getActualNode();
+        if (parent != null) {
             throw new YangParseException(name, line, "identity can be defined only in module or submodule");
         }
+        for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
+            if (idBuilder.getQName().equals(qname)) {
+                throw new YangParseException(name, line, "Duplicate node found at line " + idBuilder.getLine());
+            }
+        }
 
-        final List<String> pathToIdentity = new ArrayList<String>(parentPath);
-        final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(qname, line);
-        pathToIdentity.add(qname.getLocalName());
+        final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(line, qname);
         addedIdentities.add(builder);
         return builder;
     }
 
     @Override
-    public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode) {
+    public void addUnknownSchemaNode(UnknownSchemaNodeBuilder builder) {
         final List<String> unPath = new ArrayList<String>();
-        for (QName qname : unknownNode.getPath().getPath()) {
-            unPath.add(qname.getLocalName());
+        for (QName name : builder.getPath().getPath()) {
+            unPath.add(name.getLocalName());
         }
-
         if (addedUnknownNodes.containsKey(unPath)) {
-            addedUnknownNodes.get(unPath).add(unknownNode);
+            addedUnknownNodes.get(unPath).add(builder);
         } else {
             List<UnknownSchemaNodeBuilder> nodes = new ArrayList<UnknownSchemaNodeBuilder>();
-            nodes.add(unknownNode);
+            nodes.add(builder);
             addedUnknownNodes.put(unPath, nodes);
         }
     }
 
     public UnknownSchemaNodeBuilder addUnknownSchemaNode(final QName qname, final List<String> parentPath,
             final int line) {
-        final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(qname, line);
+        final Builder parent = getActualNode();
+        final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(line, qname);
+        builder.setParent(parent);
 
-        if (!(actualPath.isEmpty())) {
-            final Builder parent = actualPath.getFirst();
+        if (parent != null) {
             if (parent instanceof SchemaNodeBuilder) {
                 ((SchemaNodeBuilder) parent).addUnknownSchemaNode(builder);
             } else if (parent instanceof RefineHolder) {
@@ -1026,7 +1016,7 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
 
         @Override
         public Set<DataSchemaNode> getChildNodes() {
-            return new HashSet<DataSchemaNode>(childNodes.values());
+            return new LinkedHashSet<DataSchemaNode>(childNodes.values());
         }
 
         private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
@@ -1183,19 +1173,52 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         }
     }
 
-    private void updateParent(DataSchemaNodeBuilder nodeBuilder, int line, String nodeTypeName) {
-        if (!(actualPath.isEmpty())) {
-            final Builder parent = actualPath.getFirst();
+    private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childLocalName) {
+        final int line = child.getLine();
+        if (parent == null) {
+            // if parent == null => node is defined under module
+            // All leafs, leaf-lists, lists, containers, choices, rpcs,
+            // notifications, and anyxmls defined within a parent node or at the
+            // top level of the module or its submodules share the same
+            // identifier namespace.
+            for (DataSchemaNodeBuilder childNode : childNodes) {
+                if (childNode.getQName().getLocalName().equals(childLocalName)) {
+                    throw new YangParseException(name, line, "Duplicate node found at line " + childNode.getLine());
+                }
+            }
+            for (RpcDefinitionBuilder rpc : addedRpcs) {
+                if (rpc.getQName().getLocalName().equals(childLocalName)) {
+                    throw new YangParseException(name, line, "Duplicate node found at line " + rpc.getLine());
+                }
+            }
+            for (NotificationBuilder notification : addedNotifications) {
+                if (notification.getQName().getLocalName().equals(childLocalName)) {
+                    throw new YangParseException(name, line, "Duplicate node found at line " + notification.getLine());
+                }
+            }
+            childNodes.add(child);
+        } else {
+            // no need for checking rpc and notification because they can be
+            // defined only under module or submodule
             if (parent instanceof DataNodeContainerBuilder) {
-                if (parent instanceof AugmentationSchemaBuilder) {
-                    nodeBuilder.setAugmenting(true);
+                DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
+                for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
+                    if (childNode.getQName().getLocalName().equals(childLocalName)) {
+                        throw new YangParseException(name, line, "Duplicate node found at line " + childNode.getLine());
+                    }
                 }
-                ((DataNodeContainerBuilder) parent).addChildNode(nodeBuilder);
+                parentNode.addChildNode(child);
             } else if (parent instanceof ChoiceBuilder) {
-                ((ChoiceBuilder) parent).addChildNode(nodeBuilder);
+                ChoiceBuilder parentNode = (ChoiceBuilder) parent;
+                for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
+                    if (caseBuilder.getQName().getLocalName().equals(childLocalName)) {
+                        throw new YangParseException(name, line, "Duplicate node found at line "
+                                + caseBuilder.getLine());
+                    }
+                }
+                parentNode.addChildNode(child);
             } else {
-                throw new YangParseException(name, line, "Unresolved parent of " + nodeTypeName + " "
-                        + nodeBuilder.getQName().getLocalName());
+                throw new YangParseException(name, line, "Unresolved parent of node '" + childLocalName + "'.");
             }
         }
     }
@@ -1272,132 +1295,29 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
     }
 
     /**
-     * Traverse through given addedChilds and add only direct module childs.
-     * Direct module child path size is 2 (1. module name, 2. child name).
+     * Traverse through given addedUnknownNodes and add only unknown nodes
+     * defined under module statement.
      *
-     * @param addedChilds
-     * @return map of children, where key is child QName and value is child
-     *         itself
+     * @param addedUnknownNodes
+     *            unknown node builders
+     * @return list of all unknown nodes defined in module in lexicographical
+     *         order
      */
-    private Map<QName, DataSchemaNode> buildModuleChildNodes(Map<List<String>, DataSchemaNodeBuilder> addedChilds) {
-        final Map<QName, DataSchemaNode> childNodes = new HashMap<QName, DataSchemaNode>();
-        for (Map.Entry<List<String>, DataSchemaNodeBuilder> entry : addedChilds.entrySet()) {
-            List<String> path = entry.getKey();
-            DataSchemaNodeBuilder child = entry.getValue();
-            if (path.size() == 2) {
-                DataSchemaNode node = child.build();
-                QName qname = node.getQName();
-                childNodes.put(qname, node);
-            }
-        }
-        return childNodes;
-    }
-
-    /**
-     * Traverse through given addedGroupings and add only direct module
-     * groupings. Direct module grouping path size is 2 (1. module name, 2.
-     * grouping name).
-     *
-     * @param addedGroupings
-     * @return set of built GroupingDefinition objects
-     */
-    private Set<GroupingDefinition> buildModuleGroupings(Map<List<String>, GroupingBuilder> addedGroupings) {
-        final Set<GroupingDefinition> groupings = new HashSet<GroupingDefinition>();
-        for (Map.Entry<List<String>, GroupingBuilder> entry : addedGroupings.entrySet()) {
-            if (entry.getKey().size() == 2) {
-                groupings.add(entry.getValue().build());
-            }
-        }
-        return groupings;
-    }
-
-    /**
-     * Traverse through given addedRpcs and build RpcDefinition objects.
-     *
-     * @param addedRpcs
-     * @return set of built RpcDefinition objects
-     */
-    private Set<RpcDefinition> buildModuleRpcs(Map<List<String>, RpcDefinitionBuilder> addedRpcs) {
-        final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
-        RpcDefinitionBuilder builder;
-        for (Map.Entry<List<String>, RpcDefinitionBuilder> entry : addedRpcs.entrySet()) {
-            builder = entry.getValue();
-            RpcDefinition rpc = builder.build();
-            rpcs.add(rpc);
-        }
-        return rpcs;
-    }
-
-    /**
-     * Traverse through given addedTypedefs and add only direct module typedef
-     * statements. Direct module typedef path size is 2 (1. module name, 2.
-     * typedef name).
-     *
-     * @param addedTypedefs
-     * @return set of built module typedef statements
-     */
-    private Set<TypeDefinition<?>> buildModuleTypedefs(Map<List<String>, TypeDefinitionBuilder> addedTypedefs) {
-        Set<TypeDefinition<?>> typedefs = new HashSet<TypeDefinition<?>>();
-        for (Map.Entry<List<String>, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) {
-            List<String> key = entry.getKey();
-            TypeDefinitionBuilder typedefBuilder = entry.getValue();
-            if (key.size() == 2) {
-                TypeDefinition<? extends TypeDefinition<?>> node = typedefBuilder.build();
-                typedefs.add(node);
-            }
-        }
-        return typedefs;
-    }
-
-    /**
-     * Traverse through given addedUsesNodes and add only direct module uses
-     * nodes. Direct module uses node path size is 2 (1. module name, 2. uses
-     * name).
-     *
-     * @param addedUsesNodes
-     * @return set of built module uses nodes
-     */
-    private Set<UsesNode> buildUsesNodes(Map<List<String>, UsesNodeBuilder> addedUsesNodes) {
-        final Set<UsesNode> usesNodeDefs = new HashSet<UsesNode>();
-        for (Map.Entry<List<String>, UsesNodeBuilder> entry : addedUsesNodes.entrySet()) {
-            if (entry.getKey().size() == 2) {
-                usesNodeDefs.add(entry.getValue().build());
-            }
-        }
-        return usesNodeDefs;
-    }
-
-    /**
-     * Traverse through given addedFeatures and add only direct module features.
-     * Direct module feature path size is 2 (1. module name, 2. feature name).
-     *
-     * @param addedFeatures
-     * @return set of built module features
-     */
-    private Set<FeatureDefinition> buildModuleFeatures(Map<List<String>, FeatureBuilder> addedFeatures) {
-        Set<FeatureDefinition> features = new HashSet<FeatureDefinition>();
-        for (Map.Entry<List<String>, FeatureBuilder> entry : addedFeatures.entrySet()) {
-            if (entry.getKey().size() == 2) {
-                features.add(entry.getValue().build());
-            }
-        }
-        return features;
-    }
-
     private List<UnknownSchemaNode> buildModuleUnknownNodes(
             final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes) {
-        final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+        final List<UnknownSchemaNode> result = new ArrayList<UnknownSchemaNode>();
         for (Map.Entry<List<String>, List<UnknownSchemaNodeBuilder>> entry : addedUnknownNodes.entrySet()) {
             final List<String> path = entry.getKey();
             final List<UnknownSchemaNodeBuilder> child = entry.getValue();
-            for (UnknownSchemaNodeBuilder un : child) {
-                if (path.size() == 2) {
-                    final UnknownSchemaNode node = un.build();
-                    unknownNodes.add(node);
+
+            if (path.size() == 2) {
+                for (UnknownSchemaNodeBuilder node : child) {
+                    result.add(node.build());
                 }
             }
         }
-        return unknownNodes;
+        Collections.sort(result, Comparators.SCHEMA_NODE_COMP);
+        return result;
     }
 
 }
index 534ba2c..b9b1519 100644 (file)
@@ -9,11 +9,12 @@ package org.opendaylight.controller.yang.parser.builder.impl;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
@@ -31,12 +32,12 @@ import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBui
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
-import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionAwareBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
-public final class NotificationBuilder extends AbstractDataNodeContainerBuilder implements TypeDefinitionAwareBuilder,
-        SchemaNodeBuilder, AugmentationTargetBuilder {
+public final class NotificationBuilder extends AbstractDataNodeContainerBuilder implements SchemaNodeBuilder,
+        AugmentationTargetBuilder {
     private boolean isBuilt;
     private final NotificationDefinitionImpl instance;
     private final int line;
@@ -50,8 +51,8 @@ public final class NotificationBuilder extends AbstractDataNodeContainerBuilder
     private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
 
-    NotificationBuilder(final QName qname, final int line) {
-        super(qname);
+    NotificationBuilder(final int line, final QName qname) {
+        super(line, qname);
         this.line = line;
         instance = new NotificationDefinitionImpl(qname);
     }
@@ -65,21 +66,21 @@ public final class NotificationBuilder extends AbstractDataNodeContainerBuilder
             instance.setStatus(status);
 
             // CHILD NODES
-            final Map<QName, DataSchemaNode> childs = new HashMap<QName, DataSchemaNode>();
+            final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
             for (DataSchemaNodeBuilder node : addedChildNodes) {
                 childs.put(node.getQName(), node.build());
             }
             instance.setChildNodes(childs);
 
             // GROUPINGS
-            final Set<GroupingDefinition> groupingDefs = new HashSet<GroupingDefinition>();
+            final Set<GroupingDefinition> groupingDefs = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
             for (GroupingBuilder builder : addedGroupings) {
                 groupingDefs.add(builder.build());
             }
             instance.setGroupings(groupingDefs);
 
             // TYPEDEFS
-            final Set<TypeDefinition<?>> typedefs = new HashSet<TypeDefinition<?>>();
+            final Set<TypeDefinition<?>> typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
             for (TypeDefinitionBuilder entry : addedTypedefs) {
                 typedefs.add(entry.build());
             }
@@ -106,6 +107,7 @@ public final class NotificationBuilder extends AbstractDataNodeContainerBuilder
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
@@ -120,11 +122,6 @@ public final class NotificationBuilder extends AbstractDataNodeContainerBuilder
         build();
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
     @Override
     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
         return addedTypedefs;
index 8cb4a6e..d2b8544 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
@@ -23,10 +24,10 @@ import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
-import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionAwareBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
-public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder implements TypeDefinitionAwareBuilder {
+public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder {
     private boolean isBuilt;
     private final RpcDefinitionImpl instance;
     private ContainerSchemaNodeBuilder inputBuilder;
@@ -34,8 +35,8 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder implem
     private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
     private final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
 
-    RpcDefinitionBuilder(final QName qname, final int line) {
-        super(qname, line);
+    RpcDefinitionBuilder(final int line, final QName qname) {
+        super(line, qname);
         this.instance = new RpcDefinitionImpl(qname);
     }
 
@@ -51,17 +52,17 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder implem
             instance.setInput(input);
             instance.setOutput(output);
 
-            instance.setPath(path);
+            instance.setPath(schemaPath);
 
             // TYPEDEFS
-            final Set<TypeDefinition<?>> typedefs = new HashSet<TypeDefinition<?>>();
+            final Set<TypeDefinition<?>> typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
             for (TypeDefinitionBuilder entry : addedTypedefs) {
                 typedefs.add(entry.build());
             }
             instance.setTypeDefinitions(typedefs);
 
             // GROUPINGS
-            final Set<GroupingDefinition> groupings = new HashSet<GroupingDefinition>();
+            final Set<GroupingDefinition> groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
             for (GroupingBuilder entry : addedGroupings) {
                 groupings.add(entry.build());
             }
@@ -72,6 +73,7 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder implem
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
@@ -91,7 +93,6 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder implem
         return addedTypedefs;
     }
 
-    @Override
     public void addTypedef(final TypeDefinitionBuilder type) {
         addedTypedefs.add(type);
     }
@@ -109,7 +110,7 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder implem
         final int prime = 31;
         int result = 1;
         result = prime * result + ((qname == null) ? 0 : qname.hashCode());
-        result = prime * result + ((path == null) ? 0 : path.hashCode());
+        result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
         return result;
     }
 
@@ -129,11 +130,11 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder implem
         } else if (!other.qname.equals(this.qname)) {
             return false;
         }
-        if (other.path == null) {
-            if (this.path != null) {
+        if (other.schemaPath == null) {
+            if (this.schemaPath != null) {
                 return false;
             }
-        } else if (!other.path.equals(this.path)) {
+        } else if (!other.schemaPath.equals(this.schemaPath)) {
             return false;
         }
         return true;
index 6ca07bc..1d1d24b 100644 (file)
@@ -23,13 +23,11 @@ import org.opendaylight.controller.yang.model.util.ExtendedType;
 import org.opendaylight.controller.yang.model.util.UnknownType;
 import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
 public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder implements TypeDefinitionBuilder {
-    private final int line;
-    private final QName qname;
     private SchemaPath schemaPath;
-
     private List<UnknownSchemaNode> unknownNodes;
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
     private List<RangeConstraint> ranges = Collections.emptyList();
@@ -45,13 +43,11 @@ public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder im
     private boolean addedByUses;
 
     public TypeDefinitionBuilderImpl(final QName qname, final int line) {
-        this.qname = qname;
-        this.line = line;
+        super(line, qname);
     }
 
     public TypeDefinitionBuilderImpl(TypeDefinitionBuilder tdb) {
-        qname = tdb.getQName();
-        line = tdb.getLine();
+        super(tdb.getLine(), tdb.getQName());
         schemaPath = tdb.getPath();
 
         type = tdb.getType();
@@ -103,22 +99,13 @@ public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder im
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
         }
         typeBuilder.unknownSchemaNodes(unknownNodes);
         result = typeBuilder.build();
         return result;
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
-    @Override
-    public QName getQName() {
-        return qname;
-    }
-
     @Override
     public SchemaPath getPath() {
         return schemaPath;
index 433ae96..33a51d6 100644 (file)
@@ -11,7 +11,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
@@ -33,7 +32,6 @@ import org.opendaylight.controller.yang.parser.util.YangParseException;
 public final class UnionTypeBuilder extends AbstractTypeAwareBuilder implements TypeDefinitionBuilder {
     private final static String NAME = "union";
 
-    private final int line;
     private final List<TypeDefinition<?>> types;
     private final List<TypeDefinitionBuilder> typedefs;
     private UnionType instance;
@@ -42,15 +40,11 @@ public final class UnionTypeBuilder extends AbstractTypeAwareBuilder implements
     private SchemaPath path;
 
     public UnionTypeBuilder(final int line) {
-        this.line = line;
+        super(line, null);
         types = new ArrayList<TypeDefinition<?>>();
         typedefs = new ArrayList<TypeDefinitionBuilder>();
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
 
     public List<TypeDefinition<?>> getTypes() {
         return types;
@@ -129,12 +123,7 @@ public final class UnionTypeBuilder extends AbstractTypeAwareBuilder implements
 
     @Override
     public void addUnknownSchemaNode(final UnknownSchemaNodeBuilder unknownNode) {
-        // not supported
-    }
-
-    @Override
-    public QName getQName() {
-        return null;
+        // not yet supported
     }
 
     @Override
index 14cf3a9..232fa60 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
 
 public final class UnknownSchemaNodeBuilder extends AbstractSchemaNodeBuilder {
     private boolean isBuilt;
@@ -25,15 +26,15 @@ public final class UnknownSchemaNodeBuilder extends AbstractSchemaNodeBuilder {
     private QName nodeType;
     private String nodeParameter;
 
-    public UnknownSchemaNodeBuilder(final QName qname, final int line) {
-        super(qname, line);
+    public UnknownSchemaNodeBuilder(final int line, final QName qname) {
+        super(line, qname);
         instance = new UnknownSchemaNodeImpl(qname);
     }
 
     public UnknownSchemaNodeBuilder(UnknownSchemaNodeBuilder b) {
-        super(b.getQName(), b.getLine());
+        super(b.getLine(), b.getQName());
         instance = new UnknownSchemaNodeImpl(qname);
-        path = b.getPath();
+        schemaPath = b.getPath();
         description = b.getDescription();
         reference = b.getReference();
         status = b.getStatus();
@@ -47,7 +48,7 @@ public final class UnknownSchemaNodeBuilder extends AbstractSchemaNodeBuilder {
     @Override
     public UnknownSchemaNode build() {
         if (!isBuilt) {
-            instance.setPath(path);
+            instance.setPath(schemaPath);
             instance.setNodeType(nodeType);
             instance.setNodeParameter(nodeParameter);
             instance.setDescription(description);
@@ -61,6 +62,7 @@ public final class UnknownSchemaNodeBuilder extends AbstractSchemaNodeBuilder {
                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                     unknownNodes.add(b.build());
                 }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
             instance.setUnknownSchemaNodes(unknownNodes);
 
index 77a465d..ecbc1c5 100644 (file)
@@ -21,16 +21,18 @@ import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
 import org.opendaylight.controller.yang.model.api.UsesNode;\r
 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;\r
+import org.opendaylight.controller.yang.parser.builder.api.Builder;\r
 import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;\r
 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;\r
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;\r
 import org.opendaylight.controller.yang.parser.util.RefineHolder;\r
+import org.opendaylight.controller.yang.parser.util.YangParseException;\r
 \r
 public final class UsesNodeBuilderImpl implements UsesNodeBuilder {\r
     private boolean isBuilt;\r
     private UsesNodeImpl instance;\r
     private final int line;\r
-    private final DataNodeContainerBuilder parent;\r
+    private DataNodeContainerBuilder parent;\r
     private final String groupingName;\r
     private SchemaPath groupingPath;\r
     private boolean augmenting;\r
@@ -40,10 +42,9 @@ public final class UsesNodeBuilderImpl implements UsesNodeBuilder {
     private final List<RefineHolder> refines = new ArrayList<RefineHolder>();\r
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();\r
 \r
-    public UsesNodeBuilderImpl(final String groupingName, final int line, final DataNodeContainerBuilder parent) {\r
+    public UsesNodeBuilderImpl(final int line, final String groupingName) {\r
         this.groupingName = groupingName;\r
         this.line = line;\r
-        this.parent = parent;\r
     }\r
 \r
     public UsesNodeBuilderImpl(UsesNodeBuilder b) {\r
@@ -102,6 +103,14 @@ public final class UsesNodeBuilderImpl implements UsesNodeBuilder {
         return parent;\r
     }\r
 \r
+    @Override\r
+    public void setParent(Builder parent) {\r
+        if (!(parent instanceof DataNodeContainerBuilder)) {\r
+            throw new YangParseException(line, "Unresolved parent of uses '" + groupingName + "'.");\r
+        }\r
+        this.parent = (DataNodeContainerBuilder) parent;\r
+    }\r
+\r
     @Override\r
     public SchemaPath getGroupingPath() {\r
         return groupingPath;\r
@@ -176,6 +185,47 @@ public final class UsesNodeBuilderImpl implements UsesNodeBuilder {
         addedUnknownNodes.add(unknownNode);\r
     }\r
 \r
+    @Override\r
+    public int hashCode() {\r
+        final int prime = 31;\r
+        int result = 1;\r
+        result = prime * result + ((groupingName == null) ? 0 : groupingName.hashCode());\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj)\r
+            return true;\r
+        if (obj == null)\r
+            return false;\r
+        if (getClass() != obj.getClass())\r
+            return false;\r
+        UsesNodeBuilderImpl other = (UsesNodeBuilderImpl) obj;\r
+        if (groupingName == null) {\r
+            if (other.groupingName != null)\r
+                return false;\r
+        } else if (!groupingName.equals(other.groupingName))\r
+            return false;\r
+\r
+        if (parent == null) {\r
+            if (other.parent != null)\r
+                return false;\r
+        } else if (!parent.equals(other.parent))\r
+            return false;\r
+        if (refines == null) {\r
+            if (other.refines != null)\r
+                return false;\r
+        } else if (!refines.equals(other.refines))\r
+            return false;\r
+        return true;\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        return "uses '" + groupingName + "'";\r
+    }\r
+\r
     public final class UsesNodeImpl implements UsesNode {\r
         private final SchemaPath groupingPath;\r
         private Set<AugmentationSchema> augmentations = Collections.emptySet();\r
@@ -296,4 +346,5 @@ public final class UsesNodeBuilderImpl implements UsesNodeBuilder {
             return sb.toString();\r
         }\r
     }\r
+\r
 }\r
index 5dedd3c..6adc29b 100644 (file)
@@ -436,8 +436,8 @@ public final class YangParserImpl implements YangModelParser {
         final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, unknownTypeQName.getPrefix(),
                 line);
 
-        final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve.getPath(),
-                dependentModule, unknownTypeQName.getLocalName(), module.getName(), line);
+        final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve, dependentModule,
+                unknownTypeQName.getLocalName(), module.getName(), line);
 
         if (nodeToResolveType instanceof ExtendedType) {
             final ExtendedType extType = (ExtendedType) nodeToResolveType;
@@ -504,7 +504,7 @@ public final class YangParserImpl implements YangModelParser {
             }
 
         } else {
-            final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve.getPath(),
+            final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
                     dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
 
             if (nodeToResolveType instanceof ExtendedType) {
@@ -535,8 +535,8 @@ public final class YangParserImpl implements YangModelParser {
                 final UnknownType ut = (UnknownType) unionType;
                 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
                         .getPrefix(), union.getLine());
-                final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union.getPath(), dependentModule,
-                        ut.getQName().getLocalName(), builder.getName(), union.getLine());
+                final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModule, ut
+                        .getQName().getLocalName(), builder.getName(), union.getLine());
                 union.setTypedef(resolvedType);
                 toRemove.add(ut);
             } else if (unionType instanceof ExtendedType) {
@@ -546,8 +546,8 @@ public final class YangParserImpl implements YangModelParser {
                     final UnknownType ut = (UnknownType) extTypeBase;
                     final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
                             .getPrefix(), union.getLine());
-                    final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union.getPath(),
-                            dependentModule, ut.getQName().getLocalName(), builder.getName(), union.getLine());
+                    final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModule,
+                            ut.getQName().getLocalName(), builder.getName(), union.getLine());
 
                     final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
                             extType, modules, builder, union.getLine());
@@ -581,8 +581,8 @@ public final class YangParserImpl implements YangModelParser {
                     union.setType(type);
                     toRemove.add(ut);
                 } else {
-                    final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union.getPath(),
-                            dependentModuleBuilder, utQName.getLocalName(), builder.getName(), union.getLine());
+                    final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder,
+                            utQName.getLocalName(), builder.getName(), union.getLine());
                     union.setTypedef(resolvedType);
                     toRemove.add(ut);
                 }
@@ -606,7 +606,7 @@ public final class YangParserImpl implements YangModelParser {
                         union.setTypedef(newType);
                         toRemove.add(extType);
                     } else {
-                        final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union.getPath(),
+                        final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union,
                                 dependentModuleBuilder, utQName.getLocalName(), builder.getName(), union.getLine());
 
                         final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
@@ -645,7 +645,7 @@ public final class YangParserImpl implements YangModelParser {
             resolveAugment(modules, module);
             // while all augments are not resolved
             final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
-            while (!(module.getAugmentsResolved() == module.getAugments().size())) {
+            while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
                 ModuleBuilder nextModule = null;
                 // try resolve other module augments
                 try {
@@ -670,8 +670,8 @@ public final class YangParserImpl implements YangModelParser {
      *            current module
      */
     private void resolveAugment(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
-        if (module.getAugmentsResolved() < module.getAugments().size()) {
-            for (AugmentationSchemaBuilder augmentBuilder : module.getAugments()) {
+        if (module.getAugmentsResolved() < module.getAllAugments().size()) {
+            for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
 
                 if (!augmentBuilder.isResolved()) {
                     final SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
@@ -685,7 +685,7 @@ public final class YangParserImpl implements YangModelParser {
 
                     final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix,
                             augmentBuilder.getLine());
-                    processAugmentation(augmentBuilder, path, module, qname, dependentModule);
+                    processAugmentation(augmentBuilder, path, module, dependentModule);
                 }
 
             }
@@ -719,7 +719,7 @@ public final class YangParserImpl implements YangModelParser {
             resolveAugmentWithContext(modules, module, context);
             // while all augments are not resolved
             final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
-            while (!(module.getAugmentsResolved() == module.getAugments().size())) {
+            while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
                 ModuleBuilder nextModule = null;
                 // try resolve other module augments
                 try {
@@ -745,9 +745,9 @@ public final class YangParserImpl implements YangModelParser {
      */
     private void resolveAugmentWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module, final SchemaContext context) {
-        if (module.getAugmentsResolved() < module.getAugments().size()) {
+        if (module.getAugmentsResolved() < module.getAllAugments().size()) {
 
-            for (AugmentationSchemaBuilder augmentBuilder : module.getAugments()) {
+            for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
                 final int line = augmentBuilder.getLine();
 
                 if (!augmentBuilder.isResolved()) {
@@ -767,7 +767,7 @@ public final class YangParserImpl implements YangModelParser {
                         processAugmentationOnContext(augmentBuilder, path, module, prefix, line, context);
                         continue;
                     } else {
-                        processAugmentation(augmentBuilder, path, module, qname, dependentModuleBuilder);
+                        processAugmentation(augmentBuilder, path, module, dependentModuleBuilder);
                     }
                 }
 
@@ -875,18 +875,17 @@ public final class YangParserImpl implements YangModelParser {
      *            module being resolved
      */
     private void resolveUsesRefine(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
-        final Map<List<String>, UsesNodeBuilder> moduleUses = module.getUsesNodes();
-        for (Map.Entry<List<String>, UsesNodeBuilder> entry : moduleUses.entrySet()) {
+        final List<UsesNodeBuilder> allModuleUses = module.getAllUsesNodes();
+        for (UsesNodeBuilder usesNode : allModuleUses) {
             // refine
-            final UsesNodeBuilder usesNode = entry.getValue();
             final int line = usesNode.getLine();
             final GroupingBuilder targetGrouping = getTargetGroupingFromModules(usesNode, modules, module);
             usesNode.setGroupingPath(targetGrouping.getPath());
             for (RefineHolder refine : usesNode.getRefines()) {
                 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(targetGrouping,
                         refine, module.getName());
-                if(nodeToRefine instanceof GroupingMember) {
-                    ((GroupingMember)nodeToRefine).setAddedByUses(true);
+                if (nodeToRefine instanceof GroupingMember) {
+                    ((GroupingMember) nodeToRefine).setAddedByUses(true);
                 }
                 RefineUtils.performRefine(nodeToRefine, refine, line);
                 usesNode.addRefineNode(nodeToRefine);
@@ -911,9 +910,8 @@ public final class YangParserImpl implements YangModelParser {
      */
     private void resolveUsesRefineWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module, final SchemaContext context) {
-        final Map<List<String>, UsesNodeBuilder> moduleUses = module.getUsesNodes();
-        for (Map.Entry<List<String>, UsesNodeBuilder> entry : moduleUses.entrySet()) {
-            final UsesNodeBuilder usesNode = entry.getValue();
+        final List<UsesNodeBuilder> moduleUses = module.getAllUsesNodes();
+        for (UsesNodeBuilder usesNode : moduleUses) {
             final int line = usesNode.getLine();
 
             final GroupingBuilder targetGroupingBuilder = getTargetGroupingFromModules(usesNode, modules, module);
@@ -923,8 +921,8 @@ public final class YangParserImpl implements YangModelParser {
                 for (RefineHolder refine : usesNode.getRefines()) {
                     final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingDefinition(
                             targetGrouping, refine, module.getName());
-                    if(nodeToRefine instanceof GroupingMember) {
-                        ((GroupingMember)nodeToRefine).setAddedByUses(true);
+                    if (nodeToRefine instanceof GroupingMember) {
+                        ((GroupingMember) nodeToRefine).setAddedByUses(true);
                     }
                     RefineUtils.performRefine(nodeToRefine, refine, line);
                     usesNode.addRefineNode(nodeToRefine);
@@ -936,8 +934,8 @@ public final class YangParserImpl implements YangModelParser {
                 for (RefineHolder refine : usesNode.getRefines()) {
                     final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(
                             targetGroupingBuilder, refine, module.getName());
-                    if(nodeToRefine instanceof GroupingMember) {
-                        ((GroupingMember)nodeToRefine).setAddedByUses(true);
+                    if (nodeToRefine instanceof GroupingMember) {
+                        ((GroupingMember) nodeToRefine).setAddedByUses(true);
                     }
                     RefineUtils.performRefine(nodeToRefine, refine, line);
                     usesNode.addRefineNode(nodeToRefine);
@@ -989,36 +987,33 @@ public final class YangParserImpl implements YangModelParser {
             return null;
         }
 
-        List<QName> path = usesBuilder.getParent().getPath().getPath();
         GroupingBuilder result = null;
-        Set<GroupingBuilder> groupings = dependentModule.getModuleGroupings();
+        Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
         result = findGroupingBuilder(groupings, groupingName);
+        if (result != null) {
+            return result;
+        }
 
-        if (result == null) {
-            Builder currentNode = null;
-            final List<String> currentPath = new ArrayList<String>();
-            currentPath.add(dependentModule.getName());
-
-            for (int i = 0; i < path.size(); i++) {
-                QName qname = path.get(i);
-                currentPath.add(qname.getLocalName());
-                currentNode = dependentModule.getModuleNode(currentPath);
-
-                if (currentNode instanceof RpcDefinitionBuilder) {
-                    groupings = ((RpcDefinitionBuilder) currentNode).getGroupings();
-                } else if (currentNode instanceof DataNodeContainerBuilder) {
-                    groupings = ((DataNodeContainerBuilder) currentNode).getGroupingBuilders();
-                } else {
-                    groupings = Collections.emptySet();
-                }
+        Builder parent = usesBuilder.getParent();
 
-                result = findGroupingBuilder(groupings, groupingName);
-                if (result != null) {
-                    break;
-                }
+        while (parent != null) {
+            if (parent instanceof DataNodeContainerBuilder) {
+                groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
+            } else if (parent instanceof RpcDefinitionBuilder) {
+                groupings = ((RpcDefinitionBuilder) parent).getGroupings();
+            }
+            result = findGroupingBuilder(groupings, groupingName);
+            if (result == null) {
+                parent = parent.getParent();
+            } else {
+                break;
             }
         }
 
+        if (result == null) {
+            throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
+                    + "' not found.");
+        }
         return result;
     }
 
@@ -1069,9 +1064,9 @@ public final class YangParserImpl implements YangModelParser {
         for (DataSchemaNodeBuilder child : targetGrouping.getChildNodeBuilders()) {
             // if node is refined, take it from refined nodes and continue
             SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
-            if(refined != null) {
+            if (refined != null) {
                 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
-                parent.addChildNode((DataSchemaNodeBuilder)refined);
+                parent.addChildNode((DataSchemaNodeBuilder) refined);
                 continue;
             }
 
@@ -1130,9 +1125,9 @@ public final class YangParserImpl implements YangModelParser {
         for (DataSchemaNode child : targetGrouping.getChildNodes()) {
             // if node is refined, take it from refined nodes and continue
             SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
-            if(refined != null) {
+            if (refined != null) {
                 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
-                parent.addChildNode((DataSchemaNodeBuilder)refined);
+                parent.addChildNode((DataSchemaNodeBuilder) refined);
                 continue;
             }
 
index 28095b5..f806c94 100644 (file)
@@ -13,7 +13,6 @@ import java.net.URI;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Stack;
@@ -52,7 +51,6 @@ import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
-import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.util.YangTypesConverter;
 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
@@ -94,6 +92,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
     @Override
     public void enterModule_stmt(YangParser.Module_stmtContext ctx) {
         moduleName = stringFromNode(ctx);
+        logger.debug("enter module " + moduleName);
         actualPath.push(moduleName);
         moduleBuilder = new ModuleBuilder(moduleName);
 
@@ -118,14 +117,12 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitModule_stmt(YangParser.Module_stmtContext ctx) {
-        final String moduleName = actualPath.pop();
-        logger.debug("Exiting module " + moduleName);
+        exitLog("module", actualPath.pop());
     }
 
     @Override
-    public void enterModule_header_stmts(final Module_header_stmtsContext ctx) {
-        super.enterModule_header_stmts(ctx);
-
+    public void enterModule_header_stmts(Module_header_stmtsContext ctx) {
+        enterLog("module_header", "", ctx.getStart().getLine());
         String yangVersion = null;
         for (int i = 0; i < ctx.getChildCount(); ++i) {
             final ParseTree treeNode = ctx.getChild(i);
@@ -133,11 +130,14 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 final String namespaceStr = stringFromNode(treeNode);
                 namespace = URI.create(namespaceStr);
                 moduleBuilder.setNamespace(namespace);
+                setLog("namespace", namespaceStr);
             } else if (treeNode instanceof Prefix_stmtContext) {
                 yangModelPrefix = stringFromNode(treeNode);
                 moduleBuilder.setPrefix(yangModelPrefix);
+                setLog("prefix", yangModelPrefix);
             } else if (treeNode instanceof Yang_version_stmtContext) {
                 yangVersion = stringFromNode(treeNode);
+                setLog("yang-version", yangVersion);
             }
         }
 
@@ -147,34 +147,44 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         moduleBuilder.setYangVersion(yangVersion);
     }
 
+    @Override
+    public void exitModule_header_stmts(Module_header_stmtsContext ctx) {
+        exitLog("module_header", "");
+    }
+
     @Override
     public void enterMeta_stmts(YangParser.Meta_stmtsContext ctx) {
+        enterLog("meta_stmt", "", ctx.getStart().getLine());
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
             if (child instanceof Organization_stmtContext) {
                 final String organization = stringFromNode(child);
                 moduleBuilder.setOrganization(organization);
+                setLog("organization", organization);
             } else if (child instanceof Contact_stmtContext) {
                 final String contact = stringFromNode(child);
                 moduleBuilder.setContact(contact);
+                setLog("contact", contact);
             } else if (child instanceof Description_stmtContext) {
                 final String description = stringFromNode(child);
                 moduleBuilder.setDescription(description);
+                setLog("description", description);
             } else if (child instanceof Reference_stmtContext) {
                 final String reference = stringFromNode(child);
                 moduleBuilder.setReference(reference);
+                setLog("reference", reference);
             }
         }
     }
 
     @Override
-    public void exitSubmodule_header_stmts(YangParser.Submodule_header_stmtsContext ctx) {
-        final String submodule = actualPath.pop();
-        logger.debug("exiting submodule " + submodule);
+    public void exitMeta_stmts(YangParser.Meta_stmtsContext ctx) {
+        exitLog("meta_stmt", "");
     }
 
     @Override
     public void enterRevision_stmts(Revision_stmtsContext ctx) {
+        enterLog("revisions", "", ctx.getStart().getLine());
         if (ctx != null) {
             for (int i = 0; i < ctx.getChildCount(); ++i) {
                 final ParseTree treeNode = ctx.getChild(i);
@@ -185,6 +195,11 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         }
     }
 
+    @Override
+    public void exitRevision_stmts(Revision_stmtsContext ctx) {
+        exitLog("revisions", "");
+    }
+
     private void updateRevisionForRevisionStatement(final ParseTree treeNode) {
         final String revisionDateStr = stringFromNode(treeNode);
         try {
@@ -192,6 +207,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             if ((revision != null) && (this.revision.compareTo(revision) < 0)) {
                 this.revision = revision;
                 moduleBuilder.setRevision(this.revision);
+                setLog("revision", this.revision.toString());
                 for (int i = 0; i < treeNode.getChildCount(); ++i) {
                     ParseTree child = treeNode.getChild(i);
                     if (child instanceof Reference_stmtContext) {
@@ -207,7 +223,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void enterImport_stmt(Import_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String importName = stringFromNode(ctx);
+        enterLog("import", importName, line);
+
         String importPrefix = null;
         Date importRevision = null;
 
@@ -221,50 +240,58 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 try {
                     importRevision = simpleDateFormat.parse(importRevisionStr);
                 } catch (ParseException e) {
-                    logger.warn("Failed to parse import revision-date: " + importRevisionStr);
+                    logger.warn("Failed to parse import revision-date at line " + line + ": " + importRevisionStr);
                 }
             }
         }
         moduleBuilder.addModuleImport(importName, importRevision, importPrefix);
+        setLog("import", "(" + importName + "; " + importRevision + "; " + importPrefix + ")");
+    }
+
+    @Override
+    public void exitImport_stmt(Import_stmtContext ctx) {
+        exitLog("import", "");
     }
 
     @Override
     public void enterAugment_stmt(YangParser.Augment_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String augmentPath = stringFromNode(ctx);
-        AugmentationSchemaBuilder builder = moduleBuilder.addAugment(augmentPath, actualPath, ctx.getStart().getLine());
-        moduleBuilder.enterNode(builder);
-        updatePath(augmentPath);
+        enterLog("augment", augmentPath, line);
+
+        AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
             if (child instanceof Description_stmtContext) {
-                String desc = stringFromNode(child);
-                builder.setDescription(desc);
+                builder.setDescription(stringFromNode(child));
             } else if (child instanceof Reference_stmtContext) {
-                String ref = stringFromNode(child);
-                builder.setReference(ref);
+                builder.setReference(stringFromNode(child));
             } else if (child instanceof Status_stmtContext) {
-                Status status = parseStatus((Status_stmtContext) child);
-                builder.setStatus(status);
+                builder.setStatus(parseStatus((Status_stmtContext) child));
             } else if (child instanceof When_stmtContext) {
-                String when = stringFromNode(child);
-                builder.addWhenCondition(when);
+                builder.addWhenCondition(stringFromNode(child));
             }
         }
+
+        moduleBuilder.enterNode(builder);
+        actualPath.push(augmentPath);
     }
 
     @Override
     public void exitAugment_stmt(YangParser.Augment_stmtContext ctx) {
-        final String augment = actualPath.pop();
-        logger.debug("exiting augment " + augment);
         moduleBuilder.exitNode();
+        exitLog("augment", actualPath.pop());
     }
 
     @Override
     public void enterExtension_stmt(YangParser.Extension_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String extName = stringFromNode(ctx);
+        enterLog("extension", extName, line);
+
         QName qname = new QName(namespace, revision, yangModelPrefix, extName);
-        ExtensionBuilder builder = moduleBuilder.addExtension(qname, ctx.getStart().getLine());
+        ExtensionBuilder builder = moduleBuilder.addExtension(qname, line);
         parseSchemaNodeArgs(ctx, builder);
 
         String argument = null;
@@ -279,15 +306,27 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         }
         builder.setArgument(argument);
         builder.setYinElement(yin);
+
+        moduleBuilder.enterNode(builder);
+        actualPath.push(extName);
+    }
+
+    @Override
+    public void exitExtension_stmt(YangParser.Extension_stmtContext ctx) {
+        moduleBuilder.exitNode();
+        exitLog("extension", actualPath.pop());
     }
 
     @Override
     public void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String typedefName = stringFromNode(ctx);
+        enterLog("typedef", typedefName, line);
+
         QName typedefQName = new QName(namespace, revision, yangModelPrefix, typedefName);
-        TypeDefinitionBuilder builder = moduleBuilder.addTypedef(typedefQName, actualPath, ctx.getStart().getLine());
+        TypeDefinitionBuilder builder = moduleBuilder.addTypedef(line, typedefQName);
         moduleBuilder.enterNode(builder);
-        updatePath(typedefName);
+        actualPath.push(typedefName);
 
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
@@ -296,15 +335,16 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("typedef", actualPath.pop());
     }
 
     @Override
     public void enterType_stmt(YangParser.Type_stmtContext ctx) {
-        final String typeName = stringFromNode(ctx);
         final int line = ctx.getStart().getLine();
+        final String typeName = stringFromNode(ctx);
+        enterLog("type", typeName, line);
+
         final QName typeQName = parseQName(typeName);
 
         TypeDefinition<?> type = null;
@@ -323,22 +363,20 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 checkMissingBody(typeName, moduleName, line);
                 // if there are no constraints, just grab default base yang type
                 type = YangTypesConverter.javaTypeForBaseYangType(actualPath, namespace, revision, typeName);
-                moduleBuilder.setType(type, actualPath);
+                moduleBuilder.setType(type);
             } else {
                 if ("union".equals(typeName)) {
-                    List<String> typePath = new ArrayList<String>(actualPath);
-                    typePath.add(typeName);
-                    SchemaPath p = createActualSchemaPath(typePath, namespace, revision, yangModelPrefix);
+                    SchemaPath p = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
                     UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(actualPath, namespace, revision, line);
                     moduleBuilder.enterNode(unionBuilder);
                     unionBuilder.setPath(p);
                 } else if ("identityref".equals(typeName)) {
-                    SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix);
+                    SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
                     moduleBuilder.addIdentityrefType(getIdentityrefBase(typeBody), actualPath, path, line);
                 } else {
                     type = parseTypeWithBody(moduleName, typeName, typeBody, actualPath, namespace, revision,
                             yangModelPrefix, moduleBuilder.getActualNode());
-                    moduleBuilder.setType(type, actualPath);
+                    moduleBuilder.setType(type);
                 }
             }
         } else {
@@ -346,10 +384,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                     moduleBuilder.getActualNode());
             // add parent node of this type statement to dirty nodes
             moduleBuilder.addDirtyNode(actualPath);
-            moduleBuilder.setType(type, actualPath);
+            moduleBuilder.setType(type);
         }
 
-        updatePath(typeName);
+        actualPath.push(typeName);
     }
 
     private QName parseQName(String typeName) {
@@ -371,44 +409,46 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitType_stmt(YangParser.Type_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
-
         final String typeName = stringFromNode(ctx);
         if ("union".equals(typeName)) {
             moduleBuilder.exitNode();
         }
+        exitLog("type", actualPath.pop());
     }
 
     @Override
     public void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String groupName = stringFromNode(ctx);
+        enterLog("grouping", groupName, line);
+
         QName groupQName = new QName(namespace, revision, yangModelPrefix, groupName);
-        GroupingBuilder builder = moduleBuilder.addGrouping(groupQName, actualPath, ctx.getStart().getLine());
+        GroupingBuilder builder = moduleBuilder.addGrouping(ctx.getStart().getLine(), groupQName);
         moduleBuilder.enterNode(builder);
-        updatePath(groupName);
+        actualPath.push(groupName);
+
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
     }
 
     @Override
     public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
-        String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("grouping", actualPath.pop());
     }
 
     @Override
     public void enterContainer_stmt(Container_stmtContext ctx) {
         final int line = ctx.getStart().getLine();
         final String containerName = stringFromNode(ctx);
-        QName containerQName = new QName(namespace, revision, yangModelPrefix, containerName);
+        enterLog("container", containerName, line);
 
+        QName containerQName = new QName(namespace, revision, yangModelPrefix, containerName);
         SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, containerName);
 
-        ContainerSchemaNodeBuilder builder = moduleBuilder.addContainerNode(path, containerQName, actualPath, line);
+        ContainerSchemaNodeBuilder builder = moduleBuilder.addContainerNode(line, containerQName, path);
         moduleBuilder.enterNode(builder);
-        updatePath(containerName);
+        actualPath.push(containerName);
 
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
@@ -425,24 +465,26 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitContainer_stmt(Container_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("container", actualPath.pop());
     }
 
     @Override
     public void enterLeaf_stmt(Leaf_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String leafName = stringFromNode(ctx);
+        enterLog("leaf", leafName, line);
+
         QName leafQName = new QName(namespace, revision, yangModelPrefix, leafName);
         SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, leafName);
 
-        LeafSchemaNodeBuilder builder = moduleBuilder.addLeafNode(schemaPath, leafQName, actualPath, ctx.getStart().getLine());
+        LeafSchemaNodeBuilder builder = moduleBuilder.addLeafNode(line, leafQName, schemaPath);
         moduleBuilder.enterNode(builder);
-        updatePath(leafName);
+        actualPath.push(leafName);
 
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
-        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, ctx.getStart().getLine()));
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
 
         String defaultStr = null;
         String unitsStr = null;
@@ -460,53 +502,57 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx) {
-        final String actLeaf = actualPath.pop();
-        logger.debug("exiting " + actLeaf);
         moduleBuilder.exitNode();
+        exitLog("leaf", actualPath.pop());
     }
 
     @Override
     public void enterUses_stmt(YangParser.Uses_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String groupingPathStr = stringFromNode(ctx);
-        UsesNodeBuilder builder = moduleBuilder.addUsesNode(groupingPathStr, actualPath, ctx.getStart().getLine());
+        enterLog("uses", groupingPathStr, line);
+
+        UsesNodeBuilder builder = moduleBuilder.addUsesNode(line, groupingPathStr);
 
         moduleBuilder.enterNode(builder);
-        updatePath(groupingPathStr);
+        actualPath.push(groupingPathStr);
     }
 
     @Override
     public void exitUses_stmt(YangParser.Uses_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("uses", actualPath.pop());
     }
 
     @Override
     public void enterRefine_stmt(YangParser.Refine_stmtContext ctx) {
-        String refineString = stringFromNode(ctx);
+        final String refineString = stringFromNode(ctx);
+        enterLog("refine", refineString, ctx.getStart().getLine());
+
         RefineHolder refine = parseRefine(ctx);
         moduleBuilder.addRefine(refine, actualPath);
         moduleBuilder.enterNode(refine);
-        updatePath(refineString);
+        actualPath.push(refineString);
     }
 
     @Override
     public void exitRefine_stmt(YangParser.Refine_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("refine", actualPath.pop());
     }
 
     @Override
     public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String leafListName = stringFromNode(ctx);
+        enterLog("leaf-list", leafListName, line);
+
         QName leafListQName = new QName(namespace, revision, yangModelPrefix, leafListName);
         SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, leafListName);
 
-        LeafListSchemaNodeBuilder builder = moduleBuilder.addLeafListNode(schemaPath, leafListQName, actualPath, ctx.getStart()
-                .getLine());
+        LeafListSchemaNodeBuilder builder = moduleBuilder.addLeafListNode(line, leafListQName, schemaPath);
         moduleBuilder.enterNode(builder);
-        updatePath(leafListName);
+        actualPath.push(leafListName);
 
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
@@ -525,24 +571,26 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("leaf-list", actualPath.pop());
     }
 
     @Override
     public void enterList_stmt(List_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String listName = stringFromNode(ctx);
+        enterLog("list", listName, line);
+
         QName listQName = new QName(namespace, revision, yangModelPrefix, listName);
         SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, listName);
 
-        ListSchemaNodeBuilder builder = moduleBuilder.addListNode(schemaPath, listQName, actualPath, ctx.getStart().getLine());
+        ListSchemaNodeBuilder builder = moduleBuilder.addListNode(line, listQName, schemaPath);
         moduleBuilder.enterNode(builder);
-        updatePath(listName);
+        actualPath.push(listName);
 
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
-        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, ctx.getStart().getLine()));
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
 
         String keyDefinition = "";
         for (int i = 0; i < ctx.getChildCount(); ++i) {
@@ -561,45 +609,50 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitList_stmt(List_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("list", actualPath.pop());
     }
 
     @Override
     public void enterAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String anyXmlName = stringFromNode(ctx);
+        enterLog("anyxml", anyXmlName, line);
+
         QName anyXmlQName = new QName(namespace, revision, yangModelPrefix, anyXmlName);
         SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, anyXmlName);
 
-        AnyXmlBuilder builder = moduleBuilder.addAnyXml(schemaPath, anyXmlQName, actualPath, ctx.getStart().getLine());
+        AnyXmlBuilder builder = moduleBuilder.addAnyXml(line, anyXmlQName, schemaPath);
         moduleBuilder.enterNode(builder);
-        updatePath(anyXmlName);
+        actualPath.push(anyXmlName);
 
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
-        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, ctx.getStart().getLine()));
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
     }
 
     @Override
     public void exitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("anyxml", actualPath.pop());
     }
 
     @Override
     public void enterChoice_stmt(YangParser.Choice_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String choiceName = stringFromNode(ctx);
+        enterLog("choice", choiceName, line);
+
         QName choiceQName = new QName(namespace, revision, yangModelPrefix, choiceName);
-        ChoiceBuilder builder = moduleBuilder.addChoice(choiceQName, actualPath, ctx.getStart().getLine());
+
+        ChoiceBuilder builder = moduleBuilder.addChoice(line, choiceQName);
         moduleBuilder.enterNode(builder);
+        actualPath.push(choiceName);
 
-        updatePath(choiceName);
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
-        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, ctx.getStart().getLine()));
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
 
         // set 'default' case
         for (int i = 0; i < ctx.getChildCount(); i++) {
@@ -614,19 +667,21 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitChoice_stmt(YangParser.Choice_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("choice", actualPath.pop());
     }
 
     @Override
     public void enterCase_stmt(YangParser.Case_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String caseName = stringFromNode(ctx);
-        QName choiceQName = new QName(namespace, revision, yangModelPrefix, caseName);
-        ChoiceCaseBuilder builder = moduleBuilder.addCase(choiceQName, actualPath, ctx.getStart().getLine());
+        enterLog("case", caseName, line);
+
+        QName caseQName = new QName(namespace, revision, yangModelPrefix, caseName);
+        ChoiceCaseBuilder builder = moduleBuilder.addCase(line, caseQName);
         moduleBuilder.enterNode(builder);
+        actualPath.push(caseName);
 
-        updatePath(caseName);
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
@@ -634,19 +689,20 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitCase_stmt(YangParser.Case_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("case", actualPath.pop());
     }
 
     @Override
     public void enterNotification_stmt(YangParser.Notification_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String notificationName = stringFromNode(ctx);
+        enterLog("notification", notificationName, line);
+
         QName notificationQName = new QName(namespace, revision, yangModelPrefix, notificationName);
-        NotificationBuilder builder = moduleBuilder.addNotification(notificationQName, actualPath, ctx.getStart()
-                .getLine());
+        NotificationBuilder builder = moduleBuilder.addNotification(notificationQName, actualPath, line);
         moduleBuilder.enterNode(builder);
-        updatePath(notificationName);
+        actualPath.push(notificationName);
 
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
@@ -654,15 +710,17 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitNotification_stmt(YangParser.Notification_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("notification", actualPath.pop());
     }
 
-    // Unknown types
+    // Unknown nodes
     @Override
     public void enterIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String nodeParameter = stringFromNode(ctx);
+        enterLog("unknown-node", nodeParameter, line);
+
         QName nodeType = null;
 
         final String nodeTypeStr = ctx.getChild(0).getText();
@@ -685,11 +743,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             qname = new QName(namespace, revision, yangModelPrefix, nodeParameter);
         }
 
-        UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(qname, actualPath, ctx.getStart()
-                .getLine());
+        UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(qname, actualPath, line);
         builder.setNodeType(nodeType);
         builder.setNodeParameter(nodeParameter);
-        updatePath(nodeParameter);
+        actualPath.push(nodeParameter);
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
         moduleBuilder.enterNode(builder);
@@ -697,18 +754,20 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("unknown-node", actualPath.pop());
     }
 
     @Override
     public void enterRpc_stmt(YangParser.Rpc_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String rpcName = stringFromNode(ctx);
+        enterLog("rpc", rpcName, line);
+
         QName rpcQName = new QName(namespace, revision, yangModelPrefix, rpcName);
-        RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(rpcQName, actualPath, ctx.getStart().getLine());
+        RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(line, rpcQName);
         moduleBuilder.enterNode(rpcBuilder);
-        updatePath(rpcName);
+        actualPath.push(rpcName);
 
         rpcBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, rpcBuilder);
@@ -716,20 +775,22 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitRpc_stmt(YangParser.Rpc_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("rpc", actualPath.pop());
     }
 
     @Override
     public void enterInput_stmt(YangParser.Input_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String input = "input";
+        enterLog(input, input, line);
+
         QName rpcQName = new QName(namespace, revision, yangModelPrefix, input);
         SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, input);
 
-        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcInput(path, rpcQName, ctx.getStart().getLine());
+        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcInput(path, rpcQName, line);
         moduleBuilder.enterNode(builder);
-        updatePath(input);
+        actualPath.push(input);
 
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
@@ -737,20 +798,22 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitInput_stmt(YangParser.Input_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("input", actualPath.pop());
     }
 
     @Override
     public void enterOutput_stmt(YangParser.Output_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String output = "output";
+        enterLog(output, output, line);
+
         QName rpcQName = new QName(namespace, revision, yangModelPrefix, output);
         SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, output);
 
-        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcOutput(path, rpcQName, ctx.getStart().getLine());
+        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcOutput(path, rpcQName, line);
         moduleBuilder.enterNode(builder);
-        updatePath(output);
+        actualPath.push(output);
 
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
@@ -758,18 +821,20 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitOutput_stmt(YangParser.Output_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("output", actualPath.pop());
     }
 
     @Override
     public void enterFeature_stmt(YangParser.Feature_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String featureName = stringFromNode(ctx);
+        enterLog("feature", featureName, line);
+
         QName featureQName = new QName(namespace, revision, yangModelPrefix, featureName);
-        FeatureBuilder featureBuilder = moduleBuilder.addFeature(featureQName, actualPath, ctx.getStart().getLine());
+        FeatureBuilder featureBuilder = moduleBuilder.addFeature(line, featureQName);
         moduleBuilder.enterNode(featureBuilder);
-        updatePath(featureName);
+        actualPath.push(featureName);
 
         featureBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, featureBuilder);
@@ -777,19 +842,21 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitFeature_stmt(YangParser.Feature_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("feature", actualPath.pop());
     }
 
     @Override
     public void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String targetPath = stringFromNode(ctx);
+        enterLog("deviation", targetPath, line);
+
         String reference = null;
         String deviate = null;
-        DeviationBuilder builder = moduleBuilder.addDeviation(targetPath, actualPath, ctx.getStart().getLine());
+        DeviationBuilder builder = moduleBuilder.addDeviation(targetPath, actualPath, line);
         moduleBuilder.enterNode(builder);
-        updatePath(targetPath);
+        actualPath.push(targetPath);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
@@ -811,19 +878,20 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("deviation", actualPath.pop());
     }
 
     @Override
     public void enterIdentity_stmt(YangParser.Identity_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String identityName = stringFromNode(ctx);
+        enterLog("identity", identityName, line);
+
         final QName identityQName = new QName(namespace, revision, yangModelPrefix, identityName);
-        IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(identityQName, actualPath, ctx.getStart()
-                .getLine());
+        IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(identityQName, actualPath, line);
         moduleBuilder.enterNode(builder);
-        updatePath(identityName);
+        actualPath.push(identityName);
 
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
@@ -839,17 +907,24 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitIdentity_stmt(YangParser.Identity_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
         moduleBuilder.exitNode();
+        exitLog("identity", actualPath.pop());
     }
 
     public ModuleBuilder getModuleBuilder() {
         return moduleBuilder;
     }
 
-    private void updatePath(String containerName) {
-        actualPath.push(containerName);
+    private void enterLog(String p1, String p2, int line) {
+        logger.debug("entering " + p1 + " " + p2 + " (" + line + ")");
+    }
+
+    private void exitLog(String p1, String p2) {
+        logger.debug("exiting " + p1 + " " + p2);
+    }
+
+    private void setLog(String p1, String p2) {
+        logger.debug("setting " + p1 + " " + p2);
     }
 
 }
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/Comparators.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/Comparators.java
new file mode 100644 (file)
index 0000000..ea87eec
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.yang.parser.util;
+
+import java.util.Comparator;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
+
+public class Comparators {
+
+    public static final QNameComparator QNAME_COMP = new QNameComparator();
+    public static final SchemaNodeComparator SCHEMA_NODE_COMP = new SchemaNodeComparator();
+
+    private Comparators() {
+    }
+
+    private static final class QNameComparator implements Comparator<QName> {
+        @Override
+        public int compare(QName o1, QName o2) {
+            return o1.getLocalName().compareTo(o2.getLocalName());
+        }
+    }
+
+    private static final class SchemaNodeComparator implements Comparator<SchemaNode> {
+        @Override
+        public int compare(SchemaNode o1, SchemaNode o2) {
+            return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
+        }
+    }
+
+}
index 5c42b29..aea9409 100644 (file)
@@ -40,8 +40,7 @@ import com.google.common.collect.Sets;
 public final class ModuleDependencySort {
 
     private static final Date DEFAULT_REVISION = new Date(0);
-    private static final Logger logger = LoggerFactory
-            .getLogger(ModuleDependencySort.class);
+    private static final Logger logger = LoggerFactory.getLogger(ModuleDependencySort.class);
 
     /**
      * Topological sort of module builder dependency graph.
@@ -72,7 +71,7 @@ public final class ModuleDependencySort {
 
             @Override
             public ModuleBuilder apply(Node input) {
-                if(((ModuleNodeImpl) input).getReference() instanceof ModuleBuilder) {
+                if (((ModuleNodeImpl) input).getReference() instanceof ModuleBuilder) {
                     return (ModuleBuilder) ((ModuleNodeImpl) input).getReference();
                 } else {
                     return null;
@@ -113,8 +112,7 @@ public final class ModuleDependencySort {
     }
 
     @VisibleForTesting
-    static Map<String, Map<Date, ModuleNodeImpl>> createModuleGraph(
-            List<?> builders) {
+    static Map<String, Map<Date, ModuleNodeImpl>> createModuleGraph(List<?> builders) {
         Map<String, Map<Date, ModuleNodeImpl>> moduleGraph = Maps.newHashMap();
 
         processModules(moduleGraph, builders);
@@ -126,8 +124,7 @@ public final class ModuleDependencySort {
     /**
      * Extract module:revision from module builders
      */
-    private static void processDependencies(
-            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
+    private static void processDependencies(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
         Map<String, Date> imported = Maps.newHashMap();
 
         // Create edges in graph
@@ -154,26 +151,24 @@ public final class ModuleDependencySort {
 
             for (ModuleImport imprt : imports) {
                 String toName = imprt.getModuleName();
-                Date toRevision = imprt.getRevision() == null ? DEFAULT_REVISION
-                        : imprt.getRevision();
+                Date toRevision = imprt.getRevision() == null ? DEFAULT_REVISION : imprt.getRevision();
 
-                ModuleNodeImpl from = moduleGraph.get(fromName).get(
-                        fromRevision);
+                ModuleNodeImpl from = moduleGraph.get(fromName).get(fromRevision);
 
-                ModuleNodeImpl to = getModuleByNameAndRevision(moduleGraph,
-                        fromName, fromRevision, toName, toRevision);
+                ModuleNodeImpl to = getModuleByNameAndRevision(moduleGraph, fromName, fromRevision, toName, toRevision);
 
                 /*
                  * Check imports: If module is imported twice with different
                  * revisions then throw exception
                  */
-                if (imported.get(toName) != null
-                        && !imported.get(toName).equals(toRevision))
-                    ex(String
-                            .format("Module:%s imported twice with different revisions:%s, %s",
-                                    toName,
-                                    formatRevDate(imported.get(toName)),
-                                    formatRevDate(toRevision)));
+                if (imported.get(toName) != null && !imported.get(toName).equals(toRevision)) {
+                    if (!imported.get(toName).equals(DEFAULT_REVISION) && !toRevision.equals(DEFAULT_REVISION)) {
+                        ex(String.format("Module:%s imported twice with different revisions:%s, %s", toName,
+                                formatRevDate(imported.get(toName)), formatRevDate(toRevision)));
+                    }
+
+                }
+
                 imported.put(toName, toRevision);
 
                 from.addEdge(to);
@@ -184,28 +179,23 @@ public final class ModuleDependencySort {
     /**
      * Get imported module by its name and revision from moduleGraph
      */
-    private static ModuleNodeImpl getModuleByNameAndRevision(
-            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph,
+    private static ModuleNodeImpl getModuleByNameAndRevision(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph,
             String fromName, Date fromRevision, String toName, Date toRevision) {
         ModuleNodeImpl to = null;
 
-        if (moduleGraph.get(toName) == null
-                || !moduleGraph.get(toName).containsKey(toRevision)) {
+        if (moduleGraph.get(toName) == null || !moduleGraph.get(toName).containsKey(toRevision)) {
             // If revision is not specified in import, but module exists
             // with different revisions, take first
-            if (moduleGraph.get(toName) != null
-                    && !moduleGraph.get(toName).isEmpty()
+            if (moduleGraph.get(toName) != null && !moduleGraph.get(toName).isEmpty()
                     && toRevision.equals(DEFAULT_REVISION)) {
                 to = moduleGraph.get(toName).values().iterator().next();
                 logger.warn(String
                         .format("Import:%s:%s by module:%s:%s does not specify revision, using:%s:%s for module dependency sort",
-                                toName, formatRevDate(toRevision), fromName,
-                                formatRevDate(fromRevision), to.getName(),
+                                toName, formatRevDate(toRevision), fromName, formatRevDate(fromRevision), to.getName(),
                                 formatRevDate(to.getRevision())));
             } else
-                ex(String.format("Not existing module imported:%s:%s by:%s:%s",
-                        toName, formatRevDate(toRevision), fromName,
-                        formatRevDate(fromRevision)));
+                ex(String.format("Not existing module imported:%s:%s by:%s:%s", toName, formatRevDate(toRevision),
+                        fromName, formatRevDate(fromRevision)));
         } else {
             to = moduleGraph.get(toName).get(toRevision);
         }
@@ -220,8 +210,7 @@ public final class ModuleDependencySort {
      * Extract dependencies from module builders or modules to fill dependency
      * graph
      */
-    private static void processModules(
-            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
+    private static void processModules(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
 
         // Process nodes
         for (Object mb : builders) {
@@ -236,11 +225,9 @@ public final class ModuleDependencySort {
                 name = ((ModuleBuilder) mb).getName();
                 rev = ((ModuleBuilder) mb).getRevision();
             } else {
-                throw new IllegalStateException(
-                        String.format(
-                                "Unexpected type of node for sort, expected only:%s, %s, got:%s",
-                                Module.class, ModuleBuilder.class,
-                                mb.getClass()));
+                throw new IllegalStateException(String.format(
+                        "Unexpected type of node for sort, expected only:%s, %s, got:%s", Module.class,
+                        ModuleBuilder.class, mb.getClass()));
             }
 
             if (rev == null)
@@ -250,16 +237,14 @@ public final class ModuleDependencySort {
                 moduleGraph.put(name, Maps.<Date, ModuleNodeImpl> newHashMap());
 
             if (moduleGraph.get(name).get(rev) != null)
-                ex(String.format("Module:%s with revision:%s declared twice",
-                        name, formatRevDate(rev)));
+                ex(String.format("Module:%s with revision:%s declared twice", name, formatRevDate(rev)));
 
             moduleGraph.get(name).put(rev, new ModuleNodeImpl(name, rev, mb));
         }
     }
 
     private static String formatRevDate(Date rev) {
-        return rev == DEFAULT_REVISION ? "default"
-                : YangParserListenerImpl.simpleDateFormat.format(rev);
+        return rev == DEFAULT_REVISION ? "default" : YangParserListenerImpl.simpleDateFormat.format(rev);
     }
 
     @VisibleForTesting
@@ -287,8 +272,7 @@ public final class ModuleDependencySort {
             final int prime = 31;
             int result = 1;
             result = prime * result + ((name == null) ? 0 : name.hashCode());
-            result = prime * result
-                    + ((revision == null) ? 0 : revision.hashCode());
+            result = prime * result + ((revision == null) ? 0 : revision.hashCode());
             return result;
         }
 
@@ -316,8 +300,7 @@ public final class ModuleDependencySort {
 
         @Override
         public String toString() {
-            return "Module [name=" + name + ", revision="
-                    + formatRevDate(revision) + "]";
+            return "Module [name=" + name + ", revision=" + formatRevDate(revision) + "]";
         }
 
         public Object getReference() {
index 2a7bca4..64b06ad 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.controller.yang.parser.util;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -501,6 +500,14 @@ public final class ParserUtils {
             }
         }
 
+        // set correct path for all cases
+        if(childNode instanceof ChoiceBuilder) {
+            ChoiceBuilder choiceBuilder = (ChoiceBuilder) childNode;
+            for (ChoiceCaseBuilder choiceCaseBuilder : choiceBuilder.getCases()) {
+                correctAugmentChildPath(choiceCaseBuilder, childNode.getPath());
+            }
+        }
+
         // if node can contains type, correct path for this type too
         if (childNode instanceof TypeAwareBuilder) {
             TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) childNode;
@@ -756,8 +763,8 @@ public final class ParserUtils {
     }
 
     public static ContainerSchemaNodeBuilder createContainer(ContainerSchemaNode container, int line) {
-        final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(container.getQName(),
-                container.getPath(), line);
+        final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(line, container.getQName(),
+                container.getPath());
         convertDataSchemaNode(container, builder);
         builder.setConfiguration(container.isConfiguration());
         builder.setUnknownNodes(container.getUnknownSchemaNodes());
@@ -771,7 +778,7 @@ public final class ParserUtils {
     }
 
     public static ListSchemaNodeBuilder createList(ListSchemaNode list, int line) {
-        ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(list.getQName(), list.getPath(), line);
+        ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(line, list.getQName(), list.getPath());
         convertDataSchemaNode(list, builder);
         builder.setConfiguration(list.isConfiguration());
         builder.setUnknownNodes(list.getUnknownSchemaNodes());
@@ -785,8 +792,8 @@ public final class ParserUtils {
     }
 
     public static LeafListSchemaNodeBuilder createLeafList(LeafListSchemaNode leafList, int line) {
-        final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(leafList.getQName(),
-                leafList.getPath(), line);
+        final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(line, leafList.getQName(),
+                leafList.getPath());
         convertDataSchemaNode(leafList, builder);
         builder.setConfiguration(leafList.isConfiguration());
         builder.setType(leafList.getType());
@@ -796,7 +803,7 @@ public final class ParserUtils {
     }
 
     public static ChoiceBuilder createChoice(ChoiceNode choice, int line) {
-        final ChoiceBuilder builder = new ChoiceBuilder(choice.getQName(), line);
+        final ChoiceBuilder builder = new ChoiceBuilder(line, choice.getQName());
         convertDataSchemaNode(choice, builder);
         builder.setConfiguration(choice.isConfiguration());
         builder.setCases(choice.getCases());
@@ -806,7 +813,7 @@ public final class ParserUtils {
     }
 
     public static AnyXmlBuilder createAnyXml(AnyXmlSchemaNode anyxml, int line) {
-        final AnyXmlBuilder builder = new AnyXmlBuilder(anyxml.getQName(), anyxml.getPath(), line);
+        final AnyXmlBuilder builder = new AnyXmlBuilder(line, anyxml.getQName(), anyxml.getPath());
         convertDataSchemaNode(anyxml, builder);
         builder.setConfiguration(anyxml.isConfiguration());
         builder.setUnknownNodes(anyxml.getUnknownSchemaNodes());
@@ -846,16 +853,16 @@ public final class ParserUtils {
         return builder;
     }
 
-    public static UnknownSchemaNodeBuilder createUnknownSchemaNode(UnknownSchemaNode grouping, int line) {
-        final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(grouping.getQName(), line);
-        builder.setPath(grouping.getPath());
-        builder.setUnknownNodes(grouping.getUnknownSchemaNodes());
-        builder.setDescription(grouping.getDescription());
-        builder.setReference(grouping.getReference());
-        builder.setStatus(grouping.getStatus());
-        builder.setAddedByUses(grouping.isAddedByUses());
-        builder.setNodeType(grouping.getNodeType());
-        builder.setNodeParameter(grouping.getNodeParameter());
+    public static UnknownSchemaNodeBuilder createUnknownSchemaNode(UnknownSchemaNode unknownNode, int line) {
+        final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(line, unknownNode.getQName());
+        builder.setPath(unknownNode.getPath());
+        builder.setUnknownNodes(unknownNode.getUnknownSchemaNodes());
+        builder.setDescription(unknownNode.getDescription());
+        builder.setReference(unknownNode.getReference());
+        builder.setStatus(unknownNode.getStatus());
+        builder.setAddedByUses(unknownNode.isAddedByUses());
+        builder.setNodeType(unknownNode.getNodeType());
+        builder.setNodeParameter(unknownNode.getNodeParameter());
         return builder;
     }
 
@@ -992,11 +999,11 @@ public final class ParserUtils {
     }
 
     public static void processAugmentation(final AugmentationSchemaBuilder augmentBuilder, final List<QName> path,
-            final ModuleBuilder module, final QName qname, final ModuleBuilder dependentModuleBuilder) {
+            final ModuleBuilder module, final ModuleBuilder dependentModuleBuilder) {
         DataSchemaNodeBuilder currentParent = null;
         for (DataSchemaNodeBuilder child : dependentModuleBuilder.getChildNodeBuilders()) {
             final QName childQName = child.getQName();
-            if (childQName.getLocalName().equals(qname.getLocalName())) {
+            if (childQName.getLocalName().equals(path.get(0).getLocalName())) {
                 currentParent = child;
                 break;
             }
@@ -1009,7 +1016,7 @@ public final class ParserUtils {
         for (int i = 1; i < path.size(); i++) {
             final QName currentQName = path.get(i);
             DataSchemaNodeBuilder newParent = null;
-            if(currentParent instanceof DataNodeContainerBuilder) {
+            if (currentParent instanceof DataNodeContainerBuilder) {
                 for (DataSchemaNodeBuilder child : ((DataNodeContainerBuilder) currentParent).getChildNodeBuilders()) {
                     final QName childQName = child.getQName();
                     if (childQName.getLocalName().equals(currentQName.getLocalName())) {
@@ -1017,8 +1024,8 @@ public final class ParserUtils {
                         break;
                     }
                 }
-            } else if(currentParent instanceof ChoiceBuilder) {
-                for(ChoiceCaseBuilder caseBuilder : ((ChoiceBuilder)currentParent).getCases()) {
+            } else if (currentParent instanceof ChoiceBuilder) {
+                for (ChoiceCaseBuilder caseBuilder : ((ChoiceBuilder) currentParent).getCases()) {
                     final QName caseQName = caseBuilder.getQName();
                     if (caseQName.getLocalName().equals(currentQName.getLocalName())) {
                         newParent = caseBuilder;
@@ -1201,8 +1208,8 @@ public final class ParserUtils {
                         return constraints;
                     }
                 } else {
-                    TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve.getPath(),
-                            dependentModuleBuilder, qname.getLocalName(), builder.getName(), nodeToResolve.getLine());
+                    TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve, dependentModuleBuilder,
+                            qname.getLocalName(), builder.getName(), nodeToResolve.getLine());
                     return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModuleBuilder, context);
                 }
             } else if (type instanceof ExtendedType) {
@@ -1216,8 +1223,8 @@ public final class ParserUtils {
                 if (base instanceof UnknownType) {
                     ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, base.getQName()
                             .getPrefix(), nodeToResolve.getLine());
-                    TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve.getPath(), dependentModule,
-                            base.getQName().getLocalName(), builder.getName(), nodeToResolve.getLine());
+                    TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve, dependentModule, base
+                            .getQName().getLocalName(), builder.getName(), nodeToResolve.getLine());
                     return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModule, context);
                 } else {
                     // it has to be base yang type
@@ -1247,43 +1254,36 @@ public final class ParserUtils {
      *            current line in yang model
      * @return
      */
-    public static TypeDefinitionBuilder findTypeDefinitionBuilder(final SchemaPath dirtyNodeSchemaPath,
+    public static TypeDefinitionBuilder findTypeDefinitionBuilder(final TypeAwareBuilder nodeToResolve,
             final ModuleBuilder dependentModule, final String typeName, final String currentModuleName, final int line) {
-        final List<QName> path = dirtyNodeSchemaPath.getPath();
+
         TypeDefinitionBuilder result = null;
 
-        Set<TypeDefinitionBuilder> typedefs = dependentModule.getModuleTypedefs();
+        Set<TypeDefinitionBuilder> typedefs = dependentModule.getTypeDefinitionBuilders();
         result = findTypedefBuilderByName(typedefs, typeName);
+        if (result != null) {
+            return result;
+        }
 
-        if (result == null) {
-            Builder currentNode = null;
-            final List<String> currentPath = new ArrayList<String>();
-            currentPath.add(dependentModule.getName());
-
-            for (int i = 0; i < path.size(); i++) {
-                QName qname = path.get(i);
-                currentPath.add(qname.getLocalName());
-                currentNode = dependentModule.getModuleNode(currentPath);
-
-                if (currentNode instanceof RpcDefinitionBuilder) {
-                    typedefs = ((RpcDefinitionBuilder) currentNode).getTypeDefinitions();
-                } else if (currentNode instanceof DataNodeContainerBuilder) {
-                    typedefs = ((DataNodeContainerBuilder) currentNode).getTypeDefinitionBuilders();
-                } else {
-                    typedefs = Collections.emptySet();
-                }
-
-                result = findTypedefBuilderByName(typedefs, typeName);
-                if (result != null) {
-                    break;
-                }
+        Builder parent = nodeToResolve.getParent();
+        while (parent != null) {
+            if (parent instanceof DataNodeContainerBuilder) {
+                typedefs = ((DataNodeContainerBuilder) parent).getTypeDefinitionBuilders();
+            } else if (parent instanceof RpcDefinitionBuilder) {
+                typedefs = ((RpcDefinitionBuilder) parent).getTypeDefinitions();
+            }
+            result = findTypedefBuilderByName(typedefs, typeName);
+            if (result == null) {
+                parent = parent.getParent();
+            } else {
+                break;
             }
         }
 
-        if (result != null) {
-            return result;
+        if (result == null) {
+            throw new YangParseException(currentModuleName, line, "Referenced type '" + typeName + "' not found.");
         }
-        throw new YangParseException(currentModuleName, line, "Referenced type '" + typeName + "' not found.");
+        return result;
     }
 
 }
index 7d22891..1f5e294 100644 (file)
@@ -16,8 +16,9 @@ import org.opendaylight.controller.yang.parser.builder.api.ConfigNode;
 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
 
 public final class RefineHolder implements Builder, ConfigNode {
-    private final String name;
+    private Builder parent;
     private final int line;
+    private final String name;
     private String defaultStr;
     private String description;
     private String reference;
@@ -29,7 +30,7 @@ public final class RefineHolder implements Builder, ConfigNode {
     private Integer maxElements;
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
 
-    public RefineHolder(final String name, final int line) {
+    public RefineHolder(final int line, final String name) {
         this.name = name;
         this.line = line;
     }
@@ -39,6 +40,16 @@ public final class RefineHolder implements Builder, ConfigNode {
         return line;
     }
 
+    @Override
+    public Builder getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(final Builder parent) {
+        this.parent = parent;
+    }
+
     public String getDefaultStr() {
         return defaultStr;
     }
@@ -130,4 +141,100 @@ public final class RefineHolder implements Builder, ConfigNode {
         return null;
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((addedUnknownNodes == null) ? 0 : addedUnknownNodes.hashCode());
+        result = prime * result + ((config == null) ? 0 : config.hashCode());
+        result = prime * result + ((defaultStr == null) ? 0 : defaultStr.hashCode());
+        result = prime * result + ((description == null) ? 0 : description.hashCode());
+        result = prime * result + ((mandatory == null) ? 0 : mandatory.hashCode());
+        result = prime * result + ((maxElements == null) ? 0 : maxElements.hashCode());
+        result = prime * result + ((minElements == null) ? 0 : minElements.hashCode());
+        result = prime * result + ((must == null) ? 0 : must.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((parent == null) ? 0 : parent.hashCode());
+        result = prime * result + ((presence == null) ? 0 : presence.hashCode());
+        result = prime * result + ((reference == null) ? 0 : reference.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;
+        RefineHolder other = (RefineHolder) obj;
+        if (addedUnknownNodes == null) {
+            if (other.addedUnknownNodes != null)
+                return false;
+        } else if (!addedUnknownNodes.equals(other.addedUnknownNodes))
+            return false;
+        if (config == null) {
+            if (other.config != null)
+                return false;
+        } else if (!config.equals(other.config))
+            return false;
+        if (defaultStr == null) {
+            if (other.defaultStr != null)
+                return false;
+        } else if (!defaultStr.equals(other.defaultStr))
+            return false;
+        if (description == null) {
+            if (other.description != null)
+                return false;
+        } else if (!description.equals(other.description))
+            return false;
+        if (mandatory == null) {
+            if (other.mandatory != null)
+                return false;
+        } else if (!mandatory.equals(other.mandatory))
+            return false;
+        if (maxElements == null) {
+            if (other.maxElements != null)
+                return false;
+        } else if (!maxElements.equals(other.maxElements))
+            return false;
+        if (minElements == null) {
+            if (other.minElements != null)
+                return false;
+        } else if (!minElements.equals(other.minElements))
+            return false;
+        if (must == null) {
+            if (other.must != null)
+                return false;
+        } else if (!must.equals(other.must))
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (parent == null) {
+            if (other.parent != null)
+                return false;
+        } else if (!parent.equals(other.parent))
+            return false;
+        if (presence == null) {
+            if (other.presence != null)
+                return false;
+        } else if (!presence.equals(other.presence))
+            return false;
+        if (reference == null) {
+            if (other.reference != null)
+                return false;
+        } else if (!reference.equals(other.reference))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "revine " + name;
+    }
+
 }
index 856f8e2..ada2d2c 100644 (file)
@@ -924,12 +924,12 @@ public final class YangModelBuilderUtil {
                 // If the parent node is a 'case' node, the value is the same as
                 // the 'case' node's parent 'choice' node
                 ChoiceCaseBuilder choiceCase = (ChoiceCaseBuilder) parent;
-                ChoiceBuilder choice = choiceCase.getParent();
+                Builder choice = choiceCase.getParent();
                 Boolean parentConfig = null;
-                if (choice == null) {
-                    parentConfig = true;
+                if(choice instanceof ChoiceBuilder) {
+                    parentConfig = ((ChoiceBuilder)choice).isConfiguration();
                 } else {
-                    parentConfig = choice.isConfiguration();
+                    parentConfig = true;
                 }
                 result = parentConfig;
             } else {
@@ -1460,7 +1460,7 @@ public final class YangModelBuilderUtil {
      */
     public static RefineHolder parseRefine(Refine_stmtContext refineCtx) {
         final String refineTarget = stringFromNode(refineCtx);
-        final RefineHolder refine = new RefineHolder(refineTarget, refineCtx.getStart().getLine());
+        final RefineHolder refine = new RefineHolder(refineCtx.getStart().getLine(), refineTarget);
         for (int j = 0; j < refineCtx.getChildCount(); j++) {
             ParseTree refinePom = refineCtx.getChild(j);
             if (refinePom instanceof Refine_pomContext) {
index 3070c74..fb73bd6 100644 (file)
@@ -92,7 +92,6 @@ public class YangParserNegativeTest {
         } catch (YangParseException e) {
             assertTrue(e.getMessage().contains("Invalid length constraint: <4, 10>"));
         }
-
     }
 
     @Test
@@ -106,7 +105,61 @@ public class YangParserNegativeTest {
         } catch (YangParseException e) {
             assertTrue(e.getMessage().contains("Invalid range constraint: <5, 20>"));
         }
+    }
+
+    @Test
+    public void testDuplicateContainer() throws IOException {
+        try {
+            try (InputStream stream = new FileInputStream(getClass().getResource(
+                    "/negative-scenario/duplicity/container.yang").getPath())) {
+                TestUtils.loadModule(stream);
+                fail("YangParseException should by thrown");
+            }
+        } catch (YangParseException e) {
+            assertTrue(e.getMessage()
+                    .contains("Error in module 'container' on line 10: Duplicate node found at line 6"));
+        }
+    }
+
+    @Test
+    public void testDuplicateContainerList() throws IOException {
+        try {
+            try (InputStream stream = new FileInputStream(getClass().getResource(
+                    "/negative-scenario/duplicity/container-list.yang").getPath())) {
+                TestUtils.loadModule(stream);
+                fail("YangParseException should by thrown");
+            }
+        } catch (YangParseException e) {
+            assertTrue(e.getMessage().contains(
+                    "Error in module 'container-list' on line 10: Duplicate node found at line 6"));
+        }
+    }
 
+    @Test
+    public void testDuplicateContainerLeaf() throws IOException {
+        try {
+            try (InputStream stream = new FileInputStream(getClass().getResource(
+                    "/negative-scenario/duplicity/container-leaf.yang").getPath())) {
+                TestUtils.loadModule(stream);
+                fail("YangParseException should by thrown");
+            }
+        } catch (YangParseException e) {
+            assertTrue(e.getMessage().contains(
+                    "Error in module 'container-leaf' on line 10: Duplicate node found at line 6"));
+        }
+    }
+
+    @Test
+    public void testDuplicateTypedef() throws IOException {
+        try {
+            try (InputStream stream = new FileInputStream(getClass().getResource(
+                    "/negative-scenario/duplicity/typedef.yang").getPath())) {
+                TestUtils.loadModule(stream);
+                fail("YangParseException should by thrown");
+            }
+        } catch (YangParseException e) {
+            assertTrue(e.getMessage().contains("Error in module 'typedef' on line 10: Duplicate node found at line 6"));
+        }
     }
 
 }
index d331cff..3eff948 100644 (file)
@@ -28,10 +28,12 @@ import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.controller.yang.model.api.ChoiceNode;
 import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
 import org.opendaylight.controller.yang.model.api.Deviation;
 import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
 import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
 import org.opendaylight.controller.yang.model.api.FeatureDefinition;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
@@ -94,6 +96,59 @@ public class YangParserTest {
         assertEquals(" WILL BE DEFINED LATER", test.getReference());
     }
 
+    @Test
+    public void testOrderingTypedef() {
+        Module test = TestUtils.findModule(modules, "types2");
+        Set<TypeDefinition<?>> typedefs = test.getTypeDefinitions();
+        String[] expectedOrder = new String[] { "my-base-int32-type", "my-custom-string", "my-decimal-type",
+                "my-decimal-type-ext", "my-int-type", "my-int-type-ext", "my-int-type2", "my-string-type",
+                "my-string-type-ext", "my-string-type2", "my-type1", "my-union", "my-union-ext", "nested-union1",
+                "nested-union2" };
+        String[] actualOrder = new String[typedefs.size()];
+
+        int i = 0;
+        for (TypeDefinition<?> type : typedefs) {
+            actualOrder[i] = type.getQName().getLocalName();
+            i++;
+        }
+        assertArrayEquals(expectedOrder, actualOrder);
+    }
+
+    @Test
+    public void testOrderingChildNodes() {
+        Module test = TestUtils.findModule(modules, "types2");
+        Set<DataSchemaNode> childNodes = test.getChildNodes();
+        String[] expectedOrder = new String[] { "count", "if-name", "interfaces", "name", "nested-type-leaf", "peer",
+                "system" };
+        String[] actualOrder = new String[childNodes.size()];
+
+        int i = 0;
+        for (DataSchemaNode child : childNodes) {
+            actualOrder[i] = child.getQName().getLocalName();
+            i++;
+        }
+        assertArrayEquals(expectedOrder, actualOrder);
+    }
+
+    @Test
+    public void testOrderingNestedChildNodes() {
+        Module test = TestUtils.findModule(modules, "types2");
+        Set<GroupingDefinition> groupings = test.getGroupings();
+        assertEquals(1, groupings.size());
+        GroupingDefinition target = groupings.iterator().next();
+
+        Set<DataSchemaNode> childNodes = target.getChildNodes();
+        String[] expectedOrder = new String[] { "address", "addresses", "data", "how", "port" };
+        String[] actualOrder = new String[childNodes.size()];
+
+        int i = 0;
+        for (DataSchemaNode child : childNodes) {
+            actualOrder[i] = child.getQName().getLocalName();
+            i++;
+        }
+        assertArrayEquals(expectedOrder, actualOrder);
+    }
+
     @Test
     public void testParseContainer() {
         Module test = TestUtils.findModule(modules, "types2");
@@ -567,10 +622,10 @@ public class YangParserTest {
         assertEquals(5, cases.size());
         ChoiceCaseNode input = null;
         ChoiceCaseNode output = null;
-        for(ChoiceCaseNode caseNode : cases) {
-            if("input".equals(caseNode.getQName().getLocalName())) {
+        for (ChoiceCaseNode caseNode : cases) {
+            if ("input".equals(caseNode.getQName().getLocalName())) {
                 input = caseNode;
-            } else if("output".equals(caseNode.getQName().getLocalName())) {
+            } else if ("output".equals(caseNode.getQName().getLocalName())) {
                 output = caseNode;
             }
         }
index 484e34d..70bf404 100644 (file)
@@ -7,10 +7,10 @@
  */
 package org.opendaylight.controller.yang.parser.util;
 
-import static org.hamcrest.core.AnyOf.*;
-import static org.hamcrest.core.Is.*;
-import static org.junit.Assert.*;
-import static org.junit.matchers.JUnitMatchers.*;
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
 import static org.mockito.Mockito.*;
 
 import java.util.Arrays;
@@ -49,8 +49,7 @@ public class ModuleDependencySortTest {
 
         List<ModuleBuilder> l = ModuleDependencySort.sort(builders);
 
-        assertDependencyGraph(ModuleDependencySort.createModuleGraph(Arrays
-                .asList(builders)));
+        assertDependencyGraph(ModuleDependencySort.createModuleGraph(Arrays.asList(builders)));
 
         @SuppressWarnings("unchecked")
         Matcher<String> cOrD = anyOf(is(c.getName()), is(d.getName()));
@@ -90,9 +89,7 @@ public class ModuleDependencySortTest {
         try {
             ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
-            assertThat(
-                    e.getMessage(),
-                    containsString("Module:a with revision:default declared twice"));
+            assertThat(e.getMessage(), containsString("Module:a with revision:default declared twice"));
             throw e;
         }
     }
@@ -105,9 +102,7 @@ public class ModuleDependencySortTest {
         try {
             ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
-            assertThat(
-                    e.getMessage(),
-                    containsString("Not existing module imported:b:default by:a:default"));
+            assertThat(e.getMessage(), containsString("Not existing module imported:b:default by:a:default"));
             throw e;
         }
     }
@@ -123,8 +118,10 @@ public class ModuleDependencySortTest {
 
     @Test(expected = YangValidationException.class)
     public void testImportTwiceDifferentRevision() throws Exception {
-        Date date = new Date();
-        ModuleBuilder b2 = mockModuleBuilder("b", date);
+        Date date1 = new Date(463846463486L);
+        Date date2 = new Date(364896446683L);
+        b = mockModuleBuilder("b", date1);
+        ModuleBuilder b2 = mockModuleBuilder("b", date2);
 
         mockDependency(a, b);
         mockDependency(c, b2);
@@ -133,11 +130,9 @@ public class ModuleDependencySortTest {
         try {
             ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
-            assertThat(
-                    e.getMessage(),
-                    containsString("Module:b imported twice with different revisions:default, "
-                            + YangParserListenerImpl.simpleDateFormat
-                                    .format(date)));
+            assertThat(e.getMessage(), containsString("Module:b imported twice with different revisions:"
+                    + YangParserListenerImpl.simpleDateFormat.format(date1) + ", "
+                    + YangParserListenerImpl.simpleDateFormat.format(date2)));
             throw e;
         }
     }
@@ -161,24 +156,19 @@ public class ModuleDependencySortTest {
             ModuleDependencySort.sort(builders);
         } catch (YangValidationException e) {
             assertThat(e.getMessage(), containsString("Module:a with revision:"
-                    + YangParserListenerImpl.simpleDateFormat.format(rev)
-                    + " declared twice"));
+                    + YangParserListenerImpl.simpleDateFormat.format(rev) + " declared twice"));
             throw e;
         }
     }
 
-    private void assertDependencyGraph(
-            Map<String, Map<Date, ModuleNodeImpl>> moduleGraph) {
-        for (Entry<String, Map<Date, ModuleNodeImpl>> node : moduleGraph
-                .entrySet()) {
+    private void assertDependencyGraph(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph) {
+        for (Entry<String, Map<Date, ModuleNodeImpl>> node : moduleGraph.entrySet()) {
             String name = node.getKey();
 
             // Expects only one module revision
 
-            Set<Edge> inEdges = node.getValue().values().iterator().next()
-                    .getInEdges();
-            Set<Edge> outEdges = node.getValue().values().iterator().next()
-                    .getOutEdges();
+            Set<Edge> inEdges = node.getValue().values().iterator().next().getInEdges();
+            Set<Edge> outEdges = node.getValue().values().iterator().next().getOutEdges();
 
             if (name.equals("a")) {
                 assertEdgeCount(inEdges, 0, outEdges, 1);
@@ -190,8 +180,7 @@ public class ModuleDependencySortTest {
         }
     }
 
-    private void assertEdgeCount(Set<Edge> inEdges, int i, Set<Edge> outEdges,
-            int j) {
+    private void assertEdgeCount(Set<Edge> inEdges, int i, Set<Edge> outEdges, int j) {
         assertThat(inEdges.size(), is(i));
         assertThat(outEdges.size(), is(j));
     }
index bd8f378..47e6491 100644 (file)
@@ -135,6 +135,11 @@ module types1 {
         }
         container schemas {
         }
+        choice odl {
+            leaf id {
+                type int8;
+            }
+        }
     }
     
     container mycont {
index 495653c..c507da5 100644 (file)
@@ -32,14 +32,14 @@ module types3 {
             description "Description for augment holder";
         }
     }
-    
+
     augment "/data:interfaces/data:ifEntry" {
         when "if:ifType='ds2'";
         container augment-holder2 {
             description "Description for augment holder";
         }
     }
-    
+
     augment "/data:interfaces/data:ifEntry/t3:augment-holder/t1:schemas" {
         when "if:leafType='ds1'";
         leaf linkleaf {
@@ -51,7 +51,7 @@ module types3 {
         mnt:mountpoint point {
             mnt:target-ref target;
         }
-        
+
         description "network-description";
         reference "network-reference";
         status obsolete;
@@ -65,7 +65,7 @@ module types3 {
              storage (memory, flash or disk) that can be used to
              store syslog messages.";
     }
-    
+
     extension c-define {
         description
             "Takes as argument a name string.
@@ -73,7 +73,7 @@ module types3 {
              #define.";
         argument "name";
     }
-    
+
     notification event {
         leaf event-class {
             type string;
@@ -83,7 +83,7 @@ module types3 {
             type string;
         }
     }
-    
+
     rpc get-config {
         description
           "Retrieve all or part of a specified configuration.";
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container-leaf.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container-leaf.yang
new file mode 100644 (file)
index 0000000..9679385
--- /dev/null
@@ -0,0 +1,14 @@
+module container-leaf {
+    yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "t1";
+
+    container foo {
+        description "foo container";
+    }
+
+    leaf foo {
+        type int8;
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container-list.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container-list.yang
new file mode 100644 (file)
index 0000000..08d90af
--- /dev/null
@@ -0,0 +1,14 @@
+module container-list {
+    yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "t1";
+
+    container foo {
+        description "foo container";
+    }
+
+    list foo {
+        description "foo list";
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/container.yang
new file mode 100644 (file)
index 0000000..8e347a1
--- /dev/null
@@ -0,0 +1,14 @@
+module container {
+    yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "t1";
+
+    container foo {
+        description "foo 1";
+    }
+
+    container foo {
+        description "foo 2";
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/identity.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/identity.yang
new file mode 100644 (file)
index 0000000..f81e6e5
--- /dev/null
@@ -0,0 +1,14 @@
+module identity {
+    yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "t1";
+
+    identity id1;
+
+    identity id2;
+
+    identity id1 {
+        base id2;
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/typedef.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/negative-scenario/duplicity/typedef.yang
new file mode 100644 (file)
index 0000000..b4ec590
--- /dev/null
@@ -0,0 +1,14 @@
+module typedef {
+    yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "t1";
+
+    typedef int-ext {
+        type int32;
+    }
+
+    typedef int-ext {
+        type int16;
+    }
+
+}
index 31e0ad6..ae0f72c 100644 (file)
@@ -7,6 +7,8 @@
  */\r
 package org.opendaylight.controller.yang.model.api;\r
 \r
+import java.util.List;\r
+\r
 /**\r
  * AugmentationSchema represents augment definition. The "augment" statement\r
  * allows a module or submodule to add to the schema tree defined in an external\r
@@ -45,4 +47,9 @@ public interface AugmentationSchema extends DataNodeContainer {
      */\r
     SchemaPath getTargetPath();\r
 \r
+    /**\r
+     * @return collection of all unknown nodes defined in this augmentation\r
+     */\r
+    public List<UnknownSchemaNode> getUnknownSchemaNodes();\r
+\r
 }\r
index e8c814e..b636a32 100644 (file)
@@ -17,17 +17,23 @@ import org.opendaylight.controller.yang.common.QName;
 public interface DataNodeContainer {\r
 \r
     /**\r
-     * @return Set of all newly defined types within this DataNodeContainer\r
+     * Returns set of all newly defined types within this DataNodeContainer.\r
+     *\r
+     * @return typedef statements in lexicographical order\r
      */\r
     Set<TypeDefinition<?>> getTypeDefinitions();\r
 \r
     /**\r
-     * Set of all child nodes defined within this DataNodeContainer\r
+     * Returns set of all child nodes defined within this DataNodeContainer.\r
+     *\r
+     * @return child nodes in lexicographical order\r
      */\r
     Set<DataSchemaNode> getChildNodes();\r
 \r
     /**\r
-     * Set of all groupings defined within this DataNodeContainer\r
+     * Returns set of all groupings defined within this DataNodeContainer.\r
+     *\r
+     * @return grouping statements in lexicographical order\r
      */\r
     Set<GroupingDefinition> getGroupings();\r
 \r
index a04119b..648eacf 100644 (file)
@@ -17,6 +17,13 @@ package org.opendaylight.controller.yang.model.api;
  */\r
 public interface GroupingDefinition extends DataNodeContainer, SchemaNode {\r
 \r
+    /**\r
+     * Returns <code>true</code> if the data node was added by uses statement,\r
+     * otherwise returns <code>false</code>\r
+     *\r
+     * @return <code>true</code> if the data node was added by uses statement,\r
+     *         otherwise returns <code>false</code>\r
+     */\r
     boolean isAddedByUses();\r
 \r
 }\r