Merge "BUG-869: added proper handling of nullable parameter"
authorRobert Varga <rovarga@cisco.com>
Fri, 29 Aug 2014 20:23:26 +0000 (20:23 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 29 Aug 2014 20:23:26 +0000 (20:23 +0000)
62 files changed:
benchmarks/pom.xml [new file with mode: 0644]
benchmarks/src/main/java/org/opendaylight/yangtools/yang/data/impl/tree/BenchmarkModel.java [new file with mode: 0644]
benchmarks/src/main/java/org/opendaylight/yangtools/yang/data/impl/tree/InMemoryDataTreeBenchmark.java [new file with mode: 0644]
benchmarks/src/main/resources/odl-datastore-test.yang [new file with mode: 0644]
code-generator/binding-data-codec/pom.xml
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeSerializer.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingNormalizedNodeCodecRegistry.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataObjectCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionTypeCodec.java
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AbstractBindingRuntimeTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationSubstitutionTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CaseSubstitutionTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierSerializeDeserializeTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/InstanceIdentifierCodecImpl.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/NestedGroupingCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/nested-grouping/test.yang [new file with mode: 0644]
code-generator/binding-test-model/pom.xml [new file with mode: 0644]
code-generator/binding-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java [new file with mode: 0644]
code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang [new file with mode: 0644]
code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-binding-test.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend
code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/YangModuleInfoCompilationTest.java
code-generator/pom.xml
common/features/pom.xml
common/features/src/main/resources/features.xml
common/parent/pom.xml
pom.xml
restconf/restconf-jaxrs-api/src/main/java/org/opendaylight/yangtools/RestRestconfService.java
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/BindingReflections.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/YangInstanceIdentifier.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/spi/ContainerNode.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/spi/TreeNodeFactory.java
yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/StreamToNormalizedNodeTest.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/SchemaUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/valid/DataValidationException.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeFactory.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NormalizedNodeContainerModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/OperationWithModification.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ValueNodeModificationStrategy.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModificationMetadataTreeTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TreeNodeUtilsTest.java
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ChoiceNodeModification.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BitsType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnknownType.java [deleted file]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/GroupingUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/TypeDefinitionBuilderImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/util/AbstractDocumentedDataNodeContainer.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/ParserListenerUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/util/YangModelDependencyInfo.java

diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
new file mode 100644 (file)
index 0000000..e80bfee
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yangtools-parent</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+        <relativePath>../common/parent</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.opendaylight.yangtools</groupId>
+  <artifactId>benchmarks</artifactId>
+
+  <properties>
+    <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
+    <yang.maven.plugin.version>0.6.2-SNAPSHOT</yang.maven.plugin.version>
+    <java.source.version>1.7</java.source.version>
+    <java.target.version>1.7</java.target.version>
+    <jmh.version>0.9.7</jmh.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>yang-data-impl</artifactId>
+      <version>${yangtools.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>yang-parser-impl</artifactId>
+      <version>${yangtools.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-core</artifactId>
+      <version>${jmh.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-generator-annprocess</artifactId>
+      <version>${jmh.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>${java.source.version}</source>
+          <target>${java.source.version}</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/benchmarks/src/main/java/org/opendaylight/yangtools/yang/data/impl/tree/BenchmarkModel.java b/benchmarks/src/main/java/org/opendaylight/yangtools/yang/data/impl/tree/BenchmarkModel.java
new file mode 100644 (file)
index 0000000..e8cf728
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.yangtools.yang.data.impl.tree;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+/**
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
+public class BenchmarkModel {
+
+    public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+        "test");
+    public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+    public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+    public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
+    public static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
+    public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
+    public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
+    private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
+
+    public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
+    public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
+
+    public static final InputStream getDatastoreBenchmarkInputStream() {
+        return getInputStream(DATASTORE_TEST_YANG);
+    }
+
+    private static InputStream getInputStream(final String resourceName) {
+        return BenchmarkModel.class.getResourceAsStream(resourceName);
+    }
+
+    public static SchemaContext createTestContext() {
+        YangParserImpl parser = new YangParserImpl();
+        Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(
+            getDatastoreBenchmarkInputStream()));
+        return parser.resolveSchemaContext(modules);
+    }
+}
diff --git a/benchmarks/src/main/java/org/opendaylight/yangtools/yang/data/impl/tree/InMemoryDataTreeBenchmark.java b/benchmarks/src/main/java/org/opendaylight/yangtools/yang/data/impl/tree/InMemoryDataTreeBenchmark.java
new file mode 100644 (file)
index 0000000..306c14d
--- /dev/null
@@ -0,0 +1,194 @@
+/**
+ * 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.yangtools.yang.data.impl.tree;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.*;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * Benchmarking of InMemoryDataTree performance.
+ *
+ * JMH is used for microbenchmarking.
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ *
+ * @see <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a>
+ */
+@State(Scope.Thread)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+public class InMemoryDataTreeBenchmark {
+
+    private static final int OUTER_LIST_100K = 100000;
+    private static final int OUTER_LIST_50K = 50000;
+    private static final int OUTER_LIST_10K = 10000;
+
+    private static final YangInstanceIdentifier[] OUTER_LIST_100K_PATHS = initOuterListPaths(OUTER_LIST_100K);
+    private static final YangInstanceIdentifier[] OUTER_LIST_50K_PATHS = initOuterListPaths(OUTER_LIST_50K);
+    private static final YangInstanceIdentifier[] OUTER_LIST_10K_PATHS = initOuterListPaths(OUTER_LIST_10K);
+
+    private static YangInstanceIdentifier[] initOuterListPaths(final int outerListPathsCount) {
+        final YangInstanceIdentifier[] paths = new YangInstanceIdentifier[outerListPathsCount];
+
+        for (int outerListKey = 0; outerListKey < outerListPathsCount; ++outerListKey) {
+            paths[outerListKey] = YangInstanceIdentifier.builder(BenchmarkModel.OUTER_LIST_PATH)
+                .nodeWithKey(BenchmarkModel.OUTER_LIST_QNAME, BenchmarkModel.ID_QNAME, outerListKey)
+                .build();
+        }
+        return paths;
+    }
+
+    private static final MapNode ONE_ITEM_INNER_LIST = initInnerListItems(1);
+    private static final MapNode TWO_ITEM_INNER_LIST = initInnerListItems(2);
+    private static final MapNode TEN_ITEM_INNER_LIST = initInnerListItems(10);
+
+    private static MapNode initInnerListItems(final int count) {
+        final CollectionNodeBuilder<MapEntryNode, MapNode> mapEntryBuilder = ImmutableNodes
+            .mapNodeBuilder(BenchmarkModel.INNER_LIST_QNAME);
+
+        for (int i = 1; i <= count; ++i) {
+            mapEntryBuilder
+                .withChild(ImmutableNodes.mapEntry(BenchmarkModel.INNER_LIST_QNAME, BenchmarkModel.NAME_QNAME, i));
+        }
+
+        return mapEntryBuilder.build();
+    }
+
+    private static final NormalizedNode<?, ?>[] OUTER_LIST_ONE_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_100K, ONE_ITEM_INNER_LIST);
+    private static final NormalizedNode<?, ?>[] OUTER_LIST_TWO_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_50K, TWO_ITEM_INNER_LIST);
+    private static final NormalizedNode<?, ?>[] OUTER_LIST_TEN_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_10K, TEN_ITEM_INNER_LIST);
+
+    private static NormalizedNode<?,?>[] initOuterListItems(int outerListItemsCount, MapNode innerList) {
+        final NormalizedNode<?,?>[] outerListItems = new NormalizedNode[outerListItemsCount];
+
+        for (int i = 0; i < outerListItemsCount; ++i) {
+            int outerListKey = i;
+            outerListItems[i] = ImmutableNodes.mapEntryBuilder(BenchmarkModel.OUTER_LIST_QNAME, BenchmarkModel.ID_QNAME, outerListKey)
+                .withChild(innerList).build();
+        }
+        return outerListItems;
+    }
+
+    private SchemaContext schemaContext;
+    private DataTree datastore;
+
+    public static void main(String... args) throws IOException, RunnerException {
+        Options opt = new OptionsBuilder()
+            .include(".*" + InMemoryDataTreeBenchmark.class.getSimpleName() + ".*")
+            .forks(1)
+            .build();
+
+        new Runner(opt).run();
+    }
+
+    @Setup(Level.Trial)
+    public void setup() throws DataValidationFailedException {
+        schemaContext = BenchmarkModel.createTestContext();
+        final InMemoryDataTreeFactory factory = InMemoryDataTreeFactory.getInstance();
+        datastore = factory.create();
+        datastore.setSchemaContext(schemaContext);
+        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
+        initTestNode(snapshot);
+    }
+
+    @TearDown
+    public void tearDown() {
+        schemaContext = null;
+        datastore = null;
+    }
+
+    private void initTestNode(final DataTreeSnapshot snapshot) throws DataValidationFailedException {
+        final DataTreeModification modification = snapshot.newModification();
+        final YangInstanceIdentifier testPath = YangInstanceIdentifier.builder(BenchmarkModel.TEST_PATH)
+            .build();
+
+        modification.write(testPath, provideOuterListNode());
+        datastore.validate(modification);
+        final DataTreeCandidate candidate = datastore.prepare(modification);
+        datastore.commit(candidate);
+    }
+
+    private DataContainerChild<?, ?> provideOuterListNode() {
+        return ImmutableContainerNodeBuilder
+            .create()
+            .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(BenchmarkModel.TEST_QNAME))
+            .withChild(
+                ImmutableNodes.mapNodeBuilder(BenchmarkModel.OUTER_LIST_QNAME)
+                    .build()).build();
+    }
+
+    @Benchmark
+    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
+    public void singleNodes100KWriteBenchmark() throws Exception {
+        applyWriteSingleNode(OUTER_LIST_100K);
+    }
+
+    private void applyWriteSingleNode(final int reps) throws DataValidationFailedException {
+        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
+        final DataTreeModification modification = snapshot.newModification();
+        for (int outerListKey = 0; outerListKey < reps; ++outerListKey) {
+            modification.write(OUTER_LIST_100K_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
+        }
+        datastore.validate(modification);
+        final DataTreeCandidate candidate = datastore.prepare(modification);
+        datastore.commit(candidate);
+    }
+
+    @Benchmark
+    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
+    public void twoNodes50KWriteBenchmark() throws Exception {
+        applyWriteTwoNodes(OUTER_LIST_50K);
+    }
+
+    private void applyWriteTwoNodes(final int reps) throws DataValidationFailedException {
+        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
+        final DataTreeModification modification = snapshot.newModification();
+        for (int outerListKey = 0; outerListKey < reps; ++outerListKey) {
+            modification.write(OUTER_LIST_50K_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
+        }
+        datastore.validate(modification);
+        final DataTreeCandidate candidate = datastore.prepare(modification);
+        datastore.commit(candidate);
+    }
+
+    @Benchmark
+    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
+    public void tenNodes10KWriteBenchmark() throws Exception {
+        applyWriteTenNodes(OUTER_LIST_10K);
+    }
+
+    private void applyWriteTenNodes(final int reps) throws DataValidationFailedException {
+        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
+        final DataTreeModification modification = snapshot.newModification();
+        for (int outerListKey = 0; outerListKey < reps; ++outerListKey) {
+            modification.write(OUTER_LIST_10K_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
+        }
+        datastore.validate(modification);
+        final DataTreeCandidate candidate = datastore.prepare(modification);
+        datastore.commit(candidate);
+    }
+}
diff --git a/benchmarks/src/main/resources/odl-datastore-test.yang b/benchmarks/src/main/resources/odl-datastore-test.yang
new file mode 100644 (file)
index 0000000..730ca17
--- /dev/null
@@ -0,0 +1,42 @@
+module odl-datastore-test {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test";
+    prefix "store-test";
+    
+    revision "2014-03-13" {
+        description "Initial revision.";
+    }
+
+    container test {
+        list outer-list {
+            key id;
+            leaf id {
+                type int32;
+            }
+            choice outer-choice {
+                case one {
+                    leaf one {
+                        type string;
+                    }
+                }
+                case two-three {
+                    leaf two {
+                        type string;
+                    }
+                    leaf three {
+                        type string;
+                    }
+               }
+           }
+           list inner-list {
+                key name;
+                leaf name {
+                    type int32;
+                }
+                leaf value {
+                    type string;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
index 80cfe17b79577474ab8d120448007209aca5feef..b8bf7e11ef1f9bcb5e6dc008239c077166c63c83 100644 (file)
             <artifactId>jsr305</artifactId>
             <scope>provided</scope>
         </dependency>
-
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-test-model</artifactId>
+            <scope>test</scope>
         </dependency>
+
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
@@ -65,9 +66,9 @@
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.eclipse.xtend</groupId>
-            <artifactId>org.eclipse.xtend.lib</artifactId>
+            <dependency><groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 
index b75afa8b5d2b593521c8b4b0a77e021b5966a9c7..3e10492e10c75a4d573c5b06fe52797fee54f454 100644 (file)
@@ -10,6 +10,9 @@ package org.opendaylight.yangtools.binding.data.codec.api;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -18,7 +21,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 /**
  * Serialization service, which provides two-way serialization between
  * Java Binding Data representation and NormalizedNode representation.
- *
  */
 public interface BindingNormalizedNodeSerializer {
 
@@ -28,15 +30,16 @@ public interface BindingNormalizedNodeSerializer {
       * @param binding Binding Instance Identifier
       * @return DOM Instance Identifier
       */
-     YangInstanceIdentifier toYangInstanceIdentifier(InstanceIdentifier<?> binding);
+     YangInstanceIdentifier toYangInstanceIdentifier(@Nonnull InstanceIdentifier<?> binding);
 
      /**
       * Translates supplied YANG Instance Identifier into Binding instance identifier.
       *
       * @param dom YANG Instance Identifier
-      * @return Binding Instance Identifier
+      * @return Binding Instance Identifier, or null if the instance identifier is not
+      *         representable.
       */
-     InstanceIdentifier<?> fromYangInstanceIdentifier(YangInstanceIdentifier dom);
+     @Nullable InstanceIdentifier<?> fromYangInstanceIdentifier(@Nonnull YangInstanceIdentifier dom);
 
      /**
       * Translates supplied Binding Instance Identifier and data into NormalizedNode representation.
@@ -45,7 +48,7 @@ public interface BindingNormalizedNodeSerializer {
       * @param data Data object representing data
       * @return NormalizedNode representation
       */
-     <T extends DataObject> Entry<YangInstanceIdentifier,NormalizedNode<?,?>> toNormalizedNode(InstanceIdentifier<T> path, T data);
+     <T extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?,?>> toNormalizedNode(InstanceIdentifier<T> path, T data);
 
      /**
       * Translates supplied YANG Instance Identifier and NormalizedNode into Binding data.
@@ -54,7 +57,7 @@ public interface BindingNormalizedNodeSerializer {
       * @param data NormalizedNode representing data
       * @return DOM Instance Identifier
       */
-     Entry<InstanceIdentifier<?>,DataObject> fromNormalizedNode(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
+     @Nullable Entry<InstanceIdentifier<?>,DataObject> fromNormalizedNode(@Nonnull YangInstanceIdentifier path, NormalizedNode<?, ?> data);
 
      /**
       * Returns map view which contains translated set of entries to normalized nodes.
index 46fd45960f3572affcd4993d08d8b87e6489f9e0..6d1e31c2b47a1a3b7589ee060f89cbcd39156633 100644 (file)
@@ -18,6 +18,7 @@ import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -25,6 +26,9 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.concurrent.Callable;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.concepts.Immutable;
@@ -52,10 +56,13 @@ import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 class BindingCodecContext implements CodecContextFactory, Immutable {
-
+    private static final Logger LOG = LoggerFactory.getLogger(BindingCodecContext.class);
     private static final String GETTER_PREFIX = "get";
+
     private final SchemaRootCodecContext root;
     private final BindingRuntimeContext context;
     private final Codec<YangInstanceIdentifier, InstanceIdentifier<?>> instanceIdentifierCodec =
@@ -72,7 +79,7 @@ class BindingCodecContext implements CodecContextFactory, Immutable {
         return context;
     }
 
-    public Codec<YangInstanceIdentifier, InstanceIdentifier<?>> getInstanceIdentifierCodec() {
+    Codec<YangInstanceIdentifier, InstanceIdentifier<?>> getInstanceIdentifierCodec() {
         return instanceIdentifierCodec;
     }
 
@@ -102,14 +109,27 @@ class BindingCodecContext implements CodecContextFactory, Immutable {
         return currentNode;
     }
 
-    public NodeCodecContext getCodecContextNode(final YangInstanceIdentifier dom,
-            final List<InstanceIdentifier.PathArgument> builder) {
+    /**
+     * Multi-purpose utility function. Traverse the codec tree, looking for
+     * the appropriate codec for the specified {@link YangInstanceIdentifier}.
+     * As a side-effect, gather all traversed binding {@link InstanceIdentifier.PathArgument}s
+     * into the supplied collection.
+     *
+     * @param dom {@link YangInstanceIdentifier} which is to be translated
+     * @param bindingArguments Collection for traversed path arguments
+     * @return Codec for target node, or @null if the node does not have a
+     *         binding representation (choice, case, leaf).
+     */
+    @Nullable NodeCodecContext getCodecContextNode(final @Nonnull YangInstanceIdentifier dom,
+            final @Nonnull Collection<InstanceIdentifier.PathArgument> bindingArguments) {
         NodeCodecContext currentNode = root;
         ListNodeCodecContext currentList = null;
+
         for (YangInstanceIdentifier.PathArgument domArg : dom.getPathArguments()) {
-            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?>);
-            DataContainerCodecContext<?> previous = (DataContainerCodecContext<?>) currentNode;
-            NodeCodecContext nextNode = previous.getYangIdentifierChild(domArg);
+            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?>, "Unexpected child of non-container node %s", currentNode);
+            final DataContainerCodecContext<?> previous = (DataContainerCodecContext<?>) currentNode;
+            final NodeCodecContext nextNode = previous.getYangIdentifierChild(domArg);
+
             /*
              * List representation in YANG Instance Identifier consists of two
              * arguments: first is list as a whole, second is list as an item so
@@ -119,19 +139,13 @@ class BindingCodecContext implements CodecContextFactory, Immutable {
              * Identifier as Item or IdentifiableItem
              */
             if (currentList != null) {
+                Preconditions.checkArgument(currentList == nextNode, "List should be referenced two times in YANG Instance Identifier %s", dom);
 
-                if (currentList == nextNode) {
-
-                    // We entered list, so now we have all information to emit
-                    // list
-                    // path using second list argument.
-                    builder.add(currentList.getBindingPathArgument(domArg));
-                    currentList = null;
-                    currentNode = nextNode;
-                } else {
-                    throw new IllegalArgumentException(
-                            "List should be referenced two times in YANG Instance Identifier");
-                }
+                // We entered list, so now we have all information to emit
+                // list path using second list argument.
+                bindingArguments.add(currentList.getBindingPathArgument(domArg));
+                currentList = null;
+                currentNode = nextNode;
             } else if (nextNode instanceof ListNodeCodecContext) {
                 // We enter list, we do not update current Node yet,
                 // since we need to verify
@@ -141,24 +155,27 @@ class BindingCodecContext implements CodecContextFactory, Immutable {
                 // it is not supported by binding instance identifier.
                 currentNode = nextNode;
             } else if (nextNode instanceof DataContainerCodecContext<?>) {
-                builder.add(((DataContainerCodecContext<?>) nextNode).getBindingPathArgument(domArg));
+                bindingArguments.add(((DataContainerCodecContext<?>) nextNode).getBindingPathArgument(domArg));
                 currentNode = nextNode;
             } else if (nextNode instanceof LeafNodeCodecContext) {
-                Preconditions.checkArgument(builder == null, "Instance Identifier for leaf is not representable.");
-
+                LOG.debug("Instance identifier referencing a leaf is not representable (%s)", dom);
+                return null;
             }
         }
+
         // Algorithm ended in list as whole representation
         // we sill need to emit identifier for list
-
-        if (builder != null) {
-            Preconditions.checkArgument(!(currentNode instanceof ChoiceNodeCodecContext),
-                    "Instance Identifier for choice is not representable.");
-            Preconditions.checkArgument(!(currentNode instanceof CaseNodeCodecContext),
-                    "Instance Identifier for case is not representable.");
+        if (currentNode instanceof ChoiceNodeCodecContext) {
+            LOG.debug("Instance identifier targeting a choice is not representable (%s)", dom);
+            return null;
+        }
+        if (currentNode instanceof CaseNodeCodecContext) {
+            LOG.debug("Instance identifier targeting a case is not representable (%s)", dom);
+            return null;
         }
+
         if (currentList != null) {
-            builder.add(currentList.getBindingPathArgument(null));
+            bindingArguments.add(currentList.getBindingPathArgument(null));
             return currentList;
         }
         return currentNode;
@@ -264,12 +281,11 @@ class BindingCodecContext implements CodecContextFactory, Immutable {
         } else if (rootType instanceof InstanceIdentifierTypeDefinition) {
             return ValueTypeCodec.encapsulatedValueCodecFor(valueType, instanceIdentifierCodec);
         } else if (rootType instanceof UnionTypeDefinition) {
-            Callable<UnionTypeCodec> loader = UnionTypeCodec.loader(valueType, (UnionTypeDefinition) rootType,
-                    getInstanceIdentifierCodec(), getIdentityCodec());
+            Callable<UnionTypeCodec> loader = UnionTypeCodec.loader(valueType, (UnionTypeDefinition) rootType);
             try {
                 return loader.call();
             } catch (Exception e) {
-                throw new IllegalStateException("Unable to load codec for "+valueType,e);
+                throw new IllegalStateException("Unable to load codec for " + valueType, e);
             }
         }
         return ValueTypeCodec.getCodecFor(valueType, instantiatedType);
@@ -279,16 +295,16 @@ class BindingCodecContext implements CodecContextFactory, Immutable {
 
         @Override
         public YangInstanceIdentifier serialize(final InstanceIdentifier<?> input) {
-            List<YangInstanceIdentifier.PathArgument> domArgs = new LinkedList<>();
+            List<YangInstanceIdentifier.PathArgument> domArgs = new ArrayList<>();
             getCodecContextNode(input, domArgs);
             return YangInstanceIdentifier.create(domArgs);
         }
 
         @Override
         public InstanceIdentifier<?> deserialize(final YangInstanceIdentifier input) {
-            List<InstanceIdentifier.PathArgument> builder = new LinkedList<>();
-            getCodecContextNode(input, builder);
-            return InstanceIdentifier.create(builder);
+            final List<InstanceIdentifier.PathArgument> builder = new ArrayList<>();
+            final NodeCodecContext codec = getCodecContextNode(input, builder);
+            return codec == null ? null : InstanceIdentifier.create(builder);
         }
     }
 
index 9b772bd9dc0f344503d2e3a53c3d98bffef117a6..bfdad3efeb4cb555a22946a035ae460a8592698a 100644 (file)
@@ -16,7 +16,7 @@ import com.google.common.cache.LoadingCache;
 
 import java.io.IOException;
 import java.util.AbstractMap.SimpleEntry;
-import java.util.LinkedList;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -34,7 +34,9 @@ import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -74,23 +76,21 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
 
     @Override
     public YangInstanceIdentifier toYangInstanceIdentifier(final InstanceIdentifier<?> binding) {
-        List<YangInstanceIdentifier.PathArgument> builder = new LinkedList<>();
-        codecContext.getCodecContextNode(binding, builder);
         return codecContext.getInstanceIdentifierCodec().serialize(binding);
     }
 
     @Override
     public InstanceIdentifier<?> fromYangInstanceIdentifier(final YangInstanceIdentifier dom) {
         return codecContext.getInstanceIdentifierCodec().deserialize(dom);
-   }
+    }
 
     @Override
     public <T extends DataObject> Entry<YangInstanceIdentifier,NormalizedNode<?,?>> toNormalizedNode(final InstanceIdentifier<T> path, final T data) {
         NormalizedNodeResult result = new NormalizedNodeResult();
-        // We create dom stream writer which produces normalized nodes
+        // We create DOM stream writer which produces normalized nodes
         NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
 
-        // We create Binding Stream Writer wchich translates from Binding to Normalized Nodes
+        // We create Binding Stream Writer which translates from Binding to Normalized Nodes
         Entry<YangInstanceIdentifier, BindingStreamEventWriter> writeCtx = codecContext.newWriter(path, domWriter);
 
         // We get serializer which reads binding data and uses Binding To Normalized Node writer to write result
@@ -103,26 +103,51 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
         return new SimpleEntry<YangInstanceIdentifier,NormalizedNode<?,?>>(writeCtx.getKey(),result.getResult());
     }
 
-    private boolean isBindingRepresentable(final NormalizedNode<?, ?> data) {
-        return !(data instanceof MapNode) && !(data instanceof UnkeyedListNode) && !(data instanceof LeafSetNode) && !(data instanceof LeafNode<?>);
-    }
+    private static boolean isBindingRepresentable(final NormalizedNode<?, ?> data) {
+        if (data instanceof ChoiceNode) {
+            return false;
+        }
+        if (data instanceof LeafNode<?>) {
+            return false;
+        }
+        if (data instanceof LeafSetNode) {
+            return false;
+        }
+        if( data instanceof LeafSetEntryNode<?>) {
+            return false;
+        }
+        if (data instanceof MapNode) {
+            return false;
+        }
+        if (data instanceof UnkeyedListNode) {
+            return false;
+        }
 
+        return true;
+    }
 
     @Override
-    public Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(final YangInstanceIdentifier path,
-            final NormalizedNode<?, ?> data) {
-        List<PathArgument> builder = new LinkedList<>();
-        if(isBindingRepresentable(data)) {
-            DataObject lazyObj = (DataObject) codecContext.getCodecContextNode(path, builder).dataFromNormalizedNode(data);
-            InstanceIdentifier<?> bindingPath = InstanceIdentifier.create(builder);
-            return new SimpleEntry<InstanceIdentifier<?>, DataObject>(bindingPath,lazyObj);
+    public Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+        if (!isBindingRepresentable(data)) {
+            return null;
         }
-        return null;
+
+        final List<PathArgument> builder = new ArrayList<>();
+        final NodeCodecContext codec = codecContext.getCodecContextNode(path, builder);
+        if (codec == null) {
+            if (data != null) {
+                LOG.warn("Path {} does not have a binding equivalent, should have been caught earlier ({})", path, data.getClass());
+            }
+            return null;
+        }
+
+        final DataObject lazyObj = (DataObject) codec.dataFromNormalizedNode(data);
+        final InstanceIdentifier<?> bindingPath = InstanceIdentifier.create(builder);
+        return new SimpleEntry<InstanceIdentifier<?>, DataObject>(bindingPath, lazyObj);
     }
 
     @Override
-    public Map<InstanceIdentifier<?>, DataObject> fromNormalizedNodes(
-            final Map<YangInstanceIdentifier, NormalizedNode<?, ?>> dom) {
+    public Map<InstanceIdentifier<?>, DataObject> fromNormalizedNodes(final Map<YangInstanceIdentifier, NormalizedNode<?, ?>> dom) {
         throw new UnsupportedOperationException("Not implemented yet");
     }
 
@@ -144,8 +169,8 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
 
 
     private static class DeserializeFunction<T> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
-
         private final DataObjectCodecContext<?> ctx;
+
         public DeserializeFunction(final DataObjectCodecContext<?> ctx) {
             super();
             this.ctx = ctx;
@@ -159,8 +184,6 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
             }
             return Optional.absent();
         }
-
-
     }
 
     private class GeneratorLoader extends CacheLoader<Class<? extends DataObject>, DataObjectSerializer> {
index 700476f86bae3d79c3ed8c8d4d6e4315a7bac807..bac768703c24cab5f00e1b13014143f9b5fcf218 100644 (file)
@@ -11,8 +11,13 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
+
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -36,20 +41,50 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceNode>
         Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder = new HashMap<>();
         Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
         Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
-
+        Set<Class<?>> potentialSubstitutions = new HashSet<>();
+        // Walks all cases for supplied choice in current runtime context
         for (Class<?> caze : factory().getRuntimeContext().getCases(bindingClass())) {
+            // We try to load case using exact match thus name
+            // and original schema must equals
             DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
+            // If we have case definition, this case is instantiated
+            // at current location and thus is valid in context of parent choice
             if (cazeDef != null) {
                 byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
+                // Updates collection of case children
                 for (Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses((Class) caze)) {
                     byCaseChildClassBuilder.put(cazeChild, cazeDef);
                 }
+                // Updates collection of YANG instance identifier to case
                 for (DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
                     byYangCaseChildBuilder.put(new NodeIdentifier(cazeChild.getQName()), cazeDef);
                 }
+            } else {
+                /*
+                 * If case definition is not available, we store it for
+                 * later check if it could be used as substitution of existing one.
+                 */
+                potentialSubstitutions.add(caze);
             }
         }
 
+        Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
+        /*
+         * Walks all cases which are not directly instantiated and
+         * tries to match them to instantiated cases - represent same data as instantiated case,
+         * only case name or schema path is different. This is required due property of
+         * binding specification, that if choice is in grouping schema path location is lost,
+         * and users may use incorrect case class using copy builders.
+         */
+        for(Class<?> substitution : potentialSubstitutions) {
+            search: for(Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
+                if(BindingReflections.isSubstitutionFor(substitution, real.getKey())) {
+                    bySubstitutionBuilder.put(substitution, real.getValue());
+                    break search;
+                }
+            }
+        }
+        byClassBuilder.putAll(bySubstitutionBuilder);
         byYangCaseChild = ImmutableMap.copyOf(byYangCaseChildBuilder);
         byClass = ImmutableMap.copyOf(byClassBuilder);
         byCaseChildClass = ImmutableMap.copyOf(byCaseChildClassBuilder);
index 32fdf6d80ea597da1c4ec000bcecb880c9564564..19a9600f62705ee7a3e0878c5386a582192f4266 100644 (file)
@@ -107,6 +107,29 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
     @Override
     protected DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) {
         DataContainerCodecPrototype<?> childProto = byStreamClass.get(childClass);
+        if (childProto != null) {
+            return childProto.get();
+        }
+
+        if (Augmentation.class.isAssignableFrom(childClass))  {
+            /*
+             * It is potentially mismatched valid augmentation - we look up equivalent augmentation
+             * using reflection and walk all stream child and compare augmenations classes
+             * if they are equivalent.
+             *
+             * FIXME: Cache mapping of mismatched augmentation to real one, to speed up lookup.
+             */
+            Class<?> augTarget = BindingReflections.findAugmentationTarget((Class) childClass);
+            if ((bindingClass().equals(augTarget))) {
+                for (DataContainerCodecPrototype<?> realChild : byStreamClass.values()) {
+                    if (Augmentation.class.isAssignableFrom(realChild.getBindingClass())
+                            && BindingReflections.isSubstitutionFor(childClass,realChild.getBindingClass())) {
+                        childProto = realChild;
+                        break;
+                    }
+                }
+            }
+        }
         Preconditions.checkArgument(childProto != null, " Child %s is not valid child.",childClass);
         return childProto.get();
     }
index 6cbcc5c15680f9ef6a9247030aafa14ece6197f1..f94673c28897baa1eb67d79b12ae18efdb14a017 100644 (file)
@@ -8,13 +8,14 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.collect.ImmutableSet;
+
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.Callable;
-import org.opendaylight.yangtools.concepts.Codec;
+
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
@@ -34,12 +35,10 @@ final class UnionTypeCodec extends ReflectionBasedCodec {
         }
     }
 
-    @SuppressWarnings("rawtypes")
-    static final Callable<UnionTypeCodec> loader(final Class<?> unionCls,final UnionTypeDefinition unionType, final Codec instanceIdentifier, final Codec identity) {
+    static final Callable<UnionTypeCodec> loader(final Class<?> unionCls, final UnionTypeDefinition unionType) {
         return new Callable<UnionTypeCodec>() {
-
             @Override
-            public UnionTypeCodec call() throws Exception {
+            public UnionTypeCodec call() throws NoSuchMethodException, SecurityException {
                 Set<UnionValueOptionContext> values = new HashSet<>();
                 for(TypeDefinition<?> subtype : unionType.getTypes()) {
                     String methodName = "get" + BindingMapping.getClassName(subtype.getQName());
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AbstractBindingRuntimeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AbstractBindingRuntimeTest.java
new file mode 100644 (file)
index 0000000..a56364c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import org.junit.Before;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public abstract class AbstractBindingRuntimeTest {
+
+    private SchemaContext schemaContext;
+    private BindingRuntimeContext runtimeContext;
+
+    @Before
+    public void setup() {
+        ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
+        ctx.addModuleInfos(BindingReflections.loadModuleInfos());
+        schemaContext = ctx.tryToCreateSchemaContext().get();
+        runtimeContext = BindingRuntimeContext.create(ctx, schemaContext);
+
+    }
+
+    public SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    public BindingRuntimeContext getRuntimeContext() {
+        return runtimeContext;
+    }
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationSubstitutionTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationSubstitutionTest.java
new file mode 100644 (file)
index 0000000..62d913f
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class AugmentationSubstitutionTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+            .augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void augmentationInGroupingSubstituted() {
+        TopLevelList baRpc = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .addAugmentation(RpcComplexUsesAugment.class, new RpcComplexUsesAugmentBuilder(createComplexData()).build())
+            .build();
+        TopLevelList baTree = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .addAugmentation(TreeComplexUsesAugment.class, new TreeComplexUsesAugmentBuilder(createComplexData()).build())
+            .build();
+        NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
+        NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
+        assertEquals(domTreeEntry, domRpcEntry);
+    }
+
+    private RpcComplexUsesAugment createComplexData() {
+        return new RpcComplexUsesAugmentBuilder()
+        .setContainerWithUses(new ContainerWithUsesBuilder()
+            .setLeafFromGrouping("foo")
+        .build())
+        .setListViaUses(Collections.<ListViaUses>emptyList())
+        .build();
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CaseSubstitutionTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CaseSubstitutionTest.java
new file mode 100644 (file)
index 0000000..a01e12d
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.put.top.input.top.level.list.choice.in.list.ComplexViaUsesWithDifferentNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.top.level.list.choice.in.list.ComplexViaUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class CaseSubstitutionTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+            .augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void choiceInGroupingSubstituted() {
+        TopLevelList baRpc = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .setChoiceInList(new ComplexViaUsesWithDifferentNameBuilder(createComplexData()).build())
+            .build();
+        TopLevelList baTree = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .setChoiceInList(new ComplexViaUsesBuilder(createComplexData()).build())
+            .build();
+        NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
+        NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
+        assertEquals(domTreeEntry, domRpcEntry);
+    }
+
+    private RpcComplexUsesAugment createComplexData() {
+        return new RpcComplexUsesAugmentBuilder()
+        .setContainerWithUses(new ContainerWithUsesBuilder()
+            .setLeafFromGrouping("foo")
+        .build())
+        .setListViaUses(Collections.<ListViaUses>emptyList())
+        .build();
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierSerializeDeserializeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierSerializeDeserializeTest.java
new file mode 100644 (file)
index 0000000..67b7d1f
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import com.google.common.collect.Iterables;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class InstanceIdentifierSerializeDeserializeTest extends AbstractBindingRuntimeTest{
+    public static final String TOP_LEVEL_LIST_KEY_VALUE = "foo";
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+            .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+            BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES =
+            BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
+
+    public static final QName TOP_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+    public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
+    public static final QName TOP_LEVEL_LIST_KEY = QName.create(TOP_QNAME, "name");
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.builder().node(TOP_QNAME).build();
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_1_PATH = BI_TOP_LEVEL_LIST_PATH
+            .node(new YangInstanceIdentifier.NodeIdentifierWithPredicates(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY, TOP_LEVEL_LIST_KEY_VALUE));
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Before
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testYangIIToBindingAwareII() {
+        InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_PATH);
+        assertEquals(Top.class, instanceIdentifier.getTargetType());
+    }
+
+    @Test
+    public void testYangIIToBindingAwareIIListWildcarded() {
+        InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_PATH);
+        assertEquals(TopLevelList.class, instanceIdentifier.getTargetType());
+        assertTrue(instanceIdentifier.isWildcarded());
+    }
+
+    @Test
+    public void testYangIIToBindingAwareIIListWithKey() {
+        InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_1_PATH);
+        InstanceIdentifier.PathArgument last = Iterables.getLast(instanceIdentifier.getPathArguments());
+        assertEquals(TopLevelList.class, instanceIdentifier.getTargetType());
+        assertFalse(instanceIdentifier.isWildcarded());
+        assertTrue(last instanceof InstanceIdentifier.IdentifiableItem);
+        Identifier key = ((InstanceIdentifier.IdentifiableItem) last).getKey();
+        assertEquals(TopLevelListKey.class, key.getClass());
+        assertEquals(TOP_LEVEL_LIST_KEY_VALUE, ((TopLevelListKey)key).getName());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIContainer() {
+        YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+                InstanceIdentifier.create(Top.class).child(TopLevelList.class));
+        YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+        assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifier);
+        assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIIWildcard() {
+        YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+                InstanceIdentifier.create(Top.class).child(TopLevelList.class));
+        YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+        assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifier);
+        assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIIListWithKey() {
+        YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+                InstanceIdentifier.create(Top.class).child(TopLevelList.class, TOP_FOO_KEY));
+        YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+        assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates);
+        assertTrue(((YangInstanceIdentifier.NodeIdentifierWithPredicates) lastPathArgument).getKeyValues().containsValue(TOP_LEVEL_LIST_KEY_VALUE));
+        assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIIAugmentation() {
+        YangInstanceIdentifier.PathArgument lastArg = registry.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES).getLastPathArgument();
+        assertTrue(lastArg instanceof YangInstanceIdentifier.AugmentationIdentifier);
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIILeafOnlyAugmentation() {
+        YangInstanceIdentifier.PathArgument leafOnlyLastArg = registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
+        assertTrue(leafOnlyLastArg instanceof YangInstanceIdentifier.AugmentationIdentifier);
+        assertTrue(((YangInstanceIdentifier.AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
+    }
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierTest.java
new file mode 100644 (file)
index 0000000..e011017
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+public class InstanceIdentifierTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+            .augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testComplexAugmentationSerialization() {
+        YangInstanceIdentifier yangII = registry.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES);
+        PathArgument lastArg = yangII.getLastPathArgument();
+        assertTrue("Last argument should be AugmentationIdentifier", lastArg instanceof AugmentationIdentifier);
+        InstanceIdentifier<?> bindingII = registry.fromYangInstanceIdentifier(yangII);
+        assertEquals(BA_TREE_COMPLEX_USES, bindingII);
+    }
+
+    @Test
+    public void testLeafOnlyAugmentationSerialization() {
+        PathArgument leafOnlyLastArg = registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
+        assertTrue("Last argument should be AugmentationIdentifier", leafOnlyLastArg instanceof AugmentationIdentifier);
+        assertTrue(((AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java
new file mode 100644 (file)
index 0000000..4b08fbe
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.choice.identifier.ExtendedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.choice.identifier.extended.ExtendedIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+
+public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingRuntimeTest{
+
+    public static final String TOP_LEVEL_LIST_FOO_KEY_VALUE = "foo";
+    public static final TopLevelListKey TOP_LEVEL_LIST_FOO_KEY = new TopLevelListKey(TOP_LEVEL_LIST_FOO_KEY_VALUE);
+
+    public static final QName TOP_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+    public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
+    public static final QName TOP_LEVEL_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
+    public static final QName TOP_LEVEL_LEAF_LIST_QNAME = QName.create(TOP_QNAME, "top-level-leaf-list");
+    public static final QName NESTED_LIST_QNAME = QName.create(TOP_QNAME, "nested-list");
+    public static final QName NESTED_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
+    public static final QName CHOICE_CONTAINER_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "choice-container");
+    public static final QName CHOICE_IDENTIFIER_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "identifier");
+    public static final QName CHOICE_IDENTIFIER_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "id");
+    public static final QName SIMPLE_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "simple-id");
+    public static final QName EXTENDED_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "extended-id");
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+            .builder(Top.class).child(TopLevelList.class, TOP_LEVEL_LIST_FOO_KEY).toInstance();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+            BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES =
+            BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
+
+    public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.of(TOP_QNAME);
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_FOO_PATH = BI_TOP_LEVEL_LIST_PATH
+            .node(new YangInstanceIdentifier.NodeIdentifierWithPredicates(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE));
+    public static final YangInstanceIdentifier BI_CHOICE_CONTAINER_PATH = YangInstanceIdentifier.of(CHOICE_CONTAINER_QNAME);
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Before
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void containerToNormalized() {
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top());
+        ContainerNode topNormalized = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(mapNodeBuilder(TOP_LEVEL_LIST_QNAME).build()).build();
+        assertEquals(topNormalized, entry.getValue());
+    }
+
+    @Test
+    public void containerFromNormalized() {
+        ContainerNode topNormalized = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(mapNodeBuilder(TOP_LEVEL_LIST_QNAME).build()).build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_PATH, topNormalized);
+        assertEquals(top(), entry.getValue());
+    }
+
+    @Test
+    public void listWithKeysToNormalized() {
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(BA_TOP_LEVEL_LIST, topLevelList(TOP_LEVEL_LIST_FOO_KEY));
+        MapEntryNode topLevelListNormalized = ImmutableMapEntryNodeBuilder.create()
+                .withNodeIdentifier(
+                        new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .build();
+        assertEquals(topLevelListNormalized, entry.getValue());
+    }
+
+    @Test
+    public void listWithKeysFromNormalized() {
+        MapEntryNode topLevelListNormalized = ImmutableMapEntryNodeBuilder.create()
+                .withNodeIdentifier(
+                        new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry =
+                registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH, topLevelListNormalized);
+        assertEquals(topLevelList(TOP_LEVEL_LIST_FOO_KEY), entry.getValue());
+    }
+
+    @Test
+    public void leafOnlyAugmentationToNormalized() {
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(BA_TREE_LEAF_ONLY, new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build());
+        Set<QName> augmentationChildren = new HashSet<>();
+        augmentationChildren.add(SIMPLE_VALUE_QNAME);
+        AugmentationNode augmentationNode = ImmutableAugmentationNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren))
+                .withChild(leafNode(SIMPLE_VALUE_QNAME, "simpleValue"))
+                .build();
+        assertEquals(augmentationNode, entry.getValue());
+    }
+
+    @Test
+    public void leafOnlyAugmentationFromNormalized() {
+        Set<QName> augmentationChildren = new HashSet<>();
+        augmentationChildren.add(SIMPLE_VALUE_QNAME);
+        AugmentationNode augmentationNode = ImmutableAugmentationNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren))
+                .withChild(leafNode(SIMPLE_VALUE_QNAME, "simpleValue"))
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH.node(
+                        new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren)), augmentationNode);
+        assertEquals(new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build(), entry.getValue());
+    }
+
+    @Test
+    public void leafListToNormalized() {
+        List<String> topLevelLeafList = new ArrayList<>();
+        topLevelLeafList.add("foo");
+        Top top = new TopBuilder().setTopLevelLeafList(topLevelLeafList).build();
+
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top);
+        ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(ImmutableLeafSetNodeBuilder.create()
+                        .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
+                        .withChild(
+                                ImmutableLeafSetEntryNodeBuilder.create()
+                                        .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue(TOP_LEVEL_LEAF_LIST_QNAME, "foo"))
+                                        .withValue("foo")
+                                        .build())
+                        .build())
+                .build();
+        assertEquals(containerNode, entry.getValue());
+    }
+
+    @Test
+    public void leafListFromNormalized() {
+        ContainerNode topWithLeafList = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
+                        .withChild(ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+                                new YangInstanceIdentifier.NodeWithValue(TOP_LEVEL_LEAF_LIST_QNAME, "foo")).withValue("foo").build()).build())
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_PATH, topWithLeafList);
+        List<String> topLevelLeafList = new ArrayList<>();
+        topLevelLeafList.add("foo");
+        Top top = new TopBuilder().setTopLevelLeafList(topLevelLeafList).build();
+        assertEquals(top, entry.getValue());
+    }
+
+    @Test
+    public void choiceToNormalized() {
+        ChoiceContainer choiceContainerBA = new ChoiceContainerBuilder().setIdentifier(new ExtendedBuilder().setExtendedId(
+                new ExtendedIdBuilder().setId("identifier_value").build()).build()).build();
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(InstanceIdentifier.create(ChoiceContainer.class), choiceContainerBA);
+        ContainerNode choiceContainer = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_CONTAINER_QNAME))
+                .withChild(ImmutableChoiceNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
+                        .withChild(ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(EXTENDED_ID_QNAME))
+                                .withChild(leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value")).build()).build())
+                .build();
+        assertEquals(choiceContainer, entry.getValue());
+    }
+
+    @Test
+    public void choiceFromNormalized() {
+        ContainerNode choiceContainerBI = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_CONTAINER_QNAME))
+                .withChild(ImmutableChoiceNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
+                        .withChild(ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(EXTENDED_ID_QNAME))
+                                .withChild(leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value")).build()).build())
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_CHOICE_CONTAINER_PATH, choiceContainerBI);
+        ChoiceContainer choiceContainerBA = new ChoiceContainerBuilder().setIdentifier(new ExtendedBuilder().setExtendedId(
+                new ExtendedIdBuilder().setId("identifier_value").build()).build()).build();
+        assertEquals(choiceContainerBA, entry.getValue());
+    }
+
+    @Test
+    public void orderedLisToNormalized() {
+        InstanceIdentifier<TopLevelList> ii = BA_TOP_LEVEL_LIST;
+        List<NestedList> nestedLists = new ArrayList<>();
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("foo")).build());
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("bar")).build());
+        TopLevelList topLevelList = new TopLevelListBuilder().setKey(TOP_LEVEL_LIST_FOO_KEY).setNestedList(nestedLists).build();
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = registry.toNormalizedNode(ii, topLevelList);
+        MapEntryNode foo = mapEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(
+                        ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar")).build()).build();
+        assertEquals(foo, entry.getValue());
+    }
+
+    @Test
+    public void orderedLisFromNormalized() {
+        MapEntryNode foo = mapEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(
+                        ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar")).build()).build();
+        InstanceIdentifier<TopLevelList> ii = BA_TOP_LEVEL_LIST;
+
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH, foo);
+        List<NestedList> nestedLists = new ArrayList<>();
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("foo")).build());
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("bar")).build());
+        TopLevelList topLevelList = new TopLevelListBuilder().setKey(TOP_LEVEL_LIST_FOO_KEY).setNestedList(nestedLists).build();
+        assertEquals(topLevelList, entry.getValue());
+    }
+}
index befe3e88e02c494e48b287d8089cf2f05eb8fd08..af67e659b3405b72f101a35cf57785398b64e495 100644 (file)
@@ -30,7 +30,6 @@ import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findP
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -39,7 +38,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
@@ -310,7 +308,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             return null;
         }
         final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
-        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf);
+        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module);
         genType.addComment(node.getDescription());
         genType.setDescription(createDescription(node, genType.getFullyQualifiedName()));
         genType.setModuleName(module.getName());
@@ -556,7 +554,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 processUsesAugments(notification, module);
 
                 final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName,
-                        notification, BindingTypes.DATA_OBJECT);
+                        notification, BindingTypes.DATA_OBJECT, module);
                 notificationInterface.addImplementsType(NOTIFICATION);
                 genCtx.get(module).addChildNodeType(notification, notificationInterface);
 
@@ -704,7 +702,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      */
     private void groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module module) {
         final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath());
-        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping);
+        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping, module);
         genCtx.get(module).addGroupingType(grouping.getPath(), genType);
         resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.getChildNodes());
         groupingsToGenTypes(module, grouping.getGroupings());
@@ -1204,7 +1202,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         for (ChoiceCaseNode caseNode : caseNodes) {
             if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
-                final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
+                final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
                 caseTypeBuilder.addImplementsType(refChoiceType);
                 genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
                 genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
@@ -1283,7 +1281,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         for (DataSchemaNode caseNode : augmentedNodes) {
             if (caseNode != null) {
                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
-                final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
+                final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
                 caseTypeBuilder.addImplementsType(targetType);
 
                 SchemaNode parent = null;
@@ -1600,8 +1598,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return returnType.toInstance();
     }
 
-    private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {
-        return addDefaultInterfaceDefinition(packageName, schemaNode, null);
+    private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
+            final Module module) {
+        return addDefaultInterfaceDefinition(packageName, schemaNode, null, module);
     }
 
     /**
@@ -1628,7 +1627,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * @return generated type builder <code>schemaNode</code>
      */
     private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
-            final Type parent) {
+            final Type parent, final Module module) {
         final GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, "");
         if (parent == null) {
             it.addImplementsType(DATA_OBJECT);
@@ -1640,6 +1639,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }
 
         if (schemaNode instanceof DataNodeContainer) {
+            groupingsToGenTypes(module, ((DataNodeContainer) schemaNode).getGroupings());
             addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it);
         }
 
index 7c8586ed8f5af71ceab4b88bda76f082c0f4fd94..e532be5b9e83689280fbb2469de874174647b45b 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
 import com.google.common.collect.ImmutableList;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -19,7 +18,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
-
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -29,10 +27,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
@@ -60,9 +58,9 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
     public InstanceIdentifier<? extends Object> deserialize(
             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier input) {
         Class<?> baType = null;
-        List<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument> biArgs = input.getPath();
-        List<QName> scannedPath = new ArrayList<>(biArgs.size());
-        List<InstanceIdentifier.PathArgument> baArgs = new ArrayList<InstanceIdentifier.PathArgument>(biArgs.size());
+        Iterable<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument> biArgs = input.getPathArguments();
+        List<QName> scannedPath = new ArrayList<>();
+        List<InstanceIdentifier.PathArgument> baArgs = new ArrayList<InstanceIdentifier.PathArgument>();
         for (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument biArg : biArgs) {
 
             scannedPath.add(biArg.getNodeType());
index 92047d1f22c6547d284c8a29453eb5274a9408ab..f72856e1c11b540c2c6d855ef26b0ab7455a209e 100644 (file)
@@ -15,7 +15,6 @@ import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
-
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -30,7 +29,6 @@ import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
 import org.opendaylight.yangtools.binding.generator.util.Types;
 import org.opendaylight.yangtools.concepts.Delegator;
@@ -268,7 +266,7 @@ class LazyGeneratedCodecRegistry implements CodecRegistry, SchemaContextListener
         while (iterator.hasNext()) {
             QName arg = iterator.next();
             DataSchemaNode currentNode = previous.getDataChildByName(arg);
-            if (currentNode == null && previous instanceof DataNodeContainer) {
+            if (currentNode == null) {
                 currentNode = searchInChoices(previous, arg);
             }
             if (currentNode instanceof DataNodeContainer) {
@@ -852,7 +850,7 @@ class LazyGeneratedCodecRegistry implements CodecRegistry, SchemaContextListener
             if (!parentQName.equals(choiceName)) {
                 // This item is instantiation of choice via uses in other YANG
                 // module
-                if (choiceName.getNamespace().equals(schema.getQName())) {
+                if (choiceName.getNamespace().equals(schema.getQName().getNamespace())) {
                     // Original definition of grouping is in same namespace
                     // as original definition of case
                     // so for sure case is introduced via instantiation of
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/NestedGroupingCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/NestedGroupingCompilationTest.java
new file mode 100644 (file)
index 0000000..62190fc
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.yangtools.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_TEST;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test correct code generation.
+ *
+ */
+public class NestedGroupingCompilationTest extends BaseCompilationTest {
+
+    @Test
+    public void testListGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "nested-grouping");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "nested-grouping");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/nested-grouping", sourcesOutputDir);
+
+        // Test if all sources are generated
+        File parent = new File(sourcesOutputDir, NS_TEST);
+        File foo = new File(parent, "Foo.java");
+        File fooBuilder = new File(parent, "FooBuilder.java");
+        File testData = new File(parent, "TestData.java");
+        File fooDir = new File(parent, "foo");
+        assertTrue(foo.exists());
+        assertTrue(fooBuilder.exists());
+        assertTrue(testData.exists());
+        assertTrue(fooDir.exists());
+        assertFilesCount(parent, 4);
+
+        parent = new File(parent, "foo");
+        File bar = new File(parent, "Bar.java");
+        assertTrue(bar.exists());
+        assertFilesCount(parent, 1);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        Class<?> fooClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Foo", true, loader);
+        Class<?> barClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.foo.Bar", true, loader);
+
+        // Test generated 'foo'
+        assertTrue(fooClass.isInterface());
+        assertImplementsIfc(fooClass, barClass);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+        final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+        generator.generateToFile(sourcesOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/nested-grouping/test.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/nested-grouping/test.yang
new file mode 100644 (file)
index 0000000..94cf5e1
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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
+ */
+module test {
+    yang-version 1;
+    namespace "urn:opendaylight:test";
+    prefix "t";
+
+    revision "2013-10-08" {
+    }
+
+    container foo {
+        grouping bar {
+            leaf id {
+                type int32;
+            }
+        }
+        uses bar;
+    }
+
+}
diff --git a/code-generator/binding-test-model/pom.xml b/code-generator/binding-test-model/pom.xml
new file mode 100644 (file)
index 0000000..106c904
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>binding-generator</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>yang-ext</artifactId>
+        </dependency>
+    </dependencies>
+
+    <artifactId>binding-test-model</artifactId>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>
+                                        target/generated-sources/sal
+                                    </outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <tag>HEAD</tag>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+</project>
diff --git a/code-generator/binding-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java b/code-generator/binding-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java
new file mode 100644 (file)
index 0000000..0d3e7e8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014 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.md.sal.test.model.util;
+
+import com.google.common.collect.ImmutableList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListKey;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Arrays;
+
+public class ListsBindingUtils {
+
+    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+
+    private ListsBindingUtils() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    public static final TopLevelListKey TOP_BAR_KEY = new TopLevelListKey("bar");
+    public static final ListViaUsesKey USES_ONE_KEY = new ListViaUsesKey("one");
+    public static final ListViaUsesKey USES_TWO_KEY = new ListViaUsesKey("two");
+
+
+    public static InstanceIdentifier<TopLevelList> path(final TopLevelListKey key) {
+        return TOP_PATH.child(TopLevelList.class, key);
+    }
+
+    public static InstanceIdentifier<NestedList> path(final TopLevelListKey top,final NestedListKey nested) {
+        return path(top).child(NestedList.class, nested);
+    }
+
+    public static InstanceIdentifier<ListViaUses> path(final TopLevelListKey top,final ListViaUsesKey uses) {
+        return path(top).augmentation(TreeComplexUsesAugment.class).child(ListViaUses.class, uses);
+    }
+
+    public static <T extends DataObject & Augmentation<TopLevelList>> InstanceIdentifier<T> path(final TopLevelListKey key, final Class<T> augmentation) {
+        return path(key).augmentation(augmentation);
+    }
+
+    public static Top top(final TopLevelList... listItems) {
+        return new TopBuilder().setTopLevelList(Arrays.asList(listItems)).build();
+    }
+
+    public static TopLevelList topLevelList(final TopLevelListKey key) {
+        return new TopLevelListBuilder().setKey(key).build();
+    }
+
+    public static TopLevelList topLevelList(final TopLevelListKey key, final TreeComplexUsesAugment augment) {
+        TopLevelListBuilder builder = new TopLevelListBuilder().setKey(key);
+        builder.addAugmentation(TreeComplexUsesAugment.class, augment);
+        return builder.build();
+    }
+
+    public static TreeComplexUsesAugment complexUsesAugment(final ListViaUsesKey... keys) {
+        ImmutableList.Builder<ListViaUses> listViaUses = ImmutableList.<ListViaUses> builder();
+        for (ListViaUsesKey key : keys) {
+            listViaUses.add(new ListViaUsesBuilder().setKey(key).build());
+        }
+        return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
+    }
+
+    public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+        return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang
new file mode 100644 (file)
index 0000000..6d155be
--- /dev/null
@@ -0,0 +1,111 @@
+module opendaylight-yangtools-augment-test {
+
+    namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:augment";
+    prefix aug-test;
+
+    import opendaylight-yangtools-binding-test {
+        prefix test;
+    }
+    import yang-ext {
+        prefix ext;
+    }
+
+    description
+        "This module contains a collection of YANG augmentations used for
+        some test cases.";
+
+    revision 2014-07-09 {
+        description
+        "Test model for testing data broker with nested lists.";
+    }
+
+    grouping leaf-from-grouping {
+        leaf leaf-from-grouping {
+            type string;
+        }
+    }
+
+    grouping complex-from-grouping {
+        container container-with-uses {
+            uses leaf-from-grouping;
+        }
+        list list-via-uses {
+            key "name";
+            leaf name {
+                type string;
+            }
+        }
+    
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-leaf-only-uses-augment;
+        uses leaf-from-grouping;
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-leaf-only-uses-augment;
+        uses leaf-from-grouping;
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-complex-uses-augment;
+        uses complex-from-grouping;
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-complex-uses-augment;
+        uses complex-from-grouping;
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-leaf-only-augment;
+
+        leaf simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-second-leaf-only-augment;
+
+        leaf second-simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-leaf-only-augment;
+
+        leaf simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-second-leaf-only-augment;
+
+        leaf second-simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:top/test:top-level-list/test:choice-in-list" {
+        case simple-via-uses {
+            uses leaf-from-grouping;
+        }
+        case complex-via-uses {
+            uses complex-from-grouping;
+        }
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list/test:choice-in-list" {
+        case simple-via-uses {
+            uses leaf-from-grouping;
+        }
+        case complex-via-uses-with-different-name {
+            uses complex-from-grouping;
+        }
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-binding-test.yang b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-binding-test.yang
new file mode 100644 (file)
index 0000000..c5e5ce2
--- /dev/null
@@ -0,0 +1,86 @@
+module opendaylight-yangtools-binding-test {
+
+    namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:binding";
+    prefix list-test;
+
+
+    description
+        "This module contains a collection of YANG definitions used for
+        some test cases.";
+
+    revision 2014-07-01 {
+        description
+        "Test model for testing data broker with nested lists.";
+    }
+
+    grouping two-level-list {
+        list top-level-list {
+            description
+                "Top Level List";
+            key "name";
+            leaf name {
+                type string;
+            }
+
+            choice choice-in-list {
+                case simple-case {
+                    leaf simple {
+                        type string;
+                    }
+                }
+            }
+
+            list nested-list {
+                key "name";
+                leaf name {
+                    type string;
+                }
+                leaf type {
+                    type string;
+                    mandatory true;
+                    description
+                        "Mandatory type of list.";
+                }
+                ordered-by user;
+                description
+                    "A list of service functions that compose the service chain";
+            }
+        }
+        leaf-list top-level-leaf-list {
+            type string;
+        }
+    }
+
+    grouping choice {
+        choice identifier {
+            case simple {
+                container simple-id {
+                    leaf id {
+                        type int32;
+                    }
+                }
+            }
+            case extended {
+                container extended-id {
+                    leaf id {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    container top {
+        uses two-level-list;
+    }
+
+    container choice-container {
+        uses choice;
+    }
+
+    rpc put-top {
+        input {
+            uses two-level-list;
+        }
+    }
+}
index cf23c844de29cfe5e5ea5d2ab36905f8a7dfb3ce..f1864ab1b7e5af44810b1dd9a07d5d1e81e52d6a 100644 (file)
@@ -14,6 +14,9 @@ import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findD
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.BaseEncoding;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -31,7 +34,6 @@ import java.util.Set;
 import java.util.TreeMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
 import org.apache.commons.lang3.StringEscapeUtils;
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
@@ -90,10 +92,6 @@ import org.opendaylight.yangtools.yang.model.util.Uint64;
 import org.opendaylight.yangtools.yang.model.util.Uint8;
 import org.opendaylight.yangtools.yang.model.util.UnionType;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import com.google.common.io.BaseEncoding;
-
 public final class TypeProviderImpl implements TypeProvider {
     private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
 
@@ -810,11 +808,13 @@ public final class TypeProviderImpl implements TypeProvider {
         final List<GeneratedTOBuilder> genTOBuilders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
                 typedef, typeDefName, parentNode);
         GeneratedTOBuilder resultTOBuilder = null;
-        if (!genTOBuilders.isEmpty()) {
-            resultTOBuilder = genTOBuilders.remove(0);
-            for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
-                resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
-            }
+        if (genTOBuilders.isEmpty()) {
+            throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typedef);
+        }
+
+        resultTOBuilder = genTOBuilders.remove(0);
+        for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
+            resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
         }
 
         final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value");
@@ -1062,7 +1062,7 @@ public final class TypeProviderImpl implements TypeProvider {
         final String packageName = packageNameForGeneratedType(basePackageName, typedef.getPath());
         final String typeDefTOName = typedef.getQName().getLocalName();
 
-        if ((packageName != null) && (typedef != null) && (typeDefTOName != null)) {
+        if ((packageName != null) && (typeDefTOName != null)) {
             final String genTOName = BindingMapping.getClassName(typeDefTOName);
             final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTOName);
 
@@ -1300,9 +1300,8 @@ public final class TypeProviderImpl implements TypeProvider {
             typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
         }
         // keys are in ascending order
-        Set<Integer> depths = typeDefinitionsDepths.keySet();
-        for (Integer depth : depths) {
-            sortedTypeDefinition.addAll(typeDefinitionsDepths.get(depth));
+        for (Map.Entry<Integer, List<TypeDefinition<?>>> entry : typeDefinitionsDepths.entrySet()) {
+            sortedTypeDefinition.addAll(entry.getValue());
         }
 
         return sortedTypeDefinition;
index d8c49592965f0cb1f62654aed4bff87894c0269e..f40cbcaa3dff249ad6cc8443028d380853fa8485 100644 (file)
@@ -975,9 +975,9 @@ class GeneratorImpl {
             </ul>
             Â«ENDIF»
 
-            Â«IF !path.path.empty»
+            Â«IF path.pathArguments.iterator.hasNext»
             <h3>XML example</h3>
-            Â«nodes.xmlExample(path.path.last.nodeType,path)»
+            Â«nodes.xmlExample(path.pathArguments.last.nodeType,path)»
             </h3>
             Â«ENDIF»
             Â«FOR childNode : containers»
@@ -1045,8 +1045,8 @@ class GeneratorImpl {
 
 
     def header(int level,YangInstanceIdentifier name) '''
-        <h«level» id="«FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">
-            Â«FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»
+        <h«level» id="«FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">
+            Â«FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»
         </h«level»>
     '''
 
@@ -1152,7 +1152,7 @@ class GeneratorImpl {
     }
 
     def CharSequence localLink(YangInstanceIdentifier identifier, CharSequence text) '''
-        <a href="#«FOR cmp : identifier.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
+        <a href="#«FOR cmp : identifier.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
     '''
 
 
@@ -1181,7 +1181,7 @@ class GeneratorImpl {
         append(currentModule.name)
         append(":")
         var previous = false;
-        for(arg : identifier.path) {
+        for(arg : identifier.pathArguments) {
             if(previous) append("/")
             append(arg.nodeType.localName);
             previous = true;
index 1208f190f376519a18f54fd406c469c9b94f3671..1a1052baa14838f604e6d1d6a068d785911ea126 100644 (file)
@@ -82,13 +82,9 @@ public class YangModuleInfoCompilationTest {
         testCompilation(sourcesOutputDir, compiledOutputDir);
 
         // Create URLClassLoader
-        File[] roots = File.listRoots();
-        URL[] urls = new URL[roots.length + 1];
-        for (int i = 0; i < roots.length; i++) {
-            urls[i] = roots[i].toURI().toURL();
-
-        }
-        urls[roots.length] = compiledOutputDir.toURI().toURL();
+        URL[] urls = new URL[2];
+        urls[0] = compiledOutputDir.toURI().toURL();
+        urls[1] = new File(System.getProperty("user.dir")).toURI().toURL();
         ClassLoader loader = new URLClassLoader(urls);
 
         // Load class
@@ -176,13 +172,16 @@ public class YangModuleInfoCompilationTest {
     private static List<File> getSourceFiles(String path) throws Exception {
         final URI resPath = YangModuleInfoCompilationTest.class.getResource(path).toURI();
         final File sourcesDir = new File(resPath);
+        final URI currentDir = new File(System.getProperty("user.dir")).toURI();
         if (sourcesDir.exists()) {
             final List<File> sourceFiles = new ArrayList<>();
             final File[] fileArray = sourcesDir.listFiles();
             if (fileArray == null) {
                 throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
             }
-            sourceFiles.addAll(Arrays.asList(fileArray));
+            for (File sourceFile : fileArray) {
+                sourceFiles.add(new File(currentDir.relativize(sourceFile.toURI()).toString()));
+            }
             return sourceFiles;
         } else {
             throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
index 4cdf7c23c78e0349ef6e162d16a98cf76dd548a1..fc239681b50fbf6de3dfabd9397fd4c634b01481 100644 (file)
@@ -30,6 +30,7 @@
         <module>binding-java-api-generator</module>
         <module>binding-type-provider</module>
         <module>maven-sal-api-gen-plugin</module>
+        <module>binding-test-model</module>
         <module>binding-data-codec</module>
     </modules>
 
             </dependency>
 
             <!-- Local Dependencies -->
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>binding-test-model</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>binding-model-api</artifactId>
index 4fe4b110c25aee5520cad789b7cfb49dd2634009..a2eed6db1d2eedad3db89901a3ee9c99e7a7b833 100644 (file)
        <groupId>org.opendaylight.yangtools.model</groupId>
        <artifactId>ietf-yang-types</artifactId>
      </dependency>
+     <dependency>
+       <groupId>org.opendaylight.yangtools.model</groupId>
+       <artifactId>ietf-yang-types-20130715</artifactId>
+     </dependency>
      <dependency>
        <groupId>org.opendaylight.yangtools.model</groupId>
        <artifactId>yang-ext</artifactId>
        <groupId>org.opendaylight.yangtools</groupId>
        <artifactId>restconf-common</artifactId>
      </dependency>
+     <dependency>
+       <groupId>org.opendaylight.yangtools</groupId>
+       <artifactId>binding-data-codec</artifactId>
+     </dependency>
      <dependency>
        <groupId>org.opendaylight.yangtools.thirdparty</groupId>
        <artifactId>xtend-lib-osgi</artifactId>
index 58b3ab177983771a58cd2878e76ca9b56dc175d8..7f94b50c59733ca7adf0d4e038200af62a06f9d9 100644 (file)
@@ -23,6 +23,7 @@
         <feature version='${project.version}'>odl-yangtools-binding</feature>
         <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf.inet.types.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf.yang.types.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types-20130715/${ietf.yang.types.20130715.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools.model/yang-ext/${yang.ext.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools.model/opendaylight-l2-types/${opendaylight.l2.types.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools.model/ietf-topology/${ietf.topology.version}</bundle>
index ec653a59b435d40429c99f1a847300f729591919..57af4a168e96730fa487c62ef7def95275a2446b 100644 (file)
@@ -35,6 +35,7 @@
         <ietf.topology.version>2013.10.21.2-SNAPSHOT</ietf.topology.version>
         <ietf.inet.types.version>2010.09.24.4-SNAPSHOT</ietf.inet.types.version>
         <ietf.yang.types.version>2010.09.24.4-SNAPSHOT</ietf.yang.types.version>
+        <ietf.yang.types.20130715.version>2013.07.15.1-SNAPSHOT</ietf.yang.types.20130715.version>
         <ietf.restconf.version>2013.10.19.1-SNAPSHOT</ietf.restconf.version>
         <karaf.version>3.0.1</karaf.version>
         <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
                 <artifactId>ietf-yang-types</artifactId>
                 <version>2010.09.24.4-SNAPSHOT</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools.model</groupId>
+                <artifactId>ietf-yang-types-20130715</artifactId>
+                <version>2013.07.15.1-SNAPSHOT</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.yangtools.model</groupId>
                 <artifactId>ietf-restconf</artifactId>
               <artifactId>yang-data-operations</artifactId>
               <version>${project.version}</version>
             </dependency>
+            <dependency>
+              <groupId>org.opendaylight.yangtools</groupId>
+              <artifactId>binding-data-codec</artifactId>
+              <version>${project.version}</version>
+            </dependency>
             <dependency>
               <groupId>org.opendaylight.yangtools</groupId>
               <artifactId>features-test</artifactId>
diff --git a/pom.xml b/pom.xml
index 90a3e97e4d01e74a1229dea69696d54e90a0b03e..7ad393fbc312e5dcc184b7c9d8f7f77f9b17a0c3 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,8 @@
         <module>restconf</module>
         <module>websocket</module>
         <module>yang</module>
-        <!-- module>third-party</module -->
+        <module>benchmarks</module>
+      <!-- module>third-party</module -->
     </modules>
 
     <build>
index 11083c31299cc07d27baca8fd4ed8e694ad3481f..a3c7146046a55a951cfcb99ab1de388632f9d13e 100644 (file)
@@ -25,6 +25,8 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 @Path("restconf")
 public interface RestRestconfService {
 
+    public static final String IDENTIFIER = "identifier";
+    public static final String INPUT = "input";
     public static final String XML = "+xml";
     public static final String JSON = "+json";
 
@@ -45,48 +47,48 @@ public interface RestRestconfService {
     @Consumes({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
             Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
             MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public String invokeRpc(@PathParam("identifier") String identifier, @QueryParam("input") CompositeNode payload);
+    public String invokeRpc(@PathParam(IDENTIFIER) String identifier, @QueryParam(INPUT) CompositeNode payload);
 
     @POST
     @Path("/operations/{identifier}")
     @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
             Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
             MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public String invokeRpc(@PathParam("identifier") String identifier);
+    public String invokeRpc(@PathParam(IDENTIFIER) String identifier);
 
     @GET
     @Path("/config/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
             MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public String readConfigurationData(@PathParam("identifier") String identifier);
+    public String readConfigurationData(@PathParam(IDENTIFIER) String identifier);
 
     @GET
     @Path("/operational/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
             MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public String readOperationalData(@PathParam("identifier") String identifier);
+    public String readOperationalData(@PathParam(IDENTIFIER) String identifier);
 
     @PUT
     @Path("/config/{identifier:.+}")
     @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
             MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response updateConfigurationData(@PathParam("identifier") String identifier,@QueryParam("input") CompositeNode payload);
+    public Response updateConfigurationData(@PathParam(IDENTIFIER) String identifier,@QueryParam(INPUT) CompositeNode payload);
 
     @POST
     @Path("/config/{identifier:.+}")
     @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
             MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response createConfigurationData(@PathParam("identifier") String identifier, @QueryParam("input") CompositeNode payload);
+    public Response createConfigurationData(@PathParam(IDENTIFIER) String identifier, @QueryParam(INPUT) CompositeNode payload);
 
     @POST
     @Path("/config")
     @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
             MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response createConfigurationData( @QueryParam("input") CompositeNode payload);
+    public Response createConfigurationData( @QueryParam(INPUT) CompositeNode payload);
 
     @DELETE
     @Path("/config/{identifier:.+}")
-    public Response deleteConfigurationData(@PathParam("identifier") String identifier);
+    public Response deleteConfigurationData(@PathParam(IDENTIFIER) String identifier);
 
 
 }
index f9f4c5c7b547774e3e4567a326d2192541d7fbc1..bc7474a9f2cb765796063f07e8c9cd65dc2b5e96 100644 (file)
@@ -16,12 +16,15 @@ import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.collect.Sets;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -581,4 +584,51 @@ public class BindingReflections {
     public static Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Augmentable<?> input) {
         return AugmentationFieldGetter.getGetter(input.getClass()).getAugmentations(input);
     }
+
+    /**
+     *
+     * Determines if two augmentation classes or case classes represents same data.
+     * <p>
+     * Two augmentations or cases could be substituted only if and if:
+     * <ul>
+     * <li>Both implements same interfaces</li>
+     * <li>Both have same children</li>
+     * <li>If augmentations: Both have same augmentation target class. Target class was generated for data node in grouping.</li>
+     * <li>If cases: Both are from same choice. Choice class was generated for data node in grouping.</li>
+     * </ul>
+     * <p>
+     * <b>Explanation:</b> Binding Specification reuses classes generated for groupings as part of normal data tree,
+     * this classes from grouping could be used at various locations and user may not be aware of it
+     * and may use incorrect case or augmentation in particular subtree (via copy constructors, etc).
+     *
+     * @param potential Class which is potential substition
+     * @param target Class which should be used at particular subtree
+     * @return true if and only if classes represents same data.
+     */
+    @SuppressWarnings({"rawtypes","unchecked"})
+    public static boolean isSubstitutionFor(Class potential, Class target) {
+        HashSet<Class> subImplemented = Sets.newHashSet(potential.getInterfaces());
+        HashSet<Class> targetImplemented = Sets.newHashSet(target.getInterfaces());
+        if(!subImplemented.equals(targetImplemented)) {
+            return false;
+        }
+        if(Augmentation.class.isAssignableFrom(potential)
+                && !BindingReflections.findAugmentationTarget(potential).equals(BindingReflections.findAugmentationTarget(target))) {
+                return false;
+        }
+        for(Method potentialMethod : potential.getMethods()) {
+            try {
+                Method targetMethod = target.getMethod(potentialMethod.getName(), potentialMethod.getParameterTypes());
+                if(!potentialMethod.getReturnType().equals(targetMethod.getReturnType())) {
+                    return false;
+                }
+            } catch (NoSuchMethodException e) {
+                // Counterpart method is missing, so classes could not be substituted.
+                return false;
+            } catch (SecurityException e) {
+                throw new IllegalStateException("Could not compare methods",e);
+            }
+        }
+        return true;
+    }
 }
index dba2e726fa3d04bca68e2b806f20e1a74242bb9d..e9f940a4555bad2af63797018916240a4209d3a3 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.util.HashCodeBuilder;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 
 /**
@@ -311,7 +312,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
     /**
      * Path argument / component of InstanceIdentifier
      *
-     * Path argument uniquelly identifies node in data tree on particular
+     * Path argument uniquely identifies node in data tree on particular
      * level.
      * <p>
      * This interface itself is used as common parent for actual
@@ -339,6 +340,17 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
          * @return Node type
          */
         QName getNodeType();
+
+        /**
+         * Return the string representation of this object for use in context
+         * provided by a previous object. This method can be implemented in
+         * terms of {@link #toString()}, but implementations are encourage to
+         * reuse any context already emitted by the previous object.
+         *
+         * @param previous Previous path argument
+         * @return String representation
+         */
+        String toRelativeString(PathArgument previous);
     }
 
     private static abstract class AbstractPathArgument implements PathArgument {
@@ -380,6 +392,18 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         public String toString() {
             return getNodeType().toString();
         }
+
+        @Override
+        public String toRelativeString(final PathArgument previous) {
+            if (previous instanceof AbstractPathArgument) {
+                final QNameModule mod = ((AbstractPathArgument)previous).getNodeType().getModule();
+                if (getNodeType().getModule().equals(mod)) {
+                    return getNodeType().getLocalName();
+                }
+            }
+
+            return getNodeType().toString();
+        }
     }
 
     /**
@@ -498,6 +522,11 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         public String toString() {
             return super.toString() + '[' + keyValues + ']';
         }
+
+        @Override
+        public String toRelativeString(final PathArgument previous) {
+            return super.toRelativeString(previous) + '[' + keyValues + ']';
+        }
     }
 
     /**
@@ -539,6 +568,11 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         public String toString() {
             return super.toString() + '[' + value + ']';
         }
+
+        @Override
+        public String toRelativeString(final PathArgument previous) {
+            return super.toRelativeString(previous) + '[' + value + ']';
+        }
     }
 
     /**
@@ -590,7 +624,6 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         }
 
         /**
-         *
          * Returns set of all possible child nodes
          *
          * @return set of all possible child nodes.
@@ -606,6 +639,11 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
             return sb.toString();
         }
 
+        @Override
+        public String toRelativeString(final PathArgument previous) {
+            return toString();
+        }
+
         @Override
         public boolean equals(final Object o) {
             if (this == o) {
@@ -736,15 +774,14 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
             synchronized (this) {
                 ret = toStringCache;
                 if (ret == null) {
-                    final StringBuilder builder = new StringBuilder('/');
-                    boolean first = true;
+                    final StringBuilder builder = new StringBuilder("/");
+                    PathArgument prev = null;
                     for (PathArgument argument : getPathArguments()) {
-                        if (first) {
-                            first = false;
-                        } else {
+                        if (prev != null) {
                             builder.append('/');
                         }
-                        builder.append(argument.toString());
+                        builder.append(argument.toRelativeString(prev));
+                        prev = argument;
                     }
 
                     ret = builder.toString();
index 6b9e36eb7a72aad68ed5874c3fb4adfc94f19639..588b884d8a9edf563af6d6b88d8977a56d7d68d0 100644 (file)
@@ -41,7 +41,18 @@ final class ContainerNode extends AbstractTreeNode {
 
     @Override
     public Optional<TreeNode> getChild(final PathArgument key) {
-        return Optional.fromNullable(children.get(key));
+        Optional<TreeNode> explicitNode = Optional.fromNullable(children.get(key));
+        if (explicitNode.isPresent()) {
+            return explicitNode;
+        }
+        final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> castedData = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>>) getData();
+        Optional<NormalizedNode<?, ?>> value = castedData.getChild(key);
+        if (value.isPresent()) {
+            //FIXME: consider caching created Tree Nodes.
+            //We are safe to not to cache them, since written Tree Nodes are in read only snapshot.
+            return Optional.of(TreeNodeFactory.createTreeNode(value.get(), getVersion()));
+        }
+        return Optional.absent();
     }
 
     @Override
@@ -60,6 +71,26 @@ final class ContainerNode extends AbstractTreeNode {
             this.children = MapAdaptor.getDefaultInstance().takeSnapshot(parent.children);
             this.subtreeVersion = parent.getSubtreeVersion();
             this.version = parent.getVersion();
+            materializeChildVersion();
+        }
+
+        /**
+         * Traverse whole data tree and instantiate children for each data node. Set version of each MutableTreeNode
+         * accordingly to version in data node.
+         *
+         * Use this method if TreeNode is lazy initialized.
+         */
+        private void materializeChildVersion() {
+            Preconditions.checkState(data instanceof NormalizedNodeContainer);
+            NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> castedData = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
+
+            for(NormalizedNode<?, ?> childData : castedData.getValue()) {
+                PathArgument id = childData.getIdentifier();
+
+                if (!children.containsKey(id)) {
+                    children.put(id, TreeNodeFactory.createTreeNode(childData, version));
+                }
+            }
         }
 
         @Override
@@ -97,22 +128,99 @@ final class ContainerNode extends AbstractTreeNode {
         }
     }
 
-    private static ContainerNode create(final Version version, final NormalizedNode<?, ?> data,
-            final Iterable<NormalizedNode<?, ?>> children) {
+    /**
+     * Method creates and returns Container root Node and whole subtree for each child node specified in children nodes.
+     * <br>
+     * Reason why is method used recursively is that for each child in children nodes there is call to
+     * {@link TreeNodeFactory#createTreeNodeRecursively}. Each call to <code>createTreeNodeRecursively</code>
+     * calls either {@link #createNormalizedNodeRecursively} or {@link #createOrderedNodeRecursively}
+     * which depends on type of child node.
+     * <br> The root node that is returned holds reference to data node and whole subtree of children also containing references
+     * to data nodes.
+     *
+     * @param version version of indexed data
+     * @param data reference to data node
+     * @param children direct children of root node that is being created
+     * @return Root node with reference to data node and whole subtree of child nodes
+     */
+    private static ContainerNode createNodeRecursively(final Version version, final NormalizedNode<?, ?> data,
+        final Iterable<NormalizedNode<?, ?>> children) {
 
         final Map<PathArgument, TreeNode> map = new HashMap<>();
         for (NormalizedNode<?, ?> child : children) {
-            map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version));
+            map.put(child.getIdentifier(), TreeNodeFactory.createTreeNodeRecursively(child, version));
         }
 
         return new ContainerNode(data, version, map, version);
     }
 
-    public static ContainerNode create(final Version version, final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
-        return create(version, container, container.getValue());
+    /**
+     * Method creates and returns Normalized Node Container as root and recursively creates whole subtree
+     * from all of the container child iterables stored in {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer#getValue()}
+     * <br>
+     * The reason why is this method called recursively is that in background method calls {@link TreeNodeFactory#createTreeNodeRecursively}
+     * for each child stored in NormalizedNode and after each child is created the method calls again {@link #createNormalizedNodeRecursively} method
+     * until all of the children are resolved.
+     *
+     * @param version version of indexed data
+     * @param container Normalized Node Container
+     * @return Normalized Node Container as root and all whole subtree created from container iterables.
+     */
+    public static ContainerNode createNormalizedNodeRecursively(final Version version,
+        final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
+        return createNodeRecursively(version, container, container.getValue());
+    }
+
+    /**
+     * Method creates and returns Ordered Node Container as root and recursively creates whole subtree
+     * from all of the container child iterables stored in {@link org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer#getValue()}
+     * <br>
+     * The reason why is this method called recursively is that in background method calls {@link TreeNodeFactory#createTreeNodeRecursively}
+     * for each child stored in NormalizedNode and after each child is created the method calls again {@link #createNormalizedNodeRecursively} method
+     * until all of the children are resolved.
+     *
+     * @param version version of indexed data
+     * @param container Ordered Node Container
+     * @return Normalized Ordered Container as root and all whole subtree created from container iterables.
+     */
+    public static ContainerNode createOrderedNodeRecursively(final Version version,
+        final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
+        return createNodeRecursively(version, container, container.getValue());
     }
 
-    public static ContainerNode create(final Version version, final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
-        return create(version, container, container.getValue());
+    /**
+     * Creates and returns single instance of Normalized Node Container with provided version and data reference stored in NormalizedNodeContainer.
+     *
+     * @param version version of indexed data
+     * @param container Normalized Node Container
+     * @return single instance of Normalized node with provided version and data reference stored in NormalizedNodeContainer
+     */
+    public static ContainerNode createNormalizedNode(final Version version,
+        final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
+        return createNode(version, container);
+    }
+
+    /**
+     * Creates and returns single instance of Ordered Node Container with provided version and data reference stored in OrderedNodeContainer.
+     *
+     * @param version version of indexed data
+     * @param container Ordered Node Container
+     * @return single instance of Ordered Node Container with provided version and data reference stored in OrderedNodeContainer.
+     */
+    public static ContainerNode createOrderedNode(final Version version,
+        final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
+        return createNode(version, container);
+    }
+
+    /**
+     * Creates and returns single instance of {@link ContainerNode} with provided version and data reference stored in NormalizedNode.
+     *
+     * @param version version of indexed data
+     * @param data NormalizedNode data container
+     * @return single instance of {@link ContainerNode} with provided version and data reference stored in NormalizedNode.
+     */
+    private static ContainerNode createNode(final Version version, final NormalizedNode<?, ?> data) {
+        final Map<PathArgument, TreeNode> map = new HashMap<>();
+        return new ContainerNode(data, version, map, version);
     }
 }
index 656814162f21d4a54c39900f7a4c6d64d09fbd26..4f0a2201d7c58aa59770e80099c1b68bd4608871 100644 (file)
@@ -28,19 +28,40 @@ public final class TreeNodeFactory {
      * @param version data node version
      * @return new AbstractTreeNode instance, covering the data tree provided
      */
-    public static final TreeNode createTreeNode(final NormalizedNode<?, ?> data, final Version version) {
+    public static final TreeNode createTreeNodeRecursively(final NormalizedNode<?, ?> data, final Version version) {
         if (data instanceof NormalizedNodeContainer<?, ?, ?>) {
             @SuppressWarnings("unchecked")
             NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
-            return ContainerNode.create(version, container);
+            return ContainerNode.createNormalizedNodeRecursively(version, container);
 
         }
         if (data instanceof OrderedNodeContainer<?>) {
             @SuppressWarnings("unchecked")
             OrderedNodeContainer<NormalizedNode<?, ?>> container = (OrderedNodeContainer<NormalizedNode<?, ?>>) data;
-            return ContainerNode.create(version, container);
+            return ContainerNode.createOrderedNodeRecursively(version, container);
         }
 
         return new ValueNode(data, version);
     }
+
+    /**
+     * Create a new AbstractTreeNode from a data node.
+     *
+     * @param data data node
+     * @param version data node version
+     * @return new AbstractTreeNode instance, covering the data tree provided
+     */
+    public static final TreeNode createTreeNode(final NormalizedNode<?, ?> data, final Version version) {
+        if (data instanceof NormalizedNodeContainer<?, ?, ?>) {
+            @SuppressWarnings("unchecked")
+            NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
+            return ContainerNode.createNormalizedNode(version, container);
+        }
+        if (data instanceof OrderedNodeContainer<?>) {
+            @SuppressWarnings("unchecked")
+            OrderedNodeContainer<NormalizedNode<?, ?>> container = (OrderedNodeContainer<NormalizedNode<?, ?>>) data;
+            return ContainerNode.createOrderedNode(version, container);
+        }
+        return new ValueNode(data, version);
+    }
 }
index f51179e6cc02cbd3dee149f836d153c28f5a5730..06f661dd1fa04fd32e46ae652a11a80d100a3e28 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.data.codec.gson;
 
 import com.google.gson.stream.JsonReader;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -19,6 +20,7 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.List;
+
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -32,6 +34,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStre
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
@@ -83,11 +86,10 @@ public class StreamToNormalizedNodeTest {
          * This is the parsing part
          */
         // This is where we will output the nodes
-        final NormalizedNodeContainerBuilder<NodeIdentifier, ?, ?, ? extends NormalizedNode<?, ?>> parent =
-                Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(QName.create("dummy", "2014-12-31", "dummy")));
+        NormalizedNodeResult result = new NormalizedNodeResult();
 
         // StreamWriter which attaches NormalizedNode under parent
-        final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(parent);
+        final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
 
         // JSON -> StreamWriter parser
         try (JsonParserStream handler = JsonParserStream.create(streamWriter, schemaContext)) {
@@ -95,14 +97,14 @@ public class StreamToNormalizedNodeTest {
         }
 
         // Finally build the node
-        final NormalizedNode<?, ?> parsedData = parent.build();
+        final NormalizedNode<?, ?> parsedData = result.getResult();
         LOG.debug("Parsed NormalizedNodes: {}", parsedData);
 
         /*
          * This is the serialization part.
          */
         // We want to write the first child out
-        final DataContainerChild<? extends PathArgument, ?> firstChild = ((ContainerNode) parsedData).getValue().iterator().next();
+        final DataContainerChild<? extends PathArgument, ?> firstChild = (DataContainerChild<? extends PathArgument, ?>) parsedData;
         LOG.debug("Serializing first child: {}", firstChild);
 
         // String holder
index e097771e84a3fd5e59e428322074e03e7b964eb8..7312c363829832466c593d488f6bac31f7356621 100644 (file)
@@ -8,9 +8,7 @@
 package org.opendaylight.yangtools.yang.data.impl.codec.xml;
 
 import java.util.Map;
-
 import javax.annotation.Nonnull;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
@@ -50,10 +48,10 @@ public final class XmlUtils {
             if (pathArgument instanceof NodeIdentifierWithPredicates) {
                 Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
 
-                for (QName keyValue : predicates.keySet()) {
-                    String predicateValue = String.valueOf(predicates.get(keyValue));
+                for (Map.Entry<QName, Object> entry : predicates.entrySet()) {
+                    String predicateValue = String.valueOf(entry.getValue());
                     textContent.append('[');
-                    textContent.append(prefixes.encodeQName(keyValue));
+                    textContent.append(prefixes.encodeQName(entry.getKey()));
                     textContent.append("='");
                     textContent.append(predicateValue);
                     textContent.append("']");
index eb6e4bbd8eb985dbc4fafd061c97de09bb4ae5bb..84ad453df877a9f7226d8a2e6f218b01c3e7207c 100644 (file)
@@ -14,12 +14,10 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
-
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
@@ -150,7 +148,7 @@ public final class SchemaUtils {
     }
 
     private static boolean isFromAugment(final DataNodeContainer schema, final DataSchemaNode childSchema) {
-        if(schema instanceof AugmentationTarget == false) {
+        if (!(schema instanceof AugmentationTarget)) {
             return false;
         }
 
@@ -186,7 +184,7 @@ public final class SchemaUtils {
 
             for (DataSchemaNode child : ((DataNodeContainer) schema).getChildNodes()) {
                 // If is not augmented child, continue
-                if (augments.containsKey(child.getQName()) == false) {
+                if (!(augments.containsKey(child.getQName()))) {
                     continue;
                 }
 
@@ -212,7 +210,7 @@ public final class SchemaUtils {
         // Choice Node has to map child nodes from all its cases
         if (schema instanceof ChoiceNode) {
             for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) schema).getCases()) {
-                if (augments.containsKey(choiceCaseNode.getQName()) == false) {
+                if (!(augments.containsKey(choiceCaseNode.getQName()))) {
                     continue;
                 }
 
@@ -257,7 +255,7 @@ public final class SchemaUtils {
      *
      */
     public static Set<DataSchemaNode> getRealSchemasForAugment(final AugmentationTarget targetSchema, final AugmentationSchema augmentSchema) {
-        if(targetSchema.getAvailableAugmentations().contains(augmentSchema) == false) {
+        if (!(targetSchema.getAvailableAugmentations().contains(augmentSchema))) {
             return Collections.emptySet();
         }
 
index 493c6ceec0055628c3ac77aa4a469edab5b542e6..7a6627eb5e444dddfd9dd385def15f2fcd8cbc24 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid;
 
 import java.util.Map;
 import java.util.Set;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
@@ -26,26 +25,26 @@ public class DataValidationException extends RuntimeException {
 
     public static void checkLegalChild(final boolean isLegal, final YangInstanceIdentifier.PathArgument child, final DataNodeContainer schema,
             final Set<QName> childNodes, final Set<YangInstanceIdentifier.AugmentationIdentifier> augments) {
-        if (isLegal == false) {
+        if (!isLegal) {
             throw new IllegalChildException(child, schema, childNodes, augments);
         }
     }
 
     public static void checkLegalChild(final boolean isLegal, final YangInstanceIdentifier.PathArgument child, final DataSchemaNode schema,
             final Set<QName> childNodes) {
-        if (isLegal == false) {
+        if (!isLegal) {
             throw new IllegalChildException(child, schema, childNodes);
         }
     }
 
     public static void checkLegalChild(final boolean isLegal, final YangInstanceIdentifier.PathArgument child, final ChoiceNode schema) {
-        if (isLegal == false) {
+        if (!isLegal) {
             throw new IllegalChildException(child, schema);
         }
     }
 
     public static void checkLegalData(final boolean isLegal, final String messageTemplate, final Object... messageAttrs) {
-        if (isLegal == false) {
+        if (!isLegal) {
             throw new DataValidationException(String.format(messageTemplate, messageAttrs));
         }
     }
@@ -56,9 +55,6 @@ public class DataValidationException extends RuntimeException {
 
         Object expectedValue = nodeId.getKeyValues().get(keyQName);
         Object actualValue = childNode.getValue();
-        if (childNode == null) {
-            throw new IllegalListKeyException(keyQName, nodeId, actualValue, expectedValue);
-        }
     }
 
     public static void checkListKey(final DataContainerChild<?, ?> childNode, final QName keyQName, final YangInstanceIdentifier.NodeIdentifierWithPredicates nodeId) {
index 486c1c2cf5569641e6de28df1ea444f67925c998..6c24d4f06c84d3c63baf0e4f1ffe9d42716e66fe 100644 (file)
@@ -24,7 +24,7 @@ public final class InMemoryDataTreeFactory implements DataTreeFactory {
         final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
         final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
 
-        return new InMemoryDataTree(TreeNodeFactory.createTreeNode(data, Version.initial()), null);
+        return new InMemoryDataTree(TreeNodeFactory.createTreeNodeRecursively(data, Version.initial()), null);
     }
 
     /**
index e26c32ee5b03bfc01edd2ec64698a66911797bd0..de4bcef79666b6002ede5051ed2064a763838843 100644 (file)
@@ -39,7 +39,7 @@ final class InMemoryDataTreeModification implements DataTreeModification {
     InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final RootModificationApplyOperation resolver) {
         this.snapshot = Preconditions.checkNotNull(snapshot);
         this.strategyTree = Preconditions.checkNotNull(resolver).snapshot();
-        this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode());
+        this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode(), false);
         /*
          * We could allocate version beforehand, since Version contract
          * states two allocated version must be allways different.
@@ -141,8 +141,13 @@ final class InMemoryDataTreeModification implements DataTreeModification {
         ModifiedNode modification = rootNode;
         // We ensure strategy is present.
         ModificationApplyOperation operation = resolveModificationStrategy(path);
+        boolean isOrdered = true;
+        if (operation instanceof SchemaAwareApplyOperation) {
+            isOrdered = ((SchemaAwareApplyOperation) operation).isOrdered();
+        }
+
         for (PathArgument pathArg : path.getPathArguments()) {
-            modification = modification.modifyChild(pathArg);
+            modification = modification.modifyChild(pathArg, isOrdered);
         }
         return OperationWithModification.from(operation, modification);
     }
index 56353350af803bcf1553bc35476d93e63e7f38a4..27b42cc8fe55116e8a979f8602cf87cd0acc84cb 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
+import java.util.HashMap;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -48,16 +49,22 @@ final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<Pa
         }
     };
 
-    private final Map<PathArgument, ModifiedNode> children = new LinkedHashMap<>();
+    private final Map<PathArgument, ModifiedNode> children;
     private final Optional<TreeNode> original;
     private final PathArgument identifier;
     private ModificationType modificationType = ModificationType.UNMODIFIED;
     private Optional<TreeNode> snapshotCache;
     private NormalizedNode<?, ?> value;
 
-    private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original) {
+    private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original, boolean isOrdered) {
         this.identifier = identifier;
         this.original = original;
+
+        if (isOrdered) {
+            children = new LinkedHashMap<>();
+        } else {
+            children = new HashMap<>();
+        }
     }
 
     /**
@@ -119,7 +126,7 @@ final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<Pa
      * @return {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ModifiedNode} for specified child, with {@link #getOriginal()}
      *         containing child metadata if child was present in original data.
      */
-    public ModifiedNode modifyChild(final PathArgument child) {
+    public ModifiedNode modifyChild(final PathArgument child, boolean isOrdered) {
         clearSnapshot();
         if (modificationType == ModificationType.UNMODIFIED) {
             updateModificationType(ModificationType.SUBTREE_MODIFIED);
@@ -137,7 +144,7 @@ final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<Pa
             currentMetadata = Optional.absent();
         }
 
-        ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata);
+        ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata, isOrdered);
         children.put(child, newlyCreated);
         return newlyCreated;
     }
@@ -217,7 +224,7 @@ final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<Pa
                 + modificationType + ", childModification=" + children + "]";
     }
 
-    public static ModifiedNode createUnmodified(final TreeNode metadataTree) {
-        return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree));
+    public static ModifiedNode createUnmodified(final TreeNode metadataTree, boolean isOrdered) {
+        return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), isOrdered);
     }
 }
index 6667076fb40d0f647658ffd302d95d19426136d7..03b7c3ee23d8eb76033e644d2d79a8a173f0ec04 100644 (file)
@@ -108,6 +108,16 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
     }
 
+    /**
+     * Applies write/remove diff operation for each modification child in modification subtree.
+     * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
+     *
+     * @param meta MutableTreeNode (IndexTreeNode)
+     * @param data DataBuilder
+     * @param nodeVersion Version of TreeNode
+     * @param modifications modification operations to apply
+     * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
+     */
     @SuppressWarnings({ "rawtypes", "unchecked" })
     private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
             final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
@@ -223,6 +233,11 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
             entryStrategy = Optional.<ModificationApplyOperation> of(new ValueNodeModificationStrategy.LeafSetEntryModificationStrategy(schema));
         }
 
+        @Override
+        boolean isOrdered() {
+            return true;
+        }
+
         @SuppressWarnings("rawtypes")
         @Override
         protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
@@ -248,6 +263,11 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
             entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.ListEntryModificationStrategy(schema));
         }
 
+        @Override
+        boolean isOrdered() {
+            return true;
+        }
+
         @SuppressWarnings("rawtypes")
         @Override
         protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
index 511fc322cbd8b2b402ec50c56798fcd13b9828a2..e1df47c7d4df2d20ad65e7caf2860b77726801b0 100644 (file)
@@ -61,8 +61,13 @@ final class OperationWithModification {
     }
 
     public OperationWithModification forChild(final PathArgument childId) {
-        ModifiedNode childMod = modification.modifyChild(childId);
-        Optional<ModificationApplyOperation> childOp = applyOperation.getChild(childId);
-        return from(childOp.get(),childMod);
+        ModificationApplyOperation childOp = applyOperation.getChild(childId).get();
+        boolean isOrdered = true;
+        if (childOp instanceof SchemaAwareApplyOperation) {
+            isOrdered = ((SchemaAwareApplyOperation) childOp).isOrdered();
+        }
+        ModifiedNode childMod = modification.modifyChild(childId, isOrdered);
+
+        return from(childOp,childMod);
     }
 }
index d0a0bcd33fe9d7d82df72dedd2700be4fc3f62e7..d7aa826c236f4c375ca9e1bd6c3dccf3f5dd7d42 100644 (file)
@@ -9,19 +9,24 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
@@ -158,7 +163,18 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
     }
 
-    protected void checkWriteApplicable(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
+    /**
+     * Checks if write operation can be applied to current TreeNode.
+     * The operation checks if original tree node to which the modification is going to be applied exists and if
+     * current node in TreeNode structure exists.
+     *
+     * @param path Path from current node in TreeNode
+     * @param modification modification to apply
+     * @param current current node in TreeNode for modification to apply
+     * @throws DataValidationFailedException
+     */
+    protected void checkWriteApplicable(final YangInstanceIdentifier path, final NodeModification modification,
+        final Optional<TreeNode> current) throws DataValidationFailedException {
         Optional<TreeNode> original = modification.getOriginal();
         if (original.isPresent() && current.isPresent()) {
             checkNotConflicting(path, original.get(), current.get());
@@ -176,6 +192,10 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         }
     }
 
+    boolean isOrdered() {
+        return false;
+    }
+
     @Override
     public final Optional<TreeNode> apply(final ModifiedNode modification,
             final Optional<TreeNode> currentMeta, final Version version) {
@@ -234,6 +254,11 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
             entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy(schema));
         }
 
+        @Override
+        boolean isOrdered() {
+            return true;
+        }
+
         @Override
         protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
                 final Version version) {
@@ -249,12 +274,65 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
         @Override
         protected TreeNode applyWrite(final ModifiedNode modification,
                 final Optional<TreeNode> currentMeta, final Version version) {
+            final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
+            final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
+
+            if (Iterables.isEmpty(modification.getChildren())) {
+                return newValueMeta;
+            }
+
             /*
-             * FIXME: BUG-1258: This is inefficient: it needlessly creates index nodes for the entire subtree.
-             *        We can determine the depth into which metadata need to be created from the modification
-            *        -- if it does not have children, no need to bother with metadata.
+             * This is where things get interesting. The user has performed a write and
+             * then she applied some more modifications to it. So we need to make sense
+             * of that an apply the operations on top of the written value. We could have
+             * done it during the write, but this operation is potentially expensive, so
+             * we have left it out of the fast path.
+             *
+             * As it turns out, once we materialize the written data, we can share the
+             * code path with the subtree change. So let's create an unsealed TreeNode
+             * and run the common parts on it -- which end with the node being sealed.
              */
-            return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
+            final MutableTreeNode mutable = newValueMeta.mutable();
+            mutable.setSubtreeVersion(version);
+
+            @SuppressWarnings("rawtypes")
+            final NormalizedNodeContainerBuilder dataBuilder = ImmutableUnkeyedListEntryNodeBuilder
+                .create((UnkeyedListEntryNode) newValue);
+
+            return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
+        }
+
+        /**
+         * Applies write/remove diff operation for each modification child in modification subtree.
+         * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
+         *
+         * @param meta MutableTreeNode (IndexTreeNode)
+         * @param data DataBuilder
+         * @param nodeVersion Version of TreeNode
+         * @param modifications modification operations to apply
+         * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
+         */
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
+            final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
+
+            for (ModifiedNode mod : modifications) {
+                final PathArgument id = mod.getIdentifier();
+                final Optional<TreeNode> cm = meta.getChild(id);
+
+                Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+                if (result.isPresent()) {
+                    final TreeNode tn = result.get();
+                    meta.addChild(tn);
+                    data.addChild(tn.getData());
+                } else {
+                    meta.removeChild(id);
+                    data.removeChild(id);
+                }
+            }
+
+            meta.setData(data.build());
+            return meta.seal();
         }
 
         @Override
index 6979a64f717c15d708f9d950fe0f93f99eff561a..3df0c80e959eef38d79d91e1ad45e28a20894d28 100644 (file)
@@ -62,7 +62,7 @@ abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends S
     @Override
     protected TreeNode applyWrite(final ModifiedNode modification,
             final Optional<TreeNode> currentMeta, final Version version) {
-        return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
+        return TreeNodeFactory.createTreeNodeRecursively(modification.getWrittenValue(), version);
     }
 
     @Override
index a85acfd1e4c30f377fd768a1e7893e703f1bb477..2896675c156a0ddc5c2be0612d140dad75ed9c26 100644 (file)
@@ -146,7 +146,7 @@ public class ModificationMetadataTreeTest {
     @Test
     public void basicReadWrites() {
         DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper),
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper),
                 rootOper);
         Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
         assertTrue(originalBarNode.isPresent());
index bc1f6cef4f50f835268179cf855b7093f63d7778..509037fbccc05915712c3fcd141f5658d079bd2e 100644 (file)
@@ -94,7 +94,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void findNodeTestNodeFound() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         Optional<TreeNode> node = TreeNodeUtils.findNode(rootNode, OUTER_LIST_1_PATH);
         assertPresentAndType(node, TreeNode.class);
@@ -103,7 +103,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void findNodeTestNodeNotFound() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         final YangInstanceIdentifier outerList1InvalidPath = YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
                 .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 3) //
@@ -115,7 +115,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void findNodeCheckedTestNodeFound() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         TreeNode foundNode = null;
         try {
@@ -129,7 +129,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void findNodeCheckedTestNodeNotFound() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         final YangInstanceIdentifier outerList1InvalidPath = YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
                 .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 3) //
@@ -145,7 +145,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void findClosestOrFirstMatchTestNodeExists() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         Optional<TreeNode> expectedNode = TreeNodeUtils.findNode(rootNode, TWO_TWO_PATH);
         assertPresentAndType(expectedNode, TreeNode.class);
@@ -156,7 +156,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void findClosestOrFirstMatchTestNodeDoesNotExist() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         final YangInstanceIdentifier outerListInnerListPath = YangInstanceIdentifier.builder(OUTER_LIST_2_PATH)
                 .node(TestModel.INNER_LIST_QNAME)
@@ -174,7 +174,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void getChildTestChildFound() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         Optional<TreeNode> node = TreeNodeUtils.getChild(Optional.fromNullable(rootNode),
                 TestModel.TEST_PATH.getLastPathArgument());
@@ -184,7 +184,7 @@ public class TreeNodeUtilsTest {
     @Test
     public void getChildTestChildNotFound() {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
-                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+                TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         Optional<TreeNode> node = TreeNodeUtils.getChild(Optional.fromNullable(rootNode),
                 TestModel.OUTER_LIST_PATH.getLastPathArgument());
index e281ea73393ef8c6c03636649eda5d6d7c873d49..fdaf0c8f702513899a84586cac99bf2a0a25aabf 100644 (file)
@@ -11,7 +11,6 @@ import java.util.Set;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
@@ -72,7 +71,7 @@ final class ChoiceNodeModification extends
         Set<YangInstanceIdentifier.PathArgument> childrenToProcessFiltered = Sets.newLinkedHashSet();
         for (YangInstanceIdentifier.PathArgument childToProcess : childrenToProcess) {
             // child from other cases, skip
-            if (childToProcess instanceof AugmentationNode
+            if (childToProcess instanceof YangInstanceIdentifier.AugmentationIdentifier
                     && SchemaUtils.belongsToCaseAugment(detectedCase,
                             (YangInstanceIdentifier.AugmentationIdentifier) childToProcess) == false) {
                 continue;
index e8bcc0651039413b7c4fa95cb00917e8ff2a95f9..722ac918e08c995d391546d085fcf6b4aa36b95b 100644 (file)
@@ -146,7 +146,7 @@ public abstract class AbstractSchemaRepository implements SchemaRepository, Sche
             }
 
             if (m.isEmpty()) {
-                sources.remove(m);
+                sources.remove(source.getSourceIdentifier());
             }
         }
     }
index e89e6572f459730a09d1cb30e3956138ec962596..20f8c881a912235c01746fbf4f7606609ab1d004 100644 (file)
@@ -7,18 +7,16 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
 import java.util.Collections;
 import java.util.List;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-
 /**
  * The <code>default</code> implementation of Bits Type Definition interface.
  *
@@ -28,7 +26,7 @@ public final class BitsType implements BitsTypeDefinition {
     private final static QName NAME = BaseTypes.BITS_QNAME;
 
     private final SchemaPath path;
-    private final String description = "The bits built-in type represents a bit set.  "
+    private static final String DESCRIPTION = "The bits built-in type represents a bit set. "
             + "That is, a bits value is a set of flags identified by small integer position "
             + "numbers starting at 0.  Each bit number has an assigned name.";
 
@@ -129,7 +127,7 @@ public final class BitsType implements BitsTypeDefinition {
      */
     @Override
     public String getDescription() {
-        return description;
+        return DESCRIPTION;
     }
 
     /*
@@ -167,7 +165,6 @@ public final class BitsType implements BitsTypeDefinition {
         final int prime = 31;
         int result = 1;
         result = prime * result + ((bits == null) ? 0 : bits.hashCode());
-        result = prime * result + ((description == null) ? 0 : description.hashCode());
         result = prime * result + NAME.hashCode();
         result = prime * result + path.hashCode();
         return result;
@@ -192,14 +189,6 @@ public final class BitsType implements BitsTypeDefinition {
         } else if (!bits.equals(other.bits)) {
             return false;
         }
-        if (description == null) {
-            if (other.description != null) {
-                return false;
-            }
-        } else if (!description.equals(other.description)) {
-            return false;
-        }
-
         if (path == null) {
             if (other.path != null) {
                 return false;
@@ -218,7 +207,7 @@ public final class BitsType implements BitsTypeDefinition {
         builder.append(", path=");
         builder.append(path);
         builder.append(", description=");
-        builder.append(description);
+        builder.append(DESCRIPTION);
         builder.append(", reference=");
         builder.append(REFERENCE);
         builder.append(", bits=");
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnknownType.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnknownType.java
deleted file mode 100644 (file)
index f32c16f..0000000
+++ /dev/null
@@ -1,432 +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.yangtools.yang.model.util;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.Status;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
-import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
-import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
-import org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition;
-
-/**
- * Utility implementation of unknown type definition.
- *
- * Unknown type definition is derived type, for
- * which base built-in type is not yet known. This types
- * are possible during parsing and resolving of YANG model
- * without all requisites already processed.
- */
-public final class UnknownType implements UnknownTypeDefinition {
-
-    private final QName name;
-    private final SchemaPath path;
-    private final String description;
-    private final String reference;
-    private final List<LengthConstraint> lengthStatements;
-    private final List<PatternConstraint> patterns;
-    private final List<RangeConstraint> rangeStatements;
-    private final List<UnknownSchemaNode> extensions;
-    private final LengthConstraint lengthConstraint;
-    private final Integer fractionDigits;
-
-    private final Status status;
-    private final String units;
-    private final Object defaultValue;
-
-    public static class Builder {
-
-        private final QName name;
-        private final SchemaPath path;
-        private String description;
-        private String reference;
-
-        private List<LengthConstraint> lengthStatements = Collections.emptyList();
-        private List<PatternConstraint> patterns = Collections.emptyList();
-        private List<RangeConstraint> rangeStatements = Collections.emptyList();
-        private List<UnknownSchemaNode> extensions = Collections.emptyList();
-        private LengthConstraint lengthConstraint = null;
-        private Integer fractionDigits = null;
-
-        private Status status = Status.CURRENT;
-        private String units = "";
-        private Object defaultValue = null;
-
-        public Builder(final QName name, final String description, final String reference) {
-            this.name = name;
-            this.path = SchemaPath.create(true, name);
-            this.description = description;
-            this.reference = reference;
-        }
-
-        public Builder(final QName name) {
-            this.name = name;
-            this.path = SchemaPath.create(true, name);
-        }
-
-        public Builder description(final String description) {
-            this.description = description;
-            return this;
-        }
-
-        public Builder reference(final String reference) {
-            this.reference = reference;
-            return this;
-        }
-
-        public Builder lengthStatements(final List<LengthConstraint> lengthStatements) {
-            this.lengthStatements = lengthStatements;
-            return this;
-        }
-
-        public Builder patterns(final List<PatternConstraint> patterns) {
-            this.patterns = patterns;
-            return this;
-        }
-
-        public Builder rangeStatements(final List<RangeConstraint> rangeStatements) {
-            this.rangeStatements = rangeStatements;
-            return this;
-        }
-
-        public Builder extensions(final List<UnknownSchemaNode> extensions) {
-            this.extensions = extensions;
-            return this;
-        }
-
-        public Builder lengthConstraint(final LengthConstraint lengthConstraint) {
-            this.lengthConstraint = lengthConstraint;
-            return this;
-        }
-
-        public Builder fractionDigits(final Integer fractionDigits) {
-            this.fractionDigits = fractionDigits;
-            return this;
-        }
-
-        public Builder status(final Status status) {
-            this.status = status;
-            return this;
-        }
-
-        public Builder units(final String units) {
-            this.units = units;
-            return this;
-        }
-
-        public Builder defaultValue(final Object defaultValue) {
-            this.defaultValue = defaultValue;
-            return this;
-        }
-
-        public UnknownTypeDefinition build() {
-            return new UnknownType(this);
-        }
-    }
-
-    private UnknownType(final Builder builder) {
-        this.name = builder.name;
-        this.path = builder.path;
-        this.description = builder.description;
-        this.reference = builder.reference;
-        this.lengthStatements = builder.lengthStatements;
-        this.patterns = builder.patterns;
-        this.rangeStatements = builder.rangeStatements;
-        this.extensions = builder.extensions;
-        this.lengthConstraint = builder.lengthConstraint;
-        this.status = builder.status;
-        this.units = builder.units;
-        this.defaultValue = builder.defaultValue;
-        this.fractionDigits = builder.fractionDigits;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see
-     * org.opendaylight.yangtools.yang.model.api.TypeDefinition#getBaseType()
-     */
-    @Override
-    public UnknownTypeDefinition getBaseType() {
-        return this;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.TypeDefinition#getUnits()
-     */
-    @Override
-    public String getUnits() {
-        return units;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see
-     * org.opendaylight.yangtools.yang.model.api.TypeDefinition#getDefaultValue
-     * ()
-     */
-    @Override
-    public Object getDefaultValue() {
-        return defaultValue;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.SchemaNode#getQName()
-     */
-    @Override
-    public QName getQName() {
-        return name;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.SchemaNode#getPath()
-     */
-    @Override
-    public SchemaPath getPath() {
-        return path;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see
-     * org.opendaylight.yangtools.yang.model.api.SchemaNode#getDescription()
-     */
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.SchemaNode#getReference()
-     */
-    @Override
-    public String getReference() {
-        return reference;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.SchemaNode#getStatus()
-     */
-    @Override
-    public Status getStatus() {
-        return status;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see
-     * org.opendaylight.yangtools.yang.model.api.SchemaNode#getExtensionSchemaNodes
-     * ()
-     */
-    @Override
-    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
-        return extensions;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition
-     * #getRangeStatements()
-     */
-    @Override
-    public List<RangeConstraint> getRangeConstraints() {
-        return rangeStatements;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition
-     * #getLengthStatements()
-     */
-    @Override
-    public List<LengthConstraint> getLengthConstraints() {
-        return lengthStatements;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition
-     * #getPatterns()
-     */
-    @Override
-    public List<PatternConstraint> getPatternConstraints() {
-        return patterns;
-    }
-
-    @Override
-    public Integer getFractionDigits() {
-        return fractionDigits;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((defaultValue == null) ? 0 : defaultValue.hashCode());
-        result = prime * result + ((description == null) ? 0 : description.hashCode());
-        result = prime * result + ((extensions == null) ? 0 : extensions.hashCode());
-        result = prime * result + ((lengthConstraint == null) ? 0 : lengthConstraint.hashCode());
-        result = prime * result + ((lengthStatements == null) ? 0 : lengthStatements.hashCode());
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + ((path == null) ? 0 : path.hashCode());
-        result = prime * result + ((patterns == null) ? 0 : patterns.hashCode());
-        result = prime * result + ((rangeStatements == null) ? 0 : rangeStatements.hashCode());
-        result = prime * result + ((reference == null) ? 0 : reference.hashCode());
-        result = prime * result + ((status == null) ? 0 : status.hashCode());
-        result = prime * result + ((units == null) ? 0 : units.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        UnknownType other = (UnknownType) obj;
-        if (defaultValue == null) {
-            if (other.defaultValue != null) {
-                return false;
-            }
-        } else if (!defaultValue.equals(other.defaultValue)) {
-            return false;
-        }
-        if (description == null) {
-            if (other.description != null) {
-                return false;
-            }
-        } else if (!description.equals(other.description)) {
-            return false;
-        }
-        if (extensions == null) {
-            if (other.extensions != null) {
-                return false;
-            }
-        } else if (!extensions.equals(other.extensions)) {
-            return false;
-        }
-        if (lengthConstraint == null) {
-            if (other.lengthConstraint != null) {
-                return false;
-            }
-        } else if (!lengthConstraint.equals(other.lengthConstraint)) {
-            return false;
-        }
-        if (lengthStatements == null) {
-            if (other.lengthStatements != null) {
-                return false;
-            }
-        } else if (!lengthStatements.equals(other.lengthStatements)) {
-            return false;
-        }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if (path == null) {
-            if (other.path != null) {
-                return false;
-            }
-        } else if (!path.equals(other.path)) {
-            return false;
-        }
-        if (patterns == null) {
-            if (other.patterns != null) {
-                return false;
-            }
-        } else if (!patterns.equals(other.patterns)) {
-            return false;
-        }
-        if (rangeStatements == null) {
-            if (other.rangeStatements != null) {
-                return false;
-            }
-        } else if (!rangeStatements.equals(other.rangeStatements)) {
-            return false;
-        }
-        if (reference == null) {
-            if (other.reference != null) {
-                return false;
-            }
-        } else if (!reference.equals(other.reference)) {
-            return false;
-        }
-        if (status != other.status) {
-            return false;
-        }
-        if (units == null) {
-            if (other.units != null) {
-                return false;
-            }
-        } else if (!units.equals(other.units)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder2 = new StringBuilder();
-        builder2.append("UnknownType [name=");
-        builder2.append(name);
-        builder2.append(", path=");
-        builder2.append(path);
-        builder2.append(", description=");
-        builder2.append(description);
-        builder2.append(", reference=");
-        builder2.append(reference);
-        builder2.append(", lengthStatements=");
-        builder2.append(lengthStatements);
-        builder2.append(", patterns=");
-        builder2.append(patterns);
-        builder2.append(", rangeStatements=");
-        builder2.append(rangeStatements);
-        builder2.append(", extensions=");
-        builder2.append(extensions);
-        builder2.append(", lengthConstraint=");
-        builder2.append(lengthConstraint);
-        builder2.append(", status=");
-        builder2.append(status);
-        builder2.append(", units=");
-        builder2.append(units);
-        builder2.append(", defaultValue=");
-        builder2.append(defaultValue);
-        builder2.append("]");
-        return builder2.toString();
-    }
-
-}
index 6eb400c483ce7b622b1504ee87ace10c1912db93..e1792c899f7fc1af26caf0c5f4559a3864cd94f3 100644 (file)
@@ -44,7 +44,9 @@ public final class GroupingUtils {
      *            all loaded modules
      * @param module
      *            current module
-     * @return grouping with given name if found, null otherwise
+     * @return grouping with given name, never null
+     * @throws YangParseException
+     *             if no grouping found
      */
     public static GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
             final Map<URI, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
index 2d2b6420032b6fe279c3840fda0c48cd661a4445..ec7dcd5bbaf8936ef80313807737eca60ee8893f 100644 (file)
@@ -19,7 +19,6 @@ import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
-import org.opendaylight.yangtools.yang.model.util.UnknownType;
 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.util.AbstractTypeAwareBuilder;
@@ -68,11 +67,12 @@ public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder im
     public TypeDefinition<? extends TypeDefinition<?>> build() {
         TypeDefinition<?> result;
         ExtendedType.Builder typeBuilder;
-        if ((type == null || type instanceof UnknownType) && typedef == null) {
-            throw new YangParseException("Unresolved type: '" + qname.getLocalName() + "'.");
-        }
-        if (type == null || type instanceof UnknownType) {
-            type = typedef.build();
+        if (type == null) {
+            if (typedef == null) {
+                throw new YangParseException("Unresolved type: '" + qname.getLocalName() + "'.");
+            } else {
+                type = typedef.build();
+            }
         }
 
         typeBuilder = ExtendedType.builder(qname, type, Optional.fromNullable(description),
index 30e28d46bde7c04ae1b2e1be768fb34a6f67f2b7..766b61fbce1605e094f920187822eeecc9d186e5 100644 (file)
@@ -26,6 +26,7 @@ public abstract class AbstractDocumentedDataNodeContainer extends AbstractDocume
     private final Set<GroupingDefinition> groupings;
     private final Set<UsesNode> uses;
     private final Set<TypeDefinition<?>> typeDefinitions;
+    private final Set<DataSchemaNode> publicChildNodes;
 
     protected AbstractDocumentedDataNodeContainer(final AbstractDocumentedDataNodeContainerBuilder data) {
         super(data);
@@ -36,6 +37,7 @@ public abstract class AbstractDocumentedDataNodeContainer extends AbstractDocume
         groupings = ImmutableSet.copyOf(data.getGroupings());
         uses = ImmutableSet.copyOf(data.getUsesNodes());
         typeDefinitions = ImmutableSet.copyOf(data.getTypeDefinitions());
+        publicChildNodes = ImmutableSet.copyOf(childNodes.values());
     }
 
     @Override
@@ -45,7 +47,7 @@ public abstract class AbstractDocumentedDataNodeContainer extends AbstractDocume
 
     @Override
     public final Set<DataSchemaNode> getChildNodes() {
-        return ImmutableSet.copyOf(childNodes.values());
+        return publicChildNodes;
     }
 
     @Override
index 933ac6b6d4f17f489efb3fa878ea868bbf7bfb94..83b56314cb93de7f7fbfd603e66d05b3966b5037 100644 (file)
@@ -11,17 +11,14 @@ import static com.google.common.base.Preconditions.checkState;
 
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Lists;
-
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
@@ -183,13 +180,13 @@ public final class ParserListenerUtils {
                 continue;
             }
             /*
-             * 
+             *
              * It is safe not to check last argument to be same
              * grammars enforces that.
-             * 
+             *
              * FIXME: Introduce proper escaping and translation of escaped
              * characters here.
-             * 
+             *
              */
             sb.append(quoteMatcher.removeFrom(str.substring(1, str.length()-1)));
         }
@@ -378,7 +375,15 @@ public final class ParserListenerUtils {
             ParseTree child = ctx.getChild(i);
             if (child instanceof Value_stmtContext) {
                 String valueStr = stringFromNode(child);
-                value = Integer.valueOf(valueStr);
+                try {
+                    // yang enum value has same restrictions as JAVA Integer
+                    value = Integer.valueOf(valueStr);
+                } catch (NumberFormatException e) {
+                    String err = String
+                            .format("Error on enum '%s': the enum value MUST be in the range from -2147483648 to 2147483647, but was: %s",
+                                    name, valueStr);
+                    throw new YangParseException(moduleName, ctx.getStart().getLine(), err, e);
+                }
             } else if (child instanceof Description_stmtContext) {
                 description = stringFromNode(child);
             } else if (child instanceof Reference_stmtContext) {
@@ -391,10 +396,6 @@ public final class ParserListenerUtils {
         if (value == null) {
             value = highestValue + 1;
         }
-        if (value < -2147483648 || value > 2147483647) {
-            throw new YangParseException(moduleName, ctx.getStart().getLine(), "Error on enum '" + name
-                    + "': the enum value MUST be in the range from -2147483648 to 2147483647, but was: " + value);
-        }
 
         EnumPairImpl result = new EnumPairImpl();
         result.qname = path.getPathTowardsRoot().iterator().next();
index 38055d908df31608a5a3d100c8976fc69f0c182c..7948158f4dee6b277493d8d2451395d3ee6b3d19 100644 (file)
@@ -240,7 +240,7 @@ public final class YangParserImpl implements YangContextParser {
                     if (targetModule == null) {
                         Module result = findModuleFromContext(context, module, prefix, 0);
                         targetModule = new ModuleBuilder(result);
-                        TreeMap<Date, ModuleBuilder> map = modules.get(prefix);
+                        TreeMap<Date, ModuleBuilder> map = modules.get(targetModule.getNamespace());
                         if (map == null) {
                             map = new TreeMap<>();
                             map.put(targetModule.getRevision(), targetModule);
@@ -1061,10 +1061,6 @@ public final class YangParserImpl implements YangContextParser {
             ModuleBuilder module = BuilderUtils.getParentModule(usesNode);
             final GroupingBuilder targetGroupingBuilder = GroupingUtils.getTargetGroupingFromModules(usesNode, modules,
                     module);
-            if (targetGroupingBuilder == null) {
-                throw new YangParseException(module.getName(), usesNode.getLine(), "Referenced grouping '"
-                        + usesNode.getGroupingPath() + "' not found.");
-            }
             usesNode.setGrouping(targetGroupingBuilder);
         }
     }
index 9f80a1e7f7f148a9bcb2ec0992b824f0cad6c579..46c2f8240d3cb08f8eb28cce17da647125ebc0df 100644 (file)
@@ -196,14 +196,11 @@ public abstract class YangModelDependencyInfo {
 
     private static YangModelDependencyInfo parseModuleContext(final Module_stmtContext module) {
         String name = getArgumentString(module);
-        // String prefix =
-        // getArgumentString(module.module_header_stmts().prefix_stmt(0));
-        String namespace = getArgumentString(module.module_header_stmts().namespace_stmt(0));
         String latestRevision = getLatestRevision(module.revision_stmts());
         ImmutableSet<ModuleImport> imports = parseImports(module.linkage_stmts().import_stmt());
         ImmutableSet<ModuleImport> includes = parseIncludes(module.linkage_stmts().include_stmt());
 
-        return new ModuleDependencyInfo(name, latestRevision, namespace, imports, includes);
+        return new ModuleDependencyInfo(name, latestRevision, imports, includes);
     }
 
     private static ImmutableSet<ModuleImport> parseImports(final List<Import_stmtContext> importStatements) {
@@ -265,7 +262,7 @@ public abstract class YangModelDependencyInfo {
      */
     public static final class ModuleDependencyInfo extends YangModelDependencyInfo {
 
-        private ModuleDependencyInfo(final String name, final String latestRevision, final String namespace,
+        private ModuleDependencyInfo(final String name, final String latestRevision,
                 final ImmutableSet<ModuleImport> imports, final ImmutableSet<ModuleImport> includes) {
             super(name, latestRevision, imports, includes);
         }