Merge "Maping of union leaf a bits leaf YANG type to JAVA inner classes."
authorAlessandro Boch <aboch@cisco.com>
Wed, 10 Jul 2013 17:04:36 +0000 (17:04 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 10 Jul 2013 17:04:36 +0000 (17:04 +0000)
95 files changed:
opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/SimpleClient.java
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java
opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java
opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java
opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GlobalConstants.java
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Activator.java
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/DataPacketService.java
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ReadService.java
opendaylight/sal/yang-prototype/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/controller/maven/sal/api/gen/plugin/CodeGeneratorImpl.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/java/org/opendaylight/controller/yang2sources/plugin/it/YangToSourcesPluginTestIT.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/ConfigArg.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesProcessor.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/AbstractDataNodeContainerBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/AbstractSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/DataNodeContainerBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AnyXmlBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AugmentationSchemaBuilderImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ChoiceBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/DeviationBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ExtensionBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/FeatureBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/GroupingBuilderImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/IdentitySchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ModuleBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/NotificationBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/RpcDefinitionBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UnknownSchemaNodeBuilder.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserListenerImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ParserListenerUtils.java [moved from opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/YangModelBuilderUtil.java with 98% similarity]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ParserUtils.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TypeConstraints.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/validator/ValidationUtil.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/AugmentTest.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/GroupingTest.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserTest.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserWithContextTest.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/context-test/deviation-test.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/context-test/test2.yang
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/custom.yang [moved from opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile3.yang with 63% similarity]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/nodes.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang [deleted file]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile2.yang [deleted file]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/types.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/yang/pom.xml
opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java [deleted file]
opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableCompositeNode.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableNode.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableSimpleNode.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java
opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModification.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModificationBuilder.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/pom.xml [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/AbstractNodeTO.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeModificationTOImpl.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeTOImpl.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableCompositeNodeTOImpl.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableSimpleNodeTOImpl.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeFactory.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImpl.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeUtils.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeModificationTOImpl.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeTOImpl.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeFactoryTest.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeHelper.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImplTest.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config01.xml [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.content [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.xml [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02g.xml [new file with mode: 0644]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.xsd [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.yang [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/generateXml.groovy [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.xsd [new file with mode: 0644]
opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.yang [new file with mode: 0755]
opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Deviation.java
opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SpanConfig.java
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/Subnet.java
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SwitchConfig.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java
opendaylight/switchmanager/implementation/src/test/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImplTest.java
opendaylight/switchmanager/integrationtest/src/test/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerIT.java
opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java
opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java
third-party/openflowj/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java

index b6ab95db33fff81260879bb97065b2fafbf840bd..0a0a9d8828ea3ec6de32739d13e85f99e2dd08bf 100644 (file)
@@ -273,7 +273,7 @@ public class SimpleClient implements CommandProvider {
             ci.println("\nNo Clustering services available");
             return;
         }
-        String containerName = ci.nextArgument();
+        String containerName = ci.nextArgument().toLowerCase();
         if (containerName == null) {
             ci.println("containerName not supplied");
             return;
@@ -372,7 +372,7 @@ public class SimpleClient implements CommandProvider {
 
     public void _dumper(CommandInterpreter ci) {
         ConcurrentMap<Object, Object> c;
-        String containerName = ci.nextArgument();
+        String containerName = ci.nextArgument().toLowerCase();
         if (containerName == null) {
             ci.println("containerName not supplied");
             return;
@@ -490,6 +490,7 @@ public class SimpleClient implements CommandProvider {
     }
 
     class DoListenRoleChanged implements IListenRoleChange {
+        @Override
         public void newActiveAvailable() {
             logger.debug("New Active is available");
         }
index 2b9696ddb9cdf058640caa671735757556fb1a5a..1ac7cb2f51360e634dec98e33857c848ce48e069 100644 (file)
@@ -71,9 +71,11 @@ import org.slf4j.LoggerFactory;
 public class FlowConfig implements Serializable {
     private static final long serialVersionUID = 1L;
     private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
-    public static final String staticFlowsGroup = "**StaticFlows";
-    public static final String internalStaticFlowsGroup = "**InternalStaticFlows";
-    public static final String internalStaticFlowBegin = "**";
+    private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+    private static final String STATICFLOWGROUP = "__StaticFlows__";
+    public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
+    public static final String INTERNALSTATICFLOWBEGIN = "__";
+    public static final String INTERNALSTATICFLOWEND = "__";
     private boolean dynamic;
     private String status;
 
@@ -200,8 +202,9 @@ public class FlowConfig implements Serializable {
     }
 
     public boolean isInternalFlow() {
-        // Controller generated static flows have name starting with "**"
-        return (this.name != null && this.name.startsWith(FlowConfig.internalStaticFlowBegin));
+        return (this.name != null &&
+                this.name.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN) &&
+                this.name.endsWith(FlowConfig.INTERNALSTATICFLOWEND));
     }
 
     public String getName() {
@@ -692,7 +695,7 @@ public class FlowConfig implements Serializable {
 
         Switch sw = null;
         try {
-            if (name == null || name.trim().isEmpty()) {
+            if (name == null || name.trim().isEmpty() || !name.matches(FlowConfig.NAMEREGEX)) {
                 return new Status(StatusCode.BADREQUEST, "Invalid name");
             }
 
@@ -965,7 +968,8 @@ public class FlowConfig implements Serializable {
     }
 
     public FlowEntry getFlowEntry() {
-        return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this.getFlow(), this.getNode());
+        String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
+        return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
     }
 
     public Flow getFlow() {
index e86e0186c61544b73763ff2fa3edc877ce14c5f7..e8c5f648fa69c4c7d3c9f5f4846daf73a8e78341 100644 (file)
@@ -187,6 +187,7 @@ public class FlowEntry implements Cloneable, Serializable {
      * @return true if internal generated static flow, false otherwise
      */
     public boolean isInternal() {
-        return flowName.startsWith(FlowConfig.internalStaticFlowBegin);
+        return flowName.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN)
+                && flowName.endsWith(FlowConfig.INTERNALSTATICFLOWEND);
     }
 }
index bde6932a626dc10d70612b1d3ca03d4d203db3eb..4b8257488ef08c072785a5cef76f56c550ba882a 100644 (file)
@@ -350,12 +350,9 @@ public interface IForwardingRulesManager {
      *
      * @param config
      *            the {@code FlowConfig} object representing the static flow
-     * @param restore
-     *            if set to true, the config object validation will be skipped.
-     *            Used only internally, always set it to false.
      * @return the {@code Status} object indicating the result of this action.
      */
-    public Status addStaticFlow(FlowConfig config, boolean restore);
+    public Status addStaticFlow(FlowConfig config);
 
     /**
      * Remove a flow specified by the {@code FlowConfig} object on the current
index f139f45377a0344733b853cb6c86c59daca1226f..fc22ee7dddaef5752bd03647e2e4830c0f77205d 100644 (file)
@@ -258,7 +258,10 @@ public class frmTest {
     public void testInternalFlow() {
         FlowConfig flowConfig = new FlowConfig();
         Assert.assertFalse(flowConfig.isInternalFlow());
-        flowConfig.setName("**Internal");
+        flowConfig.setName("__Internal__");
+        Status status = flowConfig.validate(null);
+        Assert.assertFalse(status.isSuccess());
+        Assert.assertTrue(status.getDescription().contains("name"));
         Assert.assertTrue(flowConfig.isInternalFlow());
         flowConfig.setName("External");
         Assert.assertFalse(flowConfig.isInternalFlow());
index f6fc0012ad4219f368373cb10284e1c401e96a0f..5b2b3b32b4e1ceeb94f3bbcfb0ed969d64ab3dff 100644 (file)
@@ -30,7 +30,6 @@ import org.slf4j.LoggerFactory;
 
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
-import org.opendaylight.controller.hosttracker.IfIptoHost;
 
 public class Activator extends ComponentActivatorAbstractBase {
     protected static final Logger logger = LoggerFactory.getLogger(Activator.class);
@@ -104,15 +103,12 @@ public class Activator extends ComponentActivatorAbstractBase {
 
             c.add(createContainerServiceDependency(containerName).setService(IFlowProgrammerService.class)
                     .setCallbacks("setFlowProgrammerService", "unsetFlowProgrammerService").setRequired(true));
-
             c.add(createContainerServiceDependency(containerName).setService(IClusterContainerServices.class)
                     .setCallbacks("setClusterContainerService", "unsetClusterContainerService").setRequired(true));
             c.add(createContainerServiceDependency(containerName).setService(ISwitchManager.class)
                     .setCallbacks("setSwitchManager", "unsetSwitchManager").setRequired(true));
             c.add(createContainerServiceDependency(containerName).setService(IForwardingRulesManagerAware.class)
                     .setCallbacks("setFrmAware", "unsetFrmAware").setRequired(false));
-            c.add(createContainerServiceDependency(containerName).setService(IfIptoHost.class)
-                    .setCallbacks("setHostFinder", "unsetHostFinder").setRequired(true));
             c.add(createContainerServiceDependency(containerName).setService(IContainer.class)
                     .setCallbacks("setIContainer", "unsetIContainer").setRequired(true));
         }
index 7fae181ba632c0aa51a26d96dccd93698d313eab..7634b8b1c37c9bae0d8218e9aac6009bd5c714d8 100644 (file)
@@ -45,7 +45,6 @@ import org.opendaylight.controller.forwardingrulesmanager.PortGroup;
 import org.opendaylight.controller.forwardingrulesmanager.PortGroupChangeListener;
 import org.opendaylight.controller.forwardingrulesmanager.PortGroupConfig;
 import org.opendaylight.controller.forwardingrulesmanager.PortGroupProvider;
-import org.opendaylight.controller.hosttracker.IfIptoHost;
 import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.ActionType;
 import org.opendaylight.controller.sal.action.Controller;
@@ -129,9 +128,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
      * contain all the flow entries which were installed on the global container
      * when the first container is created.
      */
-    private List<FlowEntry> inactiveFlows;
+    private ConcurrentMap<FlowEntry, FlowEntry> inactiveFlows;
 
-    private IfIptoHost hostFinder;
     private IContainer container;
     private Set<IForwardingRulesManagerAware> frmAware;
     private PortGroupProvider portGroupProvider;
@@ -744,13 +742,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
     @Override
     public Status installFlowEntry(FlowEntry flowEntry) {
         Status status;
-        if (inContainerMode) {
+        if (isContainerModeAllowed(flowEntry)) {
+            status = addEntry(flowEntry, false);
+        } else {
             String msg = "Controller in container mode: Install Refused";
             String logMsg = msg + ": {}";
             status = new Status(StatusCode.NOTACCEPTABLE, msg);
             log.warn(logMsg, flowEntry);
-        } else {
-            status = addEntry(flowEntry, false);
         }
         return status;
     }
@@ -758,26 +756,26 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
     @Override
     public Status installFlowEntryAsync(FlowEntry flowEntry) {
         Status status;
-        if (inContainerMode) {
+        if (isContainerModeAllowed(flowEntry)) {
+            status = addEntry(flowEntry, true);
+        } else {
             String msg = "Controller in container mode: Install Refused";
             status = new Status(StatusCode.NOTACCEPTABLE, msg);
             log.warn(msg);
-        } else {
-            status = addEntry(flowEntry, true);
         }
         return status;
     }
 
     @Override
-    public Status uninstallFlowEntry(FlowEntry entry) {
+    public Status uninstallFlowEntry(FlowEntry flowEntry) {
         Status status;
-        if (inContainerMode) {
+        if (isContainerModeAllowed(flowEntry)) {
+            status = removeEntry(flowEntry, false);
+        } else {
             String msg = "Controller in container mode: Uninstall Refused";
             String logMsg = msg + ": {}";
             status = new Status(StatusCode.NOTACCEPTABLE, msg);
-            log.warn(logMsg, entry);
-        } else {
-            status = removeEntry(entry, false);
+            log.warn(logMsg, flowEntry);
         }
         return status;
     }
@@ -785,12 +783,12 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
     @Override
     public Status uninstallFlowEntryAsync(FlowEntry flowEntry) {
         Status status;
-        if (inContainerMode) {
+        if (isContainerModeAllowed(flowEntry)) {
+            status = removeEntry(flowEntry, true);
+        } else {
             String msg = "Controller in container mode: Uninstall Refused";
             status = new Status(StatusCode.NOTACCEPTABLE, msg);
             log.warn(msg);
-        } else {
-            status = removeEntry(flowEntry, true);
         }
         return status;
     }
@@ -798,30 +796,53 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
     @Override
     public Status modifyFlowEntry(FlowEntry currentFlowEntry, FlowEntry newFlowEntry) {
         Status status = null;
-        if (inContainerMode) {
+        if (isContainerModeAllowed(currentFlowEntry)) {
+            status = modifyEntry(currentFlowEntry, newFlowEntry, false);
+        } else {
             String msg = "Controller in container mode: Modify Refused";
             String logMsg = msg + ": {}";
             status = new Status(StatusCode.NOTACCEPTABLE, msg);
             log.warn(logMsg, newFlowEntry);
-        } else {
-            status = modifyEntry(currentFlowEntry, newFlowEntry, false);
         }
         return status;
     }
 
     @Override
-    public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone) {
+    public Status modifyFlowEntryAsync(FlowEntry currentFlowEntry, FlowEntry newFlowEntry) {
         Status status = null;
-        if (inContainerMode) {
+        if (isContainerModeAllowed(currentFlowEntry)) {
+            status = modifyEntry(currentFlowEntry, newFlowEntry, true);
+        } else {
             String msg = "Controller in container mode: Modify Refused";
             status = new Status(StatusCode.NOTACCEPTABLE, msg);
             log.warn(msg);
-        } else {
-            status = modifyEntry(current, newone, true);
         }
         return status;
     }
 
+    /**
+     * Returns whether the specified flow entry is allowed to be
+     * installed/removed/modified based on the current container mode status.
+     * This call always returns true in the container instance of forwarding
+     * rules manager. It is meant for the global instance only (default
+     * container) of forwarding rules manager. Idea is that for assuring
+     * container isolation of traffic, flow installation in default container is
+     * blocked when in container mode (containers are present). The only flows
+     * that are allowed in container mode in the default container are the
+     * proactive flows, the ones automatically installed on the network node
+     * which forwarding mode has been configured to "proactive". These flows are
+     * needed by controller to discover the nodes topology and to discover the
+     * attached hosts for some SDN switches.
+     *
+     * @param flowEntry
+     *            The flow entry to be installed/removed/modified
+     * @return true if not in container mode or if flowEntry is internally
+     *         generated
+     */
+    private boolean isContainerModeAllowed(FlowEntry flowEntry) {
+        return (!inContainerMode) ? true : flowEntry.isInternal();
+    }
+
     @Override
     public Status modifyOrAddFlowEntry(FlowEntry newFlowEntry) {
         /*
@@ -867,8 +888,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
         if (groupName == null || groupName.isEmpty()) {
             return new Status(StatusCode.BADREQUEST, "Invalid group name");
         }
-        if (groupName.equals(FlowConfig.internalStaticFlowsGroup)) {
-            return new Status(StatusCode.BADREQUEST, "Static flows group cannot be deleted through this api");
+        if (groupName.equals(FlowConfig.INTERNALSTATICFLOWGROUP)) {
+            return new Status(StatusCode.BADREQUEST, "Internal static flows group cannot be deleted through this api");
         }
         if (inContainerMode) {
             String msg = "Controller in container mode: Group Uninstall Refused";
@@ -898,7 +919,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
         if (groupName == null || groupName.isEmpty()) {
             return new Status(StatusCode.BADREQUEST, "Invalid group name");
         }
-        if (groupName.equals(FlowConfig.internalStaticFlowsGroup)) {
+        if (groupName.equals(FlowConfig.INTERNALSTATICFLOWGROUP)) {
             return new Status(StatusCode.BADREQUEST, "Static flows group cannot be deleted through this api");
         }
         if (inContainerMode) {
@@ -947,7 +968,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
         }
     }
 
-    public void nonClusterObjectCreate() {
+    private void nonClusterObjectCreate() {
         originalSwView = new ConcurrentHashMap<FlowEntry, FlowEntry>();
         installedSwView = new ConcurrentHashMap<FlowEntryInstall, FlowEntryInstall>();
         nodeFlows = new ConcurrentHashMap<Node, List<FlowEntryInstall>>();
@@ -958,7 +979,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
         portGroupData = new ConcurrentHashMap<PortGroupConfig, Map<Node, PortGroup>>();
         staticFlows = new ConcurrentHashMap<Integer, FlowConfig>();
         flowsSaveEvent = new HashMap<Long, String>();
-        inactiveFlows = new ArrayList<FlowEntry>(1);
+        inactiveFlows = new ConcurrentHashMap<FlowEntry, FlowEntry>();
     }
 
     private void registerWithOSGIConsole() {
@@ -1145,6 +1166,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
             clusterContainerService.createCache("frm.installedSwView",
                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
 
+            clusterContainerService.createCache("frm.inactiveFlows",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+
             clusterContainerService.createCache("frm.nodeFlows",
                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
 
@@ -1182,6 +1206,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
 
         if (this.clusterContainerService == null) {
             log.warn("un-initialized clusterContainerService, can't retrieve cache");
+            nonClusterObjectCreate();
             return;
         }
 
@@ -1201,6 +1226,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
             log.error("Retrieval of frm.installedSwView cache failed for Container {}", container.getName());
         }
 
+        map = clusterContainerService.getCache("frm.inactiveFlows");
+        if (map != null) {
+            inactiveFlows = (ConcurrentMap<FlowEntry, FlowEntry>) map;
+        } else {
+            log.error("Retrieval of frm.inactiveFlows cache failed for Container {}", container.getName());
+        }
+
         map = clusterContainerService.getCache("frm.nodeFlows");
         if (map != null) {
             nodeFlows = (ConcurrentMap<Node, List<FlowEntryInstall>>) map;
@@ -1270,19 +1302,38 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
     }
 
     @Override
-    public Status addStaticFlow(FlowConfig config, boolean restore) {
-        boolean multipleFlowPush = false;
-        String error;
-        Status status;
-        config.setStatus(SUCCESS);
-
-        // Skip validation check if we are trying to restore a saved config
-        if (!restore && !(status = config.validate(container)).isSuccess()) {
+    public Status addStaticFlow(FlowConfig config) {
+        // Configuration object validation
+        Status status = config.validate(container);
+        if (!status.isSuccess()) {
             log.warn("Invalid Configuration for flow {}. The failure is {}", config, status.getDescription());
-            error = "Invalid Configuration (" + status.getDescription() + ")";
+            String error = "Invalid Configuration (" + status.getDescription() + ")";
             config.setStatus(error);
             return new Status(StatusCode.BADREQUEST, error);
         }
+        return addStaticFlowInternal(config, false);
+    }
+
+    /**
+     * Private method to add a static flow configuration which does not run any
+     * validation on the passed FlowConfig object. If restore is set to true,
+     * configuration is stored in configuration database regardless the
+     * installation on the network node was successful. This is useful at boot
+     * when static flows are present in startup configuration and are read
+     * before the switches connects.
+     *
+     * @param config
+     *            The static flow configuration
+     * @param restore
+     *            if true, the configuration is stored regardless the
+     *            installation on the network node was successful
+     * @return The status of this request
+     */
+    private Status addStaticFlowInternal(FlowConfig config, boolean restore) {
+        boolean multipleFlowPush = false;
+        String error;
+        Status status;
+        config.setStatus(SUCCESS);
 
         // Presence check
         if (flowConfigExists(config)) {
@@ -1639,12 +1690,12 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
             FlowEntryInstall flowEntries = mapEntry.getValue();
             // Skip internal generated static flows
             if (!flowEntries.isInternal()) {
-                inactiveFlows.add(flowEntries.getOriginal());
+                inactiveFlows.put(flowEntries.getOriginal(), null);
             }
         }
 
         // Now remove the entries
-        for (FlowEntry flowEntry : inactiveFlows) {
+        for (FlowEntry flowEntry : inactiveFlows.keySet()) {
             Status status = this.removeEntry(flowEntry, false);
             if (!status.isSuccess()) {
                 log.warn("Failed to remove entry: {}. The failure is: {}", flowEntry, status.getDescription());
@@ -1660,7 +1711,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
     private void reinstallAllFlowEntries() {
         log.info("Reinstalling all inactive flows");
 
-        for (FlowEntry flowEntry : this.inactiveFlows) {
+        for (FlowEntry flowEntry : this.inactiveFlows.keySet()) {
             this.addEntry(flowEntry, false);
         }
 
@@ -1756,7 +1807,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
         }
 
         for (FlowConfig conf : getStaticFlowsOrderedList(confList, maxKey)) {
-            addStaticFlow(conf, true);
+            addStaticFlowInternal(conf, true);
         }
     }
 
@@ -1816,13 +1867,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
 
         FlowConfig allowARP = new FlowConfig();
         allowARP.setInstallInHw(true);
-        allowARP.setName("**Punt ARP Reply");
+        allowARP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt ARP Reply" + FlowConfig.INTERNALSTATICFLOWEND);
         allowARP.setPriority("500");
         allowARP.setNode(node);
         allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase());
         allowARP.setDstMac(HexEncode.bytesToHexString(switchManager.getControllerMAC()));
         allowARP.setActions(puntAction);
-        addStaticFlow(allowARP, false);
+        addStaticFlowInternal(allowARP, true); // skip validation on internal static flow name
     }
 
     @Override
@@ -1834,7 +1885,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
 
         FlowConfig allowARP = new FlowConfig();
         allowARP.setInstallInHw(true);
-        allowARP.setName("**Punt ARP");
+        allowARP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt ARP" + FlowConfig.INTERNALSTATICFLOWEND);
         allowARP.setPriority("1");
         allowARP.setNode(node);
         allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase());
@@ -1843,7 +1894,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
 
         FlowConfig allowLLDP = new FlowConfig();
         allowLLDP.setInstallInHw(true);
-        allowLLDP.setName("**Punt LLDP");
+        allowLLDP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt LLDP" + FlowConfig.INTERNALSTATICFLOWEND);
         allowLLDP.setPriority("1");
         allowLLDP.setNode(node);
         allowLLDP.setEtherType("0x" + Integer.toHexString(EtherTypes.LLDP.intValue()).toUpperCase());
@@ -1855,21 +1906,21 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
 
         FlowConfig dropAllConfig = new FlowConfig();
         dropAllConfig.setInstallInHw(true);
-        dropAllConfig.setName("**Catch-All Drop");
+        dropAllConfig.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Catch-All Drop" + FlowConfig.INTERNALSTATICFLOWEND);
         dropAllConfig.setPriority("0");
         dropAllConfig.setNode(node);
         dropAllConfig.setActions(dropAction);
         defaultConfigs.add(dropAllConfig);
 
+        log.info("Forwarding mode for node {} set to {}", node, (proactive ? "proactive" : "reactive"));
         for (FlowConfig fc : defaultConfigs) {
-            if (proactive) {
-                addStaticFlow(fc, false);
+            Status status = (proactive) ? addStaticFlowInternal(fc, true) : removeStaticFlow(fc);
+            if (status.isSuccess()) {
+                log.info("{} Proactive Static flow: {}", (proactive ? "Installed" : "Removed"), fc.getName());
             } else {
-                removeStaticFlow(fc);
+                log.warn("Failed to {} Proactive Static flow: {}", (proactive ? "install" : "remove"), fc.getName());
             }
         }
-
-        log.info("Set Switch {} Mode to {}", node, (proactive ? "proactive" : "reactive"));
     }
 
     /**
@@ -1915,7 +1966,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
             if ((staticFlow.getNode().equals(node)) && (staticFlow.getPortGroup().equals(config.getName()))) {
                 for (Short port : data.getPorts()) {
                     FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, config.getName(), port);
-                    addStaticFlow(derivedFlow, false);
+                    addStaticFlowInternal(derivedFlow, false);
                 }
             }
         }
@@ -2053,16 +2104,6 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
         }
     }
 
-    public void setHostFinder(IfIptoHost hostFinder) {
-        this.hostFinder = hostFinder;
-    }
-
-    public void unsetHostFinder(IfIptoHost hostFinder) {
-        if (this.hostFinder == hostFinder) {
-            this.hostFinder = null;
-        }
-    }
-
     public void setFrmAware(IForwardingRulesManagerAware obj) {
         this.frmAware.add(obj);
     }
@@ -2106,8 +2147,6 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
             portGroupProvider.registerPortGroupChange(this);
         }
 
-        nonClusterObjectCreate();
-
         cacheStartup();
 
         registerWithOSGIConsole();
@@ -2228,8 +2267,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
     }
 
     @Override
-    public void containerFlowUpdated(String containerName, ContainerFlow previous, ContainerFlow current,
-            UpdateType t) {
+    public void containerFlowUpdated(String containerName, ContainerFlow previous, ContainerFlow current, UpdateType t) {
         if (!container.getName().equals(containerName)) {
             return;
         }
@@ -2501,7 +2539,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Port
         log.trace("Received flow removed notification on {} for {}", node, flow);
 
         // For flow entry identification, only node, match and priority matter
-        FlowEntryInstall test = new FlowEntryInstall(new FlowEntry("","",flow, node), null);
+        FlowEntryInstall test = new FlowEntryInstall(new FlowEntry("", "", flow, node), null);
         FlowEntryInstall installedEntry = this.installedSwView.get(test);
         if (installedEntry == null) {
             log.trace("Entry is not known to us");
index b419a9b29df1c25f5d044a279a085126457230f5..d3cbc4aceed0ad88a887d3a870a7d184b35a85df 100644 (file)
@@ -321,7 +321,7 @@ public class FlowProgrammerNorthbound {
                     + RestMessages.RESOURCECONFLICT.toString());
         }
 
-        Status status = frm.addStaticFlow(flowConfig.getValue(), false);
+        Status status = frm.addStaticFlow(flowConfig.getValue());
         if (status.isSuccess()) {
             return Response.status(Response.Status.CREATED).build();
         }
index a93a8b7243cede7e2d81d212160dbe7a97806539..54c61b89abc7b951076741b5cf37e8e3c9f3cd79 100644 (file)
@@ -143,7 +143,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
             c.setInterface(IPluginInDataPacketService.class.getName(), props);
             // Hook the services coming in from SAL, as optional in
             // case SAL is not yet there, could happen
@@ -167,7 +167,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
             c.setInterface(IPluginInReadService.class.getName(), props);
             c.add(createServiceDependency()
                     .setService(IPluginReadServiceFilter.class)
@@ -180,7 +180,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
             c.setInterface(IFlowProgrammerNotifier.class.getName(), props);
 
             c.add(createContainerServiceDependency(containerName)
@@ -233,7 +233,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
             c.setInterface(
                     new String[] {
                             IPluginInFlowProgrammerService.class.getName(),
index 614e70b1b859b0e23c7500549f776dd961558d53..76c38664d4d44adde2e799d1f5ff595702aa0c67 100644 (file)
@@ -90,7 +90,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", "STUB");
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
             c.setInterface(IPluginInReadService.class.getName(), props);
         }
 
@@ -99,7 +99,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", "STUB");
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
             c.setInterface(IPluginInInventoryService.class.getName(), props);
         }
     }
@@ -115,7 +115,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", "STUB");
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
             c.setInterface(IPluginInFlowProgrammerService.class.getName(), props);
         }
         if (imp.equals(StubNodeFactory.class)) {
@@ -123,7 +123,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", "STUB");
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
             props.put("protocolName", "STUB");
             c.setInterface(INodeFactory.class.getName(), props);
         }
@@ -132,7 +132,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             // Set the protocolPluginType property which will be used
             // by SAL
-            props.put("protocolPluginType", "STUB");
+            props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
             props.put("protocolName", "STUB");
             c.setInterface(INodeConnectorFactory.class.getName(), props);
         }
index 0ebf633c55c123b742f8ba5365905f372f328b02..174f2546bad1039f87352b5e0a8bd129ad383732 100644 (file)
@@ -19,7 +19,8 @@ public enum GlobalConstants {
     CONTAINERNAME("name"),
     STATICVLAN("staticvlan"),
     CLUSTERINGSERVICES("clusteringservices"),
-    STARTUPHOME("configuration/startup/");
+    STARTUPHOME("configuration/startup/"),
+    PROTOCOLPLUGINTYPE("protocolPluginType");
 
     private GlobalConstants(String name) {
         this.name = name;
index 41e4d2a7fcb30247bdb9a95c5f8c014bfd69389a..b56a96e50cb8acc844f3419276bc4140a1ca34a0 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.sal.implementation.internal;
 
+import org.apache.felix.dm.Component;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
 import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
 import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
@@ -29,7 +30,6 @@ import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
 import org.opendaylight.controller.sal.topology.ITopologyService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.felix.dm.Component;
 
 public class Activator extends ComponentActivatorAbstractBase {
     protected static final Logger logger = LoggerFactory
@@ -40,6 +40,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      * are done by the ComponentActivatorAbstractBase.
      *
      */
+    @Override
     public void init() {
 
     }
@@ -49,6 +50,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      * ComponentActivatorAbstractBase
      *
      */
+    @Override
     public void destroy() {
 
     }
@@ -62,6 +64,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      *         instantiated in order to get an fully working implementation
      *         Object
      */
+    @Override
     public Object[] getImplementations() {
         Object[] res = { Topology.class, Inventory.class,
                 FlowProgrammerService.class, ReadService.class,
@@ -84,6 +87,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      *            per-container different behavior if needed, usually should not
      *            be the case though.
      */
+    @Override
     public void configureInstance(Component c, Object imp, String containerName) {
         if (imp.equals(Topology.class)) {
             // export the service for Apps and Plugins
@@ -121,7 +125,7 @@ public class Activator extends ComponentActivatorAbstractBase {
             c.add(createContainerServiceDependency(containerName)
                     .setService(IPluginInInventoryService.class)
                     .setCallbacks("setPluginService", "unsetPluginService")
-                    .setRequired(true));
+                    .setRequired(false));
         }
 
         if (imp.equals(FlowProgrammerService.class)) {
@@ -134,7 +138,7 @@ public class Activator extends ComponentActivatorAbstractBase {
                     .setService(IPluginInFlowProgrammerService.class)
                     .setCallbacks("setService", "unsetService")
                     .setRequired(false));
-            c.add(createServiceDependency()
+            c.add(createContainerServiceDependency(containerName)
                     .setService(IFlowProgrammerListener.class)
                     .setCallbacks("setListener", "unsetListener")
                     .setRequired(false));
index a9eefd3a8a689d8b4d92bd76fc4ec0edf1198193..eef43592341d69a68cc9b0f2780fef3e695856b4 100644 (file)
@@ -40,6 +40,7 @@ import org.opendaylight.controller.sal.packet.LinkEncap;
 import org.opendaylight.controller.sal.packet.Packet;
 import org.opendaylight.controller.sal.packet.PacketResult;
 import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.NetUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -217,7 +218,7 @@ public class DataPacketService implements IPluginOutDataPacketService,
             logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
         }
 
-        Object value = props.get("protocolPluginType");
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
         if (value instanceof String) {
             type = (String) value;
         }
@@ -243,7 +244,7 @@ public class DataPacketService implements IPluginOutDataPacketService,
             logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
         }
 
-        Object value = props.get("protocoloPluginType");
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
         if (value instanceof String) {
             type = (String) value;
         }
index d6feebd4a3067a057af0a7991dcf82613f2f5995..369588c0c4169eb74dd0ca38fd58d3a6b1d95bc1 100644 (file)
@@ -38,6 +38,7 @@ import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerSe
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IPProtocols;
 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
 import org.opendaylight.controller.sal.utils.Status;
@@ -129,7 +130,7 @@ public class FlowProgrammerService implements IFlowProgrammerService,
                     entry.getValue());
         }
 
-        Object value = props.get("protocolPluginType");
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
         if (value instanceof String) {
             type = (String) value;
         }
@@ -156,7 +157,7 @@ public class FlowProgrammerService implements IFlowProgrammerService,
                     entry.getValue());
         }
 
-        Object value = props.get("protocoloPluginType");
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
         if (value instanceof String) {
             type = (String) value;
         }
index fce0a39719234a58e1d37c98b5d84d3ae67fe6d7..edc91173890970b12680fa27628fe378a9ba1490 100644 (file)
@@ -38,6 +38,7 @@ import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
 import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
 import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IPProtocols;
 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
 import org.opendaylight.controller.sal.utils.NodeCreator;
@@ -116,7 +117,7 @@ public class ReadService implements IReadService, CommandProvider {
                     entry.getValue());
         }
 
-        Object value = props.get("protocolPluginType");
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
         if (value instanceof String) {
             type = (String) value;
         }
@@ -143,7 +144,7 @@ public class ReadService implements IReadService, CommandProvider {
                     entry.getValue());
         }
 
-        Object value = props.get("protocoloPluginType");
+        Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
         if (value instanceof String) {
             type = (String) value;
         }
index 29a78ab0a804c05d6557ac9eff03b9f5bfeb59c6..4dadc5da3c32d6134ab221590068b3e0329b0766 100644 (file)
@@ -19,8 +19,8 @@ import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
 import org.opendaylight.controller.sal.binding.generator.impl.BindingGeneratorImpl;
-import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
 import org.opendaylight.controller.sal.binding.model.api.Enumeration;
+import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
 import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
 import org.opendaylight.controller.sal.binding.model.api.Type;
 import org.opendaylight.controller.sal.java.api.generator.GeneratorJavaFile;
@@ -30,28 +30,30 @@ import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
 
 public final class CodeGeneratorImpl implements CodeGenerator {
 
-       @Override
-       public Collection<File> generateSources(SchemaContext context,
-            File outputBaseDir, Set<Module> yangModules) throws IOException {
+    @Override
+    public Collection<File> generateSources(SchemaContext context, File outputBaseDir, Set<Module> yangModules)
+            throws IOException {
+        if (outputBaseDir == null) {
+            outputBaseDir = new File("target" + File.separator + "generated-sources" + File.separator + "maven-sal-api-gen");
+        }
 
-               final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
-               final List<Type> types = bindingGenerator.generateTypes(context,yangModules);
-               final Set<GeneratedType> typesToGenerate = new HashSet<>();
-               final Set<GeneratedTransferObject> tosToGenerate = new HashSet<>();
-               final Set<Enumeration> enumsToGenerate = new HashSet<>();
+        final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
+        final List<Type> types = bindingGenerator.generateTypes(context, yangModules);
+        final Set<GeneratedType> typesToGenerate = new HashSet<>();
+        final Set<GeneratedTransferObject> tosToGenerate = new HashSet<>();
+        final Set<Enumeration> enumsToGenerate = new HashSet<>();
 
-               for (Type type : types) {
-                       if (type instanceof GeneratedTransferObject) {
-                               tosToGenerate.add((GeneratedTransferObject) type);
-                       } else if (type instanceof GeneratedType) {
-                               typesToGenerate.add((GeneratedType) type);
-                       } else if (type instanceof Enumeration) {
-                               enumsToGenerate.add((Enumeration) type);
-                       }
+        for (Type type : types) {
+            if (type instanceof GeneratedTransferObject) {
+                tosToGenerate.add((GeneratedTransferObject) type);
+            } else if (type instanceof GeneratedType) {
+                typesToGenerate.add((GeneratedType) type);
+            } else if (type instanceof Enumeration) {
+                enumsToGenerate.add((Enumeration) type);
+            }
         }
 
-        final GeneratorJavaFile generator = new GeneratorJavaFile(
-                               typesToGenerate, tosToGenerate, enumsToGenerate);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(typesToGenerate, tosToGenerate, enumsToGenerate);
 
         return generator.generateToFile(outputBaseDir);
     }
@@ -75,6 +77,6 @@ public final class CodeGeneratorImpl implements CodeGenerator {
     @Override
     public void setMavenProject(MavenProject project) {
         // no additional information needed
-       }
+    }
 
 }
index 9532d4efc9f92a4fbabe32e6ab11b79665e81e37..bbece72fd32ce54b69bba5c757c00e5aeb31e285 100644 (file)
@@ -49,8 +49,7 @@ public class YangToSourcesPluginTestIT {
         v.verifyTextInLog("[DEBUG] yang-to-sources: Additional configuration picked up for : org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: {nm1=abcd=a.b.c.d, nm2=abcd2=a.b.c.d.2}");
         v.verifyTextInLog("[DEBUG] yang-to-sources: Additional configuration picked up for : org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: {c1=config}");
         v.verifyTextInLog(File.separator
-                + "files marked as resources: META-INF" + File.separator
-                + "yang");
+                + "files marked as resources: META-INF/yang");
         v.verifyTextInLog("target"
                 + File.separator
                 + "generated-resources marked as resources for generator: org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl");
index 0df9a6345ee9384b316f3d71093fa19a9796a658..88f4dde31a538a567cfe7ed5199a4fae5776a8e8 100644 (file)
@@ -23,10 +23,13 @@ public abstract class ConfigArg {
     private final File outputBaseDir;
 
     public ConfigArg(String outputBaseDir) {
-        this.outputBaseDir = new File(outputBaseDir);
+        this.outputBaseDir = outputBaseDir == null ? null : new File(outputBaseDir);
     }
 
     public File getOutputBaseDir(MavenProject project) {
+        if (outputBaseDir == null) {
+            return null;
+        }
         if (outputBaseDir.isAbsolute()) {
             return outputBaseDir;
         } else {
@@ -40,21 +43,19 @@ public abstract class ConfigArg {
      * Configuration argument for code generator class and output directory.
      */
     public static final class CodeGeneratorArg extends ConfigArg {
-        private static final String CODE_GEN_DEFAULT_DIR = "target"
-                + File.separator + "generated-sources";
-        private static final String CODE_GEN_DEFAULT_RESOURCE_DIR = "target"
-                + File.separator + "generated-resources";
+        private static final String CODE_GEN_DEFAULT_RESOURCE_DIR = "target" + File.separator + "generated-resources";
+
         private String codeGeneratorClass;
         private File resourceBaseDir = new File(CODE_GEN_DEFAULT_RESOURCE_DIR);
 
         private Map<String, String> additionalConfiguration = Maps.newHashMap();
 
         public CodeGeneratorArg() {
-            super(CODE_GEN_DEFAULT_DIR);
+            super(null);
         }
 
         public CodeGeneratorArg(String codeGeneratorClass) {
-            this(codeGeneratorClass, CODE_GEN_DEFAULT_DIR);
+            this(codeGeneratorClass, null);
         }
 
         public CodeGeneratorArg(String codeGeneratorClass, String outputBaseDir) {
@@ -62,8 +63,7 @@ public abstract class ConfigArg {
             this.codeGeneratorClass = codeGeneratorClass;
         }
 
-        public CodeGeneratorArg(String codeGeneratorClass,
-                String outputBaseDir, String resourceBaseDir) {
+        public CodeGeneratorArg(String codeGeneratorClass, String outputBaseDir, String resourceBaseDir) {
             super(outputBaseDir);
             this.codeGeneratorClass = codeGeneratorClass;
             this.resourceBaseDir = new File(resourceBaseDir);
@@ -71,8 +71,7 @@ public abstract class ConfigArg {
 
         @Override
         public void check() {
-            Preconditions.checkNotNull(codeGeneratorClass,
-                    "codeGeneratorClass for CodeGenerator cannot be null");
+            Preconditions.checkNotNull(codeGeneratorClass, "codeGeneratorClass for CodeGenerator cannot be null");
         }
 
         public String getCodeGeneratorClass() {
index a7b7f429ccbffbd9bf4f4593094989446914105f..b781d72311e19a8a9372ce49c64fa9e254ef9827 100644 (file)
@@ -144,11 +144,11 @@ class YangToSourcesProcessor {
                 throw new MojoFailureException(message, e);
             }
 
-            setResource(targetYangDir, META_INF_YANG_DIR.getPath(), project);
+            setResource(targetYangDir, META_INF_YANG_STRING_JAR, project);
 
             log.debug(Util.message(
                     "Yang files from: %s marked as resources: %s", LOG_PREFIX,
-                    yangFilesRootDir, META_INF_YANG_DIR.getPath()));
+                    yangFilesRootDir, META_INF_YANG_STRING_JAR));
         }
 
         private static void setResource(File targetYangDir, String targetPath,
@@ -220,7 +220,9 @@ class YangToSourcesProcessor {
                 codeGeneratorCfg.getCodeGeneratorClass(),
                 codeGeneratorCfg.getAdditionalConfiguration()));
 
-        project.addCompileSourceRoot(outputDir.getAbsolutePath());
+        if(outputDir != null) {
+            project.addCompileSourceRoot(outputDir.getAbsolutePath());
+        }
         g.setLog(log);
         g.setMavenProject(project);
         g.setAdditionalConfig(codeGeneratorCfg.getAdditionalConfiguration());
index 6e804a199d3a829646cfa951120910543128d9c5..091bfc72337e8037a1d823f81f352990d00126ec 100644 (file)
@@ -7,12 +7,14 @@
  */
 package org.opendaylight.controller.yang.parser.builder.api;
 
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
 
 public abstract class AbstractDataNodeContainerBuilder implements DataNodeContainerBuilder {
     protected final int line;
@@ -52,6 +54,9 @@ public abstract class AbstractDataNodeContainerBuilder implements DataNodeContai
 
     @Override
     public Set<DataSchemaNode> getChildNodes() {
+        if (childNodes == null) {
+            return Collections.emptySet();
+        }
         return childNodes;
     }
 
@@ -65,12 +70,30 @@ public abstract class AbstractDataNodeContainerBuilder implements DataNodeContai
     }
 
     @Override
-    public void addChildNode(DataSchemaNodeBuilder childNode) {
-        addedChildNodes.add(childNode);
+    public DataSchemaNodeBuilder getDataChildByName(final String name) {
+        for (DataSchemaNodeBuilder child : addedChildNodes) {
+            if (child.getQName().getLocalName().equals(name)) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void addChildNode(DataSchemaNodeBuilder child) {
+        for (DataSchemaNodeBuilder childNode : addedChildNodes) {
+            if (childNode.getQName().getLocalName().equals(child.getQName().getLocalName())) {
+                throw new YangParseException(child.getLine(), "Duplicate node found at line " + childNode.getLine());
+            }
+        }
+        addedChildNodes.add(child);
     }
 
     @Override
     public Set<GroupingDefinition> getGroupings() {
+        if (groupings == null) {
+            return Collections.emptySet();
+        }
         return groupings;
     }
 
@@ -83,8 +106,13 @@ public abstract class AbstractDataNodeContainerBuilder implements DataNodeContai
     }
 
     @Override
-    public void addGrouping(GroupingBuilder grouping) {
-        addedGroupings.add(grouping);
+    public void addGrouping(GroupingBuilder groupingBuilder) {
+        for (GroupingBuilder gb : addedGroupings) {
+            if (gb.getQName().getLocalName().equals(groupingBuilder.getQName().getLocalName())) {
+                throw new YangParseException(groupingBuilder.getLine(), "Duplicate node found at line " + gb.getLine());
+            }
+        }
+        addedGroupings.add(groupingBuilder);
     }
 
 }
index 1963c6cd36d26ea812f84e266089298b67f4b0e0..8659cac1fa4d4c09853769cb3f08215880d3b75e 100644 (file)
@@ -13,6 +13,7 @@ import java.util.List;
 import org.opendaylight.controller.yang.common.QName;\r
 import org.opendaylight.controller.yang.model.api.SchemaPath;\r
 import org.opendaylight.controller.yang.model.api.Status;\r
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;\r
 \r
 /**\r
@@ -26,6 +27,7 @@ public abstract class AbstractSchemaNodeBuilder implements SchemaNodeBuilder {
     protected String description;\r
     protected String reference;\r
     protected Status status = Status.CURRENT;\r
+    protected List<UnknownSchemaNode> unknownNodes;\r
     protected final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();\r
 \r
     protected AbstractSchemaNodeBuilder(final int line, final QName qname) {\r
@@ -52,34 +54,42 @@ public abstract class AbstractSchemaNodeBuilder implements SchemaNodeBuilder {
         this.parent = parent;\r
     }\r
 \r
+    @Override\r
     public SchemaPath getPath() {\r
         return schemaPath;\r
     }\r
 \r
+    @Override\r
     public void setPath(SchemaPath schemaPath) {\r
         this.schemaPath = schemaPath;\r
     }\r
 \r
+    @Override\r
     public String getDescription() {\r
         return description;\r
     }\r
 \r
+    @Override\r
     public void setDescription(String description) {\r
         this.description = description;\r
     }\r
 \r
+    @Override\r
     public String getReference() {\r
         return reference;\r
     }\r
 \r
+    @Override\r
     public void setReference(String reference) {\r
         this.reference = reference;\r
     }\r
 \r
+    @Override\r
     public Status getStatus() {\r
         return status;\r
     }\r
 \r
+    @Override\r
     public void setStatus(Status status) {\r
         if (status != null) {\r
             this.status = status;\r
@@ -91,4 +101,8 @@ public abstract class AbstractSchemaNodeBuilder implements SchemaNodeBuilder {
         addedUnknownNodes.add(unknownNode);\r
     }\r
 \r
+    public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {\r
+        this.unknownNodes = unknownNodes;\r
+    }\r
+\r
 }\r
index 13b7e4874e533b0290b09592950b86a3d19e4c59..4271776d63f4bca6dd11d5f1cff262abdfeebb55 100644 (file)
@@ -28,6 +28,8 @@ public interface DataNodeContainerBuilder extends Builder {
 
     Set<DataSchemaNodeBuilder> getChildNodeBuilders();
 
+    DataSchemaNodeBuilder getDataChildByName(String name);
+
     void addChildNode(DataSchemaNodeBuilder childNode);
 
     Set<GroupingDefinition> getGroupings();
index dd8906025da492ed53c481471e0cc86256b49fb8..a2dacc24a401491717cf64bee9ad303140ab5aa7 100644 (file)
@@ -28,7 +28,6 @@ public final class AnyXmlBuilder extends AbstractSchemaNodeBuilder implements Da
     private boolean built;
     private final AnyXmlSchemaNodeImpl instance;
     private final ConstraintsBuilder constraints;
-    private List<UnknownSchemaNode> unknownNodes;
 
     private Boolean configuration;
     private boolean augmenting;
@@ -93,10 +92,6 @@ public final class AnyXmlBuilder extends AbstractSchemaNodeBuilder implements Da
         return addedUnknownNodes;
     }
 
-    public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {
-        this.unknownNodes = unknownNodes;
-    }
-
     @Override
     public boolean isAugmenting() {
         return augmenting;
index b534ba4f6013bb91056e30e1294486ec5b3e5086..7fcee2ef52aff579ce707673d31c8c34171482bc 100644 (file)
@@ -27,21 +27,20 @@ import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.model.api.UsesNode;
 import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
-import org.opendaylight.controller.yang.parser.builder.api.Builder;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
 import org.opendaylight.controller.yang.parser.util.Comparators;
-import org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
-public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBuilder {
+public final class AugmentationSchemaBuilderImpl extends AbstractDataNodeContainerBuilder implements
+        AugmentationSchemaBuilder {
     private boolean built;
     private final AugmentationSchemaImpl instance;
-    private final int line;
-    private Builder parent;
 
     private String whenCondition;
     private String description;
@@ -52,50 +51,18 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
     private SchemaPath dirtyAugmentTarget;
     private SchemaPath finalAugmentTarget;
 
-    private final Set<DataSchemaNodeBuilder> childNodes = new HashSet<DataSchemaNodeBuilder>();
-    private final Set<GroupingBuilder> groupings = new HashSet<GroupingBuilder>();
     private final Set<UsesNodeBuilder> usesNodes = new HashSet<UsesNodeBuilder>();
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
     private boolean resolved;
 
     AugmentationSchemaBuilderImpl(final int line, final String augmentTargetStr) {
+        super(line, null);
         this.augmentTargetStr = augmentTargetStr;
-        this.line = line;
-        final SchemaPath targetPath = YangModelBuilderUtil.parseAugmentPath(augmentTargetStr);
+        final SchemaPath targetPath = ParserListenerUtils.parseAugmentPath(augmentTargetStr);
         dirtyAugmentTarget = targetPath;
         instance = new AugmentationSchemaImpl(targetPath);
     }
 
-    @Override
-    public int getLine() {
-        return line;
-    }
-
-    @Override
-    public Builder getParent() {
-        return parent;
-    }
-
-    @Override
-    public void setParent(final Builder parent) {
-        this.parent = parent;
-    }
-
-    @Override
-    public void addChildNode(DataSchemaNodeBuilder childNode) {
-        childNodes.add(childNode);
-    }
-
-    @Override
-    public Set<DataSchemaNode> getChildNodes() {
-        return Collections.emptySet();
-    }
-
-    @Override
-    public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
-        return childNodes;
-    }
-
     @Override
     public Set<GroupingDefinition> getGroupings() {
         return Collections.emptySet();
@@ -103,12 +70,12 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
 
     @Override
     public Set<GroupingBuilder> getGroupingBuilders() {
-        return groupings;
+        return Collections.emptySet();
     }
 
     @Override
     public void addGrouping(GroupingBuilder grouping) {
-        groupings.add(grouping);
+        throw new YangParseException(line, "augment can not contains grouping statement");
     }
 
     @Override
@@ -116,14 +83,6 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
         usesNodes.add(usesBuilder);
     }
 
-    /**
-     * Always returns null.
-     */
-    @Override
-    public QName getQName() {
-        return null;
-    }
-
     /**
      * Always returns null.
      */
@@ -150,19 +109,11 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
 
             // CHILD NODES
             final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
-            for (DataSchemaNodeBuilder node : childNodes) {
+            for (DataSchemaNodeBuilder node : addedChildNodes) {
                 childs.put(node.getQName(), node.build());
             }
             instance.setChildNodes(childs);
 
-            // GROUPINGS
-            final Set<GroupingDefinition> groupingDefinitions = new TreeSet<GroupingDefinition>(
-                    Comparators.SCHEMA_NODE_COMP);
-            for (GroupingBuilder builder : groupings) {
-                groupingDefinitions.add(builder.build());
-            }
-            instance.setGroupings(groupingDefinitions);
-
             // USES
             final Set<UsesNode> usesNodeDefinitions = new HashSet<UsesNode>();
             for (UsesNodeBuilder builder : usesNodes) {
@@ -306,7 +257,6 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
         private SchemaPath targetPath;
         private RevisionAwareXPath whenCondition;
         private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
-        private Set<GroupingDefinition> groupings = Collections.emptySet();
         private Set<UsesNode> uses = Collections.emptySet();
         private String description;
         private String reference;
@@ -348,15 +298,13 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
             }
         }
 
+        /**
+         * Always returns an empty set, because augment can not contains
+         * grouping statement.
+         */
         @Override
         public Set<GroupingDefinition> getGroupings() {
-            return groupings;
-        }
-
-        private void setGroupings(Set<GroupingDefinition> groupings) {
-            if (groupings != null) {
-                this.groupings = groupings;
-            }
+            return Collections.emptySet();
         }
 
         @Override
@@ -371,8 +319,8 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu
         }
 
         /**
-         * Always returns an empty set, because augmentation can not contains
-         * type definitions.
+         * Always returns an empty set, because augment can not contains type
+         * definitions.
          */
         @Override
         public Set<TypeDefinition<?>> getTypeDefinitions() {
index 01acc11f239daea34b9eb01e3a0634d2a5ef3cf4..7ed47bf4239e7558eaf0e258713f36e5e74939d1 100644 (file)
@@ -35,8 +35,6 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
         AugmentationTargetBuilder, GroupingMember, ConfigNode {
     private boolean isBuilt;
     private final ChoiceNodeImpl instance;
-    // SchemaNode args
-    private List<UnknownSchemaNode> unknownNodes;
     // DataSchemaNode args
     private boolean augmenting;
     private boolean addedByUses;
@@ -197,10 +195,6 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da
         return addedUnknownNodes;
     }
 
-    public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {
-        this.unknownNodes = unknownNodes;
-    }
-
     public String getDefaultCase() {
         return defaultCase;
     }
index 9b52d61c88085e822a780f569e97be05003f1ed9..afc0e3b4fd2701b530ab541a6b1f5133b9de4296 100644 (file)
@@ -17,31 +17,48 @@ import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.parser.builder.api.Builder;
 import org.opendaylight.controller.yang.parser.util.Comparators;
-import org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
 public final class DeviationBuilder implements Builder {
     private final int line;
     private Builder parent;
+    private boolean isBuilt;
     private final DeviationImpl instance;
+
+    private SchemaPath targetPath;
+    private String reference;
     private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
 
-    DeviationBuilder(final String targetPathStr, final int line) {
+    DeviationBuilder(final int line, final String targetPathStr) {
+        if(!targetPathStr.startsWith("/")) {
+            throw new YangParseException(line, "Deviation argument string must be an absolute schema node identifier.");
+        }
         this.line = line;
-        final SchemaPath targetPath = YangModelBuilderUtil
-                .parseAugmentPath(targetPathStr);
-        instance = new DeviationImpl(targetPath);
+        this.targetPath = ParserListenerUtils.parseAugmentPath(targetPathStr);
+        instance = new DeviationImpl();
     }
 
     @Override
     public Deviation build() {
-        // UNKNOWN NODES
-        List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
-        for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
-            unknownNodes.add(b.build());
+        if(targetPath == null) {
+            throw new YangParseException(line, "Unresolved deviation target");
+        }
+
+        if(!isBuilt) {
+            instance.setTargetPath(targetPath);
+            instance.setReference(reference);
+
+            // UNKNOWN NODES
+            List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+            for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+                unknownNodes.add(b.build());
+            }
+            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+            instance.setUnknownSchemaNodes(unknownNodes);
+
+            isBuilt = true;
         }
-        Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
-        instance.setUnknownSchemaNodes(unknownNodes);
 
         return instance;
     }
@@ -66,6 +83,14 @@ public final class DeviationBuilder implements Builder {
         addedUnknownNodes.add(unknownNode);
     }
 
+    public SchemaPath getTargetPath() {
+        return targetPath;
+    }
+
+    public void setTargetPath(final SchemaPath targetPath) {
+        this.targetPath = targetPath;
+    }
+
     public void setDeviate(final String deviate) {
         if ("not-supported".equals(deviate)) {
             instance.setDeviate(Deviate.NOT_SUPPORTED);
@@ -82,17 +107,16 @@ public final class DeviationBuilder implements Builder {
     }
 
     public void setReference(final String reference) {
-        instance.setReference(reference);
+        this.reference = reference;
     }
 
     private final class DeviationImpl implements Deviation {
-        private final SchemaPath targetPath;
+        private SchemaPath targetPath;
         private Deviate deviate;
         private String reference;
         private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
 
-        private DeviationImpl(final SchemaPath targetPath) {
-            this.targetPath = targetPath;
+        private DeviationImpl() {
         }
 
         @Override
@@ -100,6 +124,10 @@ public final class DeviationBuilder implements Builder {
             return targetPath;
         }
 
+        private void setTargetPath(final SchemaPath targetPath) {
+            this.targetPath = targetPath;
+        }
+
         @Override
         public Deviate getDeviate() {
             return deviate;
@@ -118,6 +146,7 @@ public final class DeviationBuilder implements Builder {
             this.reference = reference;
         }
 
+        @Override
         public List<UnknownSchemaNode> getUnknownSchemaNodes() {
             return unknownNodes;
         }
index a0ee47f7b8d13a7fc7540e4480fac53f7c48abeb..764d2bf8dba0b445bdb95978d562653b68a0584e 100644 (file)
@@ -37,11 +37,13 @@ public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
             instance.setStatus(status);
 
             // UNKNOWN NODES
-            final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
-            for (UnknownSchemaNodeBuilder un : addedUnknownNodes) {
-                unknownNodes.add(un.build());
+            if (unknownNodes == null) {
+                unknownNodes = new ArrayList<UnknownSchemaNode>();
+                for (UnknownSchemaNodeBuilder un : addedUnknownNodes) {
+                    unknownNodes.add(un.build());
+                }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
-            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
index c5dd60a79042d576b1de82684a9045f4aa802b4e..4d5ce9703f052d36dbd80b36de91774ac539d538 100644 (file)
@@ -37,11 +37,13 @@ public final class FeatureBuilder extends AbstractSchemaNodeBuilder {
             instance.setStatus(status);
 
             // UNKNOWN NODES
-            final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
-            for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
-                unknownNodes.add(b.build());
+            if (unknownNodes == null) {
+                unknownNodes = new ArrayList<UnknownSchemaNode>();
+                for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+                    unknownNodes.add(b.build());
+                }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
-            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
index 0f7179e791eeb761cf1b7528e94a96728eff348c..0099b4f54b0d8b44a882d496039f04436190b424 100644 (file)
@@ -258,6 +258,16 @@ public final class GroupingBuilderImpl implements GroupingBuilder {
         return addedChildNodes;
     }
 
+    @Override
+    public DataSchemaNodeBuilder getDataChildByName(final String name) {
+        for(DataSchemaNodeBuilder child : addedChildNodes) {
+            if(child.getQName().getLocalName().equals(name)) {
+                return child;
+            }
+        }
+        return null;
+    }
+
     public void setChildNodes(final Set<DataSchemaNode> childNodes) {
         this.childNodes = childNodes;
     }
index 14fca7d250cb4cf9300fcb0d4d4757156762d0ef..96b4bd4dd89826176af584cce712f47504a9b8ee 100644 (file)
@@ -48,11 +48,13 @@ public final class IdentitySchemaNodeBuilder extends AbstractSchemaNodeBuilder {
             }
 
             // UNKNOWN NODES
-            final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
-            for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
-                unknownNodes.add(b.build());
+            if (unknownNodes == null) {
+                unknownNodes = new ArrayList<UnknownSchemaNode>();
+                for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+                    unknownNodes.add(b.build());
+                }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
-            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
index 57e87b33ad855bb345bcd0cf5d1459ac8304ca62..47f1fbc2f16dee262e7117b7f0d6f7da1dbf77b8 100644 (file)
@@ -11,7 +11,6 @@ import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -37,6 +36,7 @@ import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.Builder;
 import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
@@ -51,11 +51,11 @@ import org.opendaylight.controller.yang.parser.util.RefineHolder;
 import org.opendaylight.controller.yang.parser.util.YangParseException;
 
 /**
- * This builder builds Module object. If this module is dependent on external
+ * Builder of Module object. If this module is dependent on external
  * module/modules, these dependencies must be resolved before module is built,
  * otherwise result may not be valid.
  */
-public class ModuleBuilder implements DataNodeContainerBuilder {
+public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
     private final ModuleImpl instance;
     private final String name;
     private URI namespace;
@@ -64,15 +64,10 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
 
     private int augmentsResolved;
 
-    private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
-
-    /**
-     * Holds all child (DataSchemaNode) nodes: anyxml, choice, case, container,
-     * list, leaf, leaf-list.
-     */
-    private final Set<DataSchemaNodeBuilder> childNodes = new HashSet<DataSchemaNodeBuilder>();
+    private final LinkedList<Builder> actualPath = new LinkedList<Builder>();
+    private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<TypeAwareBuilder>();
 
-    private final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
+    private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
     private final List<AugmentationSchemaBuilder> addedAugments = new ArrayList<AugmentationSchemaBuilder>();
     private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<AugmentationSchemaBuilder>();
     private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
@@ -81,17 +76,14 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
     private final Set<NotificationBuilder> addedNotifications = new HashSet<NotificationBuilder>();
     private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<IdentitySchemaNodeBuilder>();
     private final Set<FeatureBuilder> addedFeatures = new HashSet<FeatureBuilder>();
-    private final Map<List<String>, DeviationBuilder> addedDeviations = new HashMap<List<String>, DeviationBuilder>();
+    private final Set<DeviationBuilder> addedDeviations = new HashSet<DeviationBuilder>();
     private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
-    private final Map<List<String>, UnionTypeBuilder> addedUnionTypes = new HashMap<List<String>, UnionTypeBuilder>();
     private final List<ExtensionBuilder> addedExtensions = new ArrayList<ExtensionBuilder>();
-    private final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes = new HashMap<List<String>, List<UnknownSchemaNodeBuilder>>();
-
-    private final Map<List<String>, TypeAwareBuilder> dirtyNodes = new HashMap<List<String>, TypeAwareBuilder>();
-
-    private final LinkedList<Builder> actualPath = new LinkedList<Builder>();
+    private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
+    private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
 
     public ModuleBuilder(final String name) {
+        super(0, null);
         this.name = name;
         instance = new ModuleImpl(name);
     }
@@ -115,7 +107,7 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
 
         // CHILD NODES
         final Map<QName, DataSchemaNode> children = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
-        for (DataSchemaNodeBuilder child : childNodes) {
+        for (DataSchemaNodeBuilder child : addedChildNodes) {
             children.put(child.getQName(), child.build());
         }
         instance.setChildNodes(children);
@@ -165,8 +157,8 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
 
         // DEVIATIONS
         final Set<Deviation> deviations = new HashSet<Deviation>();
-        for (Map.Entry<List<String>, DeviationBuilder> entry : addedDeviations.entrySet()) {
-            deviations.add(entry.getValue().build());
+        for (DeviationBuilder entry : addedDeviations) {
+            deviations.add(entry.build());
         }
         instance.setDeviations(deviations);
 
@@ -186,32 +178,20 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         instance.setIdentities(identities);
 
         // UNKNOWN NODES
-        final List<UnknownSchemaNode> unknownNodes = buildModuleUnknownNodes(addedUnknownNodes);
+        final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+        for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
+            unknownNodes.add(unb.build());
+        }
         instance.setUnknownSchemaNodes(unknownNodes);
 
         return instance;
     }
 
-    @Override
-    public int getLine() {
-        return 0;
-    }
-
-    @Override
-    public Builder getParent() {
-        return null;
-    }
-
     @Override
     public void setParent(Builder parent) {
         throw new YangParseException(name, 0, "Can not set parent to module");
     }
 
-    @Override
-    public QName getQName() {
-        return new QName(namespace, revision, prefix, name);
-    }
-
     @Override
     public SchemaPath getPath() {
         return null;
@@ -246,26 +226,7 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         }
     }
 
-    @Override
-    public Set<GroupingDefinition> getGroupings() {
-        return Collections.emptySet();
-    }
-
-    @Override
-    public Set<GroupingBuilder> getGroupingBuilders() {
-        return addedGroupings;
-    }
-
-    @Override
-    public Set<DataSchemaNode> getChildNodes() {
-        return Collections.emptySet();
-    }
-
-    public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
-        return childNodes;
-    }
-
-    public Map<List<String>, TypeAwareBuilder> getDirtyNodes() {
+    public Set<TypeAwareBuilder> getDirtyNodes() {
         return dirtyNodes;
     }
 
@@ -281,12 +242,12 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         return allUsesNodes;
     }
 
-    public List<UnknownSchemaNodeBuilder> getUnknownNodes() {
-        List<UnknownSchemaNodeBuilder> result = new ArrayList<UnknownSchemaNodeBuilder>();
-        for (List<UnknownSchemaNodeBuilder> entry : addedUnknownNodes.values()) {
-            result.addAll(entry);
-        }
-        return result;
+    public Set<DeviationBuilder> getDeviations() {
+        return addedDeviations;
+    }
+
+    public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
+        return allUnknownNodes;
     }
 
     public String getName() {
@@ -317,10 +278,9 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         augmentsResolved++;
     }
 
-    public void addDirtyNode(final List<String> path) {
-        final List<String> dirtyNodePath = new ArrayList<String>(path);
-        final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) actualPath.getFirst();
-        dirtyNodes.put(dirtyNodePath, nodeBuilder);
+    public void markActualNodeDirty() {
+        final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
+        dirtyNodes.add(nodeBuilder);
     }
 
     public void setRevision(final Date revision) {
@@ -366,17 +326,6 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         return builder;
     }
 
-    @Override
-    public void addChildNode(DataSchemaNodeBuilder child) {
-        for (DataSchemaNodeBuilder childNode : childNodes) {
-            if (childNode.getQName().getLocalName().equals(child.getQName().getLocalName())) {
-                throw new YangParseException(name, child.getLine(), "Duplicate node found at line "
-                        + childNode.getLine());
-            }
-        }
-        childNodes.add(child);
-    }
-
     public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName containerName,
             final SchemaPath schemaPath) {
         final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(line, containerName, schemaPath);
@@ -419,17 +368,6 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         return builder;
     }
 
-    @Override
-    public void addGrouping(GroupingBuilder groupingBuilder) {
-        for (GroupingBuilder gb : addedGroupings) {
-            if (gb.getQName().getLocalName().equals(groupingBuilder.getQName().getLocalName())) {
-                throw new YangParseException(name, groupingBuilder.getLine(), "Duplicate node found at line "
-                        + gb.getLine());
-            }
-        }
-        addedGroupings.add(groupingBuilder);
-    }
-
     public GroupingBuilder addGrouping(final int line, final QName qname) {
         final GroupingBuilder builder = new GroupingBuilderImpl(qname, line);
 
@@ -706,64 +644,51 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         Builder parent = getActualNode();
         if (parent == null || !(parent instanceof TypeAwareBuilder)) {
             throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
-                    + "'. Unknown parent node: " + parent);
+                    + "'. Invalid parent node: " + parent);
         }
         ((TypeAwareBuilder) parent).setType(type);
     }
 
-    public UnionTypeBuilder addUnionType(final List<String> currentPath, final URI namespace, final Date revision,
-            final int line) {
-        final List<String> pathToUnion = new ArrayList<String>(currentPath);
-        final UnionTypeBuilder union = new UnionTypeBuilder(line);
-
-        if (actualPath.isEmpty()) {
-            throw new YangParseException(line, "union error");
+    public UnionTypeBuilder addUnionType(final int line, final URI namespace, final Date revision) {
+        final Builder parent = getActualNode();
+        if (parent == null) {
+            throw new YangParseException(line, "Error while parsing union type");
         } else {
-            final Builder parent = actualPath.getFirst();
+            final UnionTypeBuilder union = new UnionTypeBuilder(line);
             if (parent instanceof TypeAwareBuilder) {
-
                 ((TypeAwareBuilder) parent).setTypedef(union);
-
-                final List<String> path = new ArrayList<String>(pathToUnion);
-                path.add("union");
-
-                addedUnionTypes.put(path, union);
                 return union;
             } else {
-                throw new YangParseException(name, line, "Unresolved parent of union type.");
+                throw new YangParseException(name, line, "Invalid parent of union type.");
             }
         }
     }
 
-    public void addIdentityrefType(final String baseString, final List<String> parentPath, final SchemaPath schemaPath,
-            final int line) {
-        final List<String> pathToIdentityref = new ArrayList<String>(parentPath);
+    public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
         final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(baseString, schemaPath, line);
 
-        if (actualPath.isEmpty()) {
-            throw new YangParseException(line, "identityref error");
+        final Builder parent = getActualNode();
+        if (parent == null) {
+            throw new YangParseException(line, "Error while parsing identityref type.");
         } else {
-            final Builder parent = actualPath.getFirst();
             if (parent instanceof TypeAwareBuilder) {
                 final TypeAwareBuilder typeParent = (TypeAwareBuilder) parent;
                 typeParent.setTypedef(identityref);
-                dirtyNodes.put(pathToIdentityref, typeParent);
+                dirtyNodes.add(typeParent);
             } else {
-                throw new YangParseException(name, line, "Unresolved parent of identityref type.");
+                throw new YangParseException(name, line, "Invalid parent of identityref type.");
             }
         }
     }
 
-    public DeviationBuilder addDeviation(final String targetPath, final List<String> parentPath, final int line) {
+    public DeviationBuilder addDeviation(final int line, final String targetPath) {
         Builder parent = getActualNode();
         if (parent != null) {
             throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
         }
 
-        final List<String> pathToDeviation = new ArrayList<String>(parentPath);
-        pathToDeviation.add(targetPath);
-        final DeviationBuilder builder = new DeviationBuilder(targetPath, line);
-        addedDeviations.put(pathToDeviation, builder);
+        final DeviationBuilder builder = new DeviationBuilder(line, targetPath);
+        addedDeviations.add(builder);
         return builder;
     }
 
@@ -784,29 +709,24 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
     }
 
     @Override
-    public void addUnknownSchemaNode(UnknownSchemaNodeBuilder builder) {
-        final List<String> unPath = new ArrayList<String>();
-        for (QName name : builder.getPath().getPath()) {
-            unPath.add(name.getLocalName());
-        }
-        if (addedUnknownNodes.containsKey(unPath)) {
-            addedUnknownNodes.get(unPath).add(builder);
-        } else {
-            List<UnknownSchemaNodeBuilder> nodes = new ArrayList<UnknownSchemaNodeBuilder>();
-            nodes.add(builder);
-            addedUnknownNodes.put(unPath, nodes);
-        }
+    public void addUnknownSchemaNode(final UnknownSchemaNodeBuilder builder) {
+        addedUnknownNodes.add(builder);
+        allUnknownNodes.add(builder);
     }
 
-    public UnknownSchemaNodeBuilder addUnknownSchemaNode(final QName qname, final List<String> parentPath,
-            final int line) {
+    public UnknownSchemaNodeBuilder addUnknownSchemaNode(final int line, final QName qname) {
         final Builder parent = getActualNode();
         final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(line, qname);
         builder.setParent(parent);
+        allUnknownNodes.add(builder);
 
-        if (parent != null) {
+        if (parent == null) {
+            addedUnknownNodes.add(builder);
+        } else {
             if (parent instanceof SchemaNodeBuilder) {
                 ((SchemaNodeBuilder) parent).addUnknownSchemaNode(builder);
+            } else if (parent instanceof DataNodeContainerBuilder) {
+                ((DataNodeContainerBuilder) parent).addUnknownSchemaNode(builder);
             } else if (parent instanceof RefineHolder) {
                 ((RefineHolder) parent).addUnknownSchemaNode(builder);
             } else {
@@ -814,22 +734,13 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
                         + "'");
             }
         }
-        final List<String> unPath = new ArrayList<String>(parentPath);
-        unPath.add(qname.getLocalName());
 
-        if (addedUnknownNodes.containsKey(unPath)) {
-            addedUnknownNodes.get(unPath).add(builder);
-        } else {
-            List<UnknownSchemaNodeBuilder> nodes = new ArrayList<UnknownSchemaNodeBuilder>();
-            nodes.add(builder);
-            addedUnknownNodes.put(unPath, nodes);
-        }
         return builder;
     }
 
     @Override
     public String toString() {
-        return ModuleBuilder.class.getSimpleName() + "[" + name + "]";
+        return "module " + name;
     }
 
     private final class ModuleImpl implements Module {
@@ -1181,7 +1092,7 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
             // notifications, and anyxmls defined within a parent node or at the
             // top level of the module or its submodules share the same
             // identifier namespace.
-            for (DataSchemaNodeBuilder childNode : childNodes) {
+            for (DataSchemaNodeBuilder childNode : addedChildNodes) {
                 if (childNode.getQName().getLocalName().equals(childLocalName)) {
                     throw new YangParseException(name, line, "Duplicate node found at line " + childNode.getLine());
                 }
@@ -1196,7 +1107,7 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
                     throw new YangParseException(name, line, "Duplicate node found at line " + notification.getLine());
                 }
             }
-            childNodes.add(child);
+            addedChildNodes.add(child);
         } else {
             // no need for checking rpc and notification because they can be
             // defined only under module or submodule
@@ -1294,30 +1205,4 @@ public class ModuleBuilder implements DataNodeContainerBuilder {
         return moduleImport;
     }
 
-    /**
-     * Traverse through given addedUnknownNodes and add only unknown nodes
-     * defined under module statement.
-     *
-     * @param addedUnknownNodes
-     *            unknown node builders
-     * @return list of all unknown nodes defined in module in lexicographical
-     *         order
-     */
-    private List<UnknownSchemaNode> buildModuleUnknownNodes(
-            final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes) {
-        final List<UnknownSchemaNode> result = new ArrayList<UnknownSchemaNode>();
-        for (Map.Entry<List<String>, List<UnknownSchemaNodeBuilder>> entry : addedUnknownNodes.entrySet()) {
-            final List<String> path = entry.getKey();
-            final List<UnknownSchemaNodeBuilder> child = entry.getValue();
-
-            if (path.size() == 2) {
-                for (UnknownSchemaNodeBuilder node : child) {
-                    result.add(node.build());
-                }
-            }
-        }
-        Collections.sort(result, Comparators.SCHEMA_NODE_COMP);
-        return result;
-    }
-
 }
index b9b151989ef00a0526bbf7847e1737a189c8b250..1c4962835d399993f0273f6f51b63b0c2b48a02f 100644 (file)
@@ -40,7 +40,6 @@ public final class NotificationBuilder extends AbstractDataNodeContainerBuilder
         AugmentationTargetBuilder {
     private boolean isBuilt;
     private final NotificationDefinitionImpl instance;
-    private final int line;
     private SchemaPath schemaPath;
     private String description;
     private String reference;
@@ -53,7 +52,6 @@ public final class NotificationBuilder extends AbstractDataNodeContainerBuilder
 
     NotificationBuilder(final int line, final QName qname) {
         super(line, qname);
-        this.line = line;
         instance = new NotificationDefinitionImpl(qname);
     }
 
index d2b8544bfdf2fdee7a277178d59409aa6c901898..65b15c583b672b30acc0be6531b91209d3202458 100644 (file)
@@ -69,11 +69,13 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder {
             instance.setGroupings(groupings);
 
             // UNKNOWN NODES
-            final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
-            for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
-                unknownNodes.add(b.build());
+            if (unknownNodes == null) {
+                unknownNodes = new ArrayList<UnknownSchemaNode>();
+                for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+                    unknownNodes.add(b.build());
+                }
+                Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             }
-            Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
             instance.setUnknownSchemaNodes(unknownNodes);
 
             isBuilt = true;
@@ -140,6 +142,11 @@ public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder {
         return true;
     }
 
+    @Override
+    public String toString() {
+        return "rpc " + qname.getLocalName();
+    }
+
     private final class RpcDefinitionImpl implements RpcDefinition {
         private final QName qname;
         private SchemaPath path;
index 232fa60d6b8805c9ed8130abcbf9200f9f04a393..267696bdae8383fbd911d3fd6488f372cc3f0a9b 100644 (file)
@@ -22,7 +22,6 @@ public final class UnknownSchemaNodeBuilder extends AbstractSchemaNodeBuilder {
     private boolean isBuilt;
     private final UnknownSchemaNodeImpl instance;
     private boolean addedByUses;
-    private List<UnknownSchemaNode> unknownNodes;
     private QName nodeType;
     private String nodeParameter;
 
@@ -80,10 +79,6 @@ public final class UnknownSchemaNodeBuilder extends AbstractSchemaNodeBuilder {
         this.addedByUses = addedByUses;
     }
 
-    public void setUnknownNodes(final List<UnknownSchemaNode> unknownNodes) {
-        this.unknownNodes = unknownNodes;
-    }
-
     public QName getNodeType() {
         return nodeType;
     }
index 6adc29b2271ce956fed15035084b1a3f9f7f77b0..5850abeb8129caace7573f5a6ede985674dc3995 100644 (file)
@@ -39,6 +39,7 @@ import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.controller.yang.model.api.ChoiceNode;
 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;
 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
@@ -47,6 +48,7 @@ import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
 import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
@@ -68,6 +70,7 @@ import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.DeviationBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
 import org.opendaylight.controller.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.IdentityrefTypeBuilder;
@@ -305,6 +308,7 @@ public final class YangParserImpl implements YangModelParser {
             }
         }
         resolveAugments(modules);
+        resolveDeviations(modules);
 
         // build
         // LinkedHashMap MUST be used otherwise the values will not maintain
@@ -333,6 +337,7 @@ public final class YangParserImpl implements YangModelParser {
             }
         }
         resolveAugmentsWithContext(modules, context);
+        resolveDeviationsWithContext(modules, context);
 
         // build
         // LinkedHashMap MUST be used otherwise the values will not maintain
@@ -376,11 +381,9 @@ public final class YangParserImpl implements YangModelParser {
      *            current module
      */
     private void resolveDirtyNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
-        final Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
+        final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
         if (!dirtyNodes.isEmpty()) {
-            for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
-                final TypeAwareBuilder nodeToResolve = entry.getValue();
-
+            for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
                 if (nodeToResolve instanceof UnionTypeBuilder) {
                     // special handling for union types
                     resolveTypeUnion((UnionTypeBuilder) nodeToResolve, modules, module);
@@ -397,11 +400,9 @@ public final class YangParserImpl implements YangModelParser {
 
     private void resolveDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module, SchemaContext context) {
-        final Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
+        final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
         if (!dirtyNodes.isEmpty()) {
-            for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
-                final TypeAwareBuilder nodeToResolve = entry.getValue();
-
+            for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
                 if (nodeToResolve instanceof UnionTypeBuilder) {
                     // special handling for union types
                     resolveTypeUnionWithContext((UnionTypeBuilder) nodeToResolve, modules, module, context);
@@ -1062,34 +1063,42 @@ public final class YangParserImpl implements YangModelParser {
         DataNodeContainerBuilder parent = usesNode.getParent();
         SchemaPath parentPath = parent.getPath();
         for (DataSchemaNodeBuilder child : targetGrouping.getChildNodeBuilders()) {
-            // if node is refined, take it from refined nodes and continue
-            SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
-            if (refined != null) {
-                refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
-                parent.addChildNode((DataSchemaNodeBuilder) refined);
-                continue;
-            }
+            if (child != null) {
+                // if node is refined, take it from refined nodes and continue
+                SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
+                if (refined != null) {
+                    refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
+                    parent.addChildNode((DataSchemaNodeBuilder) refined);
+                    continue;
+                }
 
-            DataSchemaNodeBuilder newChild = null;
-            if (child instanceof AnyXmlBuilder) {
-                newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
-            } else if (child instanceof ChoiceBuilder) {
-                newChild = new ChoiceBuilder((ChoiceBuilder) child);
-            } else if (child instanceof ContainerSchemaNodeBuilder) {
-                newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
-            } else if (child instanceof LeafListSchemaNodeBuilder) {
-                newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
-            } else if (child instanceof LeafSchemaNodeBuilder) {
-                newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
-            } else if (child instanceof ListSchemaNodeBuilder) {
-                newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
-            }
+                DataSchemaNodeBuilder newChild = null;
+                if (child instanceof AnyXmlBuilder) {
+                    newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
+                } else if (child instanceof ChoiceBuilder) {
+                    newChild = new ChoiceBuilder((ChoiceBuilder) child);
+                } else if (child instanceof ContainerSchemaNodeBuilder) {
+                    newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
+                } else if (child instanceof LeafListSchemaNodeBuilder) {
+                    newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
+                } else if (child instanceof LeafSchemaNodeBuilder) {
+                    newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
+                } else if (child instanceof ListSchemaNodeBuilder) {
+                    newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
+                }
+
+                if (newChild == null) {
+                    throw new YangParseException(usesNode.getLine(),
+                            "Unknown member of target grouping while resolving uses node.");
+                }
 
-            if (newChild instanceof GroupingMember) {
-                ((GroupingMember) newChild).setAddedByUses(true);
+                if (newChild instanceof GroupingMember) {
+                    ((GroupingMember) newChild).setAddedByUses(true);
+                }
+
+                newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
+                parent.addChildNode(newChild);
             }
-            newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
-            parent.addChildNode(newChild);
         }
         for (GroupingBuilder g : targetGrouping.getGroupingBuilders()) {
             GroupingBuilder newGrouping = new GroupingBuilderImpl(g);
@@ -1123,34 +1132,41 @@ public final class YangParserImpl implements YangModelParser {
         DataNodeContainerBuilder parent = usesNode.getParent();
         SchemaPath parentPath = parent.getPath();
         for (DataSchemaNode child : targetGrouping.getChildNodes()) {
-            // if node is refined, take it from refined nodes and continue
-            SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
-            if (refined != null) {
-                refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
-                parent.addChildNode((DataSchemaNodeBuilder) refined);
-                continue;
-            }
+            if (child != null) {
+                // if node is refined, take it from refined nodes and continue
+                SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
+                if (refined != null) {
+                    refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
+                    parent.addChildNode((DataSchemaNodeBuilder) refined);
+                    continue;
+                }
 
-            DataSchemaNodeBuilder newChild = null;
-            if (child instanceof AnyXmlSchemaNode) {
-                newChild = createAnyXml((AnyXmlSchemaNode) child, line);
-            } else if (child instanceof ChoiceNode) {
-                newChild = createChoice((ChoiceNode) child, line);
-            } else if (child instanceof ContainerSchemaNode) {
-                newChild = createContainer((ContainerSchemaNode) child, line);
-            } else if (child instanceof LeafListSchemaNode) {
-                newChild = createLeafList((LeafListSchemaNode) child, line);
-            } else if (child instanceof LeafSchemaNode) {
-                newChild = createLeafBuilder((LeafSchemaNode) child, line);
-            } else if (child instanceof ListSchemaNode) {
-                newChild = createList((ListSchemaNode) child, line);
-            }
+                DataSchemaNodeBuilder newChild = null;
+                if (child instanceof AnyXmlSchemaNode) {
+                    newChild = createAnyXml((AnyXmlSchemaNode) child, line);
+                } else if (child instanceof ChoiceNode) {
+                    newChild = createChoice((ChoiceNode) child, line);
+                } else if (child instanceof ContainerSchemaNode) {
+                    newChild = createContainer((ContainerSchemaNode) child, line);
+                } else if (child instanceof LeafListSchemaNode) {
+                    newChild = createLeafList((LeafListSchemaNode) child, line);
+                } else if (child instanceof LeafSchemaNode) {
+                    newChild = createLeafBuilder((LeafSchemaNode) child, line);
+                } else if (child instanceof ListSchemaNode) {
+                    newChild = createList((ListSchemaNode) child, line);
+                }
+
+                if (newChild == null) {
+                    throw new YangParseException(usesNode.getLine(),
+                            "Unknown member of target grouping while resolving uses node.");
+                }
 
-            if (newChild instanceof GroupingMember) {
-                ((GroupingMember) newChild).setAddedByUses(true);
+                if (newChild instanceof GroupingMember) {
+                    ((GroupingMember) newChild).setAddedByUses(true);
+                }
+                newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
+                parent.addChildNode(newChild);
             }
-            newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
-            parent.addChildNode(newChild);
         }
         for (GroupingDefinition g : targetGrouping.getGroupings()) {
             GroupingBuilder newGrouping = createGrouping(g, line);
@@ -1201,7 +1217,7 @@ public final class YangParserImpl implements YangModelParser {
     }
 
     private void resolveUnknownNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
-        for (UnknownSchemaNodeBuilder usnb : module.getUnknownNodes()) {
+        for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {
             QName nodeType = usnb.getNodeType();
             if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
                 try {
@@ -1218,8 +1234,8 @@ public final class YangParserImpl implements YangModelParser {
     }
 
     private void resolveUnknownNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            final ModuleBuilder module, SchemaContext context) {
-        for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getUnknownNodes()) {
+            final ModuleBuilder module, final SchemaContext context) {
+        for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getAllUnknownNodes()) {
             QName nodeType = unknownNodeBuilder.getNodeType();
             if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
                 try {
@@ -1246,4 +1262,115 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    private void resolveDeviations(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
+        for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+            for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+                ModuleBuilder b = inner.getValue();
+                resolveDeviation(modules, b);
+            }
+        }
+    }
+
+    private void resolveDeviation(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+        for (DeviationBuilder dev : module.getDeviations()) {
+            int line = dev.getLine();
+            SchemaPath targetPath = dev.getTargetPath();
+            List<QName> path = targetPath.getPath();
+            QName q0 = path.get(0);
+            String prefix = q0.getPrefix();
+            if (prefix == null) {
+                prefix = module.getPrefix();
+            }
+
+            ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
+            processDeviation(dev, dependentModuleBuilder, path, module);
+        }
+    }
+
+    private void resolveDeviationsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final SchemaContext context) {
+        for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+            for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+                ModuleBuilder b = inner.getValue();
+                resolveDeviationWithContext(modules, b, context);
+            }
+        }
+    }
+
+    private void resolveDeviationWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final ModuleBuilder module, final SchemaContext context) {
+        for (DeviationBuilder dev : module.getDeviations()) {
+            int line = dev.getLine();
+            SchemaPath targetPath = dev.getTargetPath();
+            List<QName> path = targetPath.getPath();
+            QName q0 = path.get(0);
+            String prefix = q0.getPrefix();
+            if (prefix == null) {
+                prefix = module.getPrefix();
+            }
+            String name = null;
+
+            ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
+            if (dependentModuleBuilder == null) {
+                Module dependentModule = findModuleFromContext(context, module, prefix, line);
+                Object currentParent = dependentModule;
+
+                for (int i = 0; i < path.size(); i++) {
+                    if (currentParent == null) {
+                        throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+                    }
+                    QName q = path.get(i);
+                    name = q.getLocalName();
+                    if (currentParent instanceof DataNodeContainer) {
+                        currentParent = ((DataNodeContainer) currentParent).getDataChildByName(name);
+                    }
+                }
+
+                if (currentParent == null) {
+                    throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+                }
+                if (currentParent instanceof SchemaNode) {
+                    dev.setTargetPath(((SchemaNode) currentParent).getPath());
+                }
+
+            } else {
+                processDeviation(dev, dependentModuleBuilder, path, module);
+            }
+        }
+    }
+
+    /**
+     * Correct deviation target path in deviation builder.
+     *
+     * @param dev
+     *            deviation
+     * @param dependentModuleBuilder
+     *            module containing deviation target
+     * @param path
+     *            current deviation target path
+     * @param module
+     *            current module
+     */
+    private void processDeviation(final DeviationBuilder dev, final ModuleBuilder dependentModuleBuilder,
+            final List<QName> path, final ModuleBuilder module) {
+        final int line = dev.getLine();
+        Builder currentParent = dependentModuleBuilder;
+
+        for (int i = 0; i < path.size(); i++) {
+            if (currentParent == null) {
+                throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+            }
+            QName q = path.get(i);
+            String name = q.getLocalName();
+            if (currentParent instanceof DataNodeContainerBuilder) {
+                currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name);
+            }
+        }
+
+        if (currentParent == null || !(currentParent instanceof SchemaNodeBuilder)) {
+            throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+        }
+        dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath());
+    }
+
 }
index f806c94a30909c9a507c9eb3d6a3b4d948a532b5..eb0fc21d37a326c03549ecba6782f11a25a790df 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.controller.yang.parser.impl;
 
-import static org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil.*;
+import static org.opendaylight.controller.yang.parser.util.ParserListenerUtils.*;
 
 import java.net.URI;
 import java.text.DateFormat;
@@ -185,12 +185,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
     @Override
     public void enterRevision_stmts(Revision_stmtsContext ctx) {
         enterLog("revisions", "", ctx.getStart().getLine());
-        if (ctx != null) {
-            for (int i = 0; i < ctx.getChildCount(); ++i) {
-                final ParseTree treeNode = ctx.getChild(i);
-                if (treeNode instanceof Revision_stmtContext) {
-                    updateRevisionForRevisionStatement(treeNode);
-                }
+        for (int i = 0; i < ctx.getChildCount(); ++i) {
+            final ParseTree treeNode = ctx.getChild(i);
+            if (treeNode instanceof Revision_stmtContext) {
+                updateRevisionForRevisionStatement(treeNode);
             }
         }
     }
@@ -331,6 +329,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
         builder.setUnits(parseUnits(ctx));
+        builder.setDefaultValue(parseDefault(ctx));
     }
 
     @Override
@@ -367,12 +366,12 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             } else {
                 if ("union".equals(typeName)) {
                     SchemaPath p = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
-                    UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(actualPath, namespace, revision, line);
+                    UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(line, namespace, revision);
                     moduleBuilder.enterNode(unionBuilder);
                     unionBuilder.setPath(p);
                 } else if ("identityref".equals(typeName)) {
                     SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
-                    moduleBuilder.addIdentityrefType(getIdentityrefBase(typeBody), actualPath, path, line);
+                    moduleBuilder.addIdentityrefType(line, path, getIdentityrefBase(typeBody));
                 } else {
                     type = parseTypeWithBody(moduleName, typeName, typeBody, actualPath, namespace, revision,
                             yangModelPrefix, moduleBuilder.getActualNode());
@@ -383,7 +382,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             type = parseUnknownTypeWithBody(typeQName, typeBody, actualPath, namespace, revision, yangModelPrefix,
                     moduleBuilder.getActualNode());
             // add parent node of this type statement to dirty nodes
-            moduleBuilder.addDirtyNode(actualPath);
+            moduleBuilder.markActualNodeDirty();
             moduleBuilder.setType(type);
         }
 
@@ -743,7 +742,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             qname = new QName(namespace, revision, yangModelPrefix, nodeParameter);
         }
 
-        UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(qname, actualPath, line);
+        UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(line, qname);
         builder.setNodeType(nodeType);
         builder.setNodeParameter(nodeParameter);
         actualPath.push(nodeParameter);
@@ -854,7 +853,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
         String reference = null;
         String deviate = null;
-        DeviationBuilder builder = moduleBuilder.addDeviation(targetPath, actualPath, line);
+        DeviationBuilder builder = moduleBuilder.addDeviation(line, targetPath);
         moduleBuilder.enterNode(builder);
         actualPath.push(targetPath);
 
@@ -118,10 +118,10 @@ import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public final class YangModelBuilderUtil {
-    private static final Logger logger = LoggerFactory.getLogger(YangModelBuilderUtil.class);
+public final class ParserListenerUtils {
+    private static final Logger logger = LoggerFactory.getLogger(ParserListenerUtils.class);
 
-    private YangModelBuilderUtil() {
+    private ParserListenerUtils() {
     }
 
     /**
@@ -216,6 +216,26 @@ public final class YangModelBuilderUtil {
         return units;
     }
 
+    /**
+     * Parse given tree and returns default statement as string.
+     *
+     * @param ctx
+     *            context to parse
+     * @return value of default statement as string or null if there is no
+     *         default statement
+     */
+    public static String parseDefault(final ParseTree ctx) {
+        String defaultValue = null;
+        for (int i = 0; i < ctx.getChildCount(); i++) {
+            ParseTree child = ctx.getChild(i);
+            if (child instanceof Default_stmtContext) {
+                defaultValue = stringFromNode(child);
+                break;
+            }
+        }
+        return defaultValue;
+    }
+
     /**
      * Create SchemaPath from actualPath and names.
      *
@@ -926,8 +946,8 @@ public final class YangModelBuilderUtil {
                 ChoiceCaseBuilder choiceCase = (ChoiceCaseBuilder) parent;
                 Builder choice = choiceCase.getParent();
                 Boolean parentConfig = null;
-                if(choice instanceof ChoiceBuilder) {
-                    parentConfig = ((ChoiceBuilder)choice).isConfiguration();
+                if (choice instanceof ChoiceBuilder) {
+                    parentConfig = ((ChoiceBuilder) choice).isConfiguration();
                 } else {
                     parentConfig = true;
                 }
@@ -1019,17 +1039,14 @@ public final class YangModelBuilderUtil {
                 TypeDefinition<?> baseType = unknownType.build();
                 TypeDefinition<?> result = null;
                 QName qname = new QName(namespace, revision, prefix, typeName);
-                ExtendedType.Builder typeBuilder = null;
-
                 SchemaPath schemaPath = createTypeSchemaPath(actualPath, namespace, revision, prefix, typeName, false,
                         false);
-                typeBuilder = new ExtendedType.Builder(qname, baseType, "", "", schemaPath);
 
+                ExtendedType.Builder typeBuilder = new ExtendedType.Builder(qname, baseType, null, null, schemaPath);
                 typeBuilder.ranges(rangeStatements);
                 typeBuilder.lengths(lengthStatements);
                 typeBuilder.patterns(patternStatements);
                 typeBuilder.fractionDigits(fractionDigits);
-
                 result = typeBuilder.build();
 
                 return result;
@@ -1063,6 +1080,7 @@ public final class YangModelBuilderUtil {
     public static TypeDefinition<?> parseTypeWithBody(final String moduleName, final String typeName,
             final Type_body_stmtsContext typeBody, final List<String> actualPath, final URI namespace,
             final Date revision, final String prefix, final Builder parent) {
+        final int line = typeBody.getStart().getLine();
         TypeDefinition<?> baseType = null;
 
         Integer fractionDigits = getFractionDigits(typeBody);
@@ -1070,7 +1088,7 @@ public final class YangModelBuilderUtil {
         List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
         List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody);
 
-        TypeConstraints constraints = new TypeConstraints(moduleName, typeBody.getStart().getLine());
+        TypeConstraints constraints = new TypeConstraints(moduleName, line);
         constraints.addFractionDigits(fractionDigits);
         constraints.addLengths(lengthStatements);
         constraints.addPatterns(patternStatements);
@@ -1098,6 +1116,9 @@ public final class YangModelBuilderUtil {
             } else if ("int64".equals(typeName)) {
                 intType = new Int64(baseTypePath);
             }
+            if(intType == null) {
+                throw new YangParseException(moduleName, line, "Unknown yang type "+ typeName);
+            }
             constraints.addRanges(intType.getRangeStatements());
             baseType = intType;
         } else if (typeName.startsWith("uint")) {
@@ -1111,6 +1132,9 @@ public final class YangModelBuilderUtil {
             } else if ("uint64".equals(typeName)) {
                 uintType = new Uint64(baseTypePath);
             }
+            if(uintType == null) {
+                throw new YangParseException(moduleName, line, "Unknown yang type "+ typeName);
+            }
             constraints.addRanges(uintType.getRangeStatements());
             baseType = uintType;
         } else if ("enumeration".equals(typeName)) {
index 64b06ad68ac4486389374d7c6ec0c5e16e35f245..87075e212205210dbb1da423bf2585cc9bea4fb6 100644 (file)
@@ -501,7 +501,7 @@ public final class ParserUtils {
         }
 
         // set correct path for all cases
-        if(childNode instanceof ChoiceBuilder) {
+        if (childNode instanceof ChoiceBuilder) {
             ChoiceBuilder choiceBuilder = (ChoiceBuilder) childNode;
             for (ChoiceCaseBuilder choiceCaseBuilder : choiceBuilder.getCases()) {
                 correctAugmentChildPath(choiceCaseBuilder, childNode.getPath());
@@ -601,11 +601,12 @@ public final class ParserUtils {
 
     private static TypeDefinition<?> createCorrectTypeDefinition(SchemaPath parentSchemaPath, QName nodeQName,
             TypeDefinition<?> nodeType) {
-        QName nodeTypeQName = nodeType.getQName();
-        SchemaPath newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, nodeTypeQName);
         TypeDefinition<?> result = null;
 
         if (nodeType != null) {
+            QName nodeTypeQName = nodeType.getQName();
+            SchemaPath newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, nodeTypeQName);
+
             if (nodeType instanceof BinaryTypeDefinition) {
                 BinaryTypeDefinition binType = (BinaryTypeDefinition) nodeType;
 
index 17307b46ee29f8aedc8a8dcc58e4113a1d9c84f2..4d2c5b582321c907860b801edeb57499a2ab9f6b 100644 (file)
@@ -24,7 +24,7 @@ public final class TypeConstraints {
     private final int line;
     private final List<List<RangeConstraint>> ranges = new ArrayList<List<RangeConstraint>>();
     private final List<List<LengthConstraint>> lengths = new ArrayList<List<LengthConstraint>>();
-    private final List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
+    private final List<List<PatternConstraint>> patterns = new ArrayList<List<PatternConstraint>>();
     private final List<Integer> fractionDigits = new ArrayList<Integer>();
 
     public TypeConstraints(final String moduleName, final int line) {
@@ -195,11 +195,14 @@ public final class TypeConstraints {
     }
 
     public List<PatternConstraint> getPatterns() {
-        return patterns;
+        if(patterns.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return patterns.get(0);
     }
 
     public void addPatterns(final List<PatternConstraint> patterns) {
-        this.patterns.addAll(patterns);
+        this.patterns.add(patterns);
     }
 
     public Integer getFractionDigits() {
index d697201f217029316ba35afdb35d1d9bee39e514..cb5af9f34928ee22548d6d0a135db6d0b53209f7 100644 (file)
@@ -16,7 +16,7 @@ import java.util.Set;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
-import org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
 import org.opendaylight.controller.yang.parser.util.YangValidationException;
 
 /**
@@ -60,7 +60,7 @@ final class ValidationUtil {
     }
 
     static String getName(ParseTree child) {
-        return YangModelBuilderUtil.stringFromNode(child);
+        return ParserListenerUtils.stringFromNode(child);
     }
 
     static String f(String base, Object... args) {
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/AugmentTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/AugmentTest.java
new file mode 100644 (file)
index 0000000..d6f6356
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.yang.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.Leafref;
+
+import com.google.common.collect.Lists;
+
+public class AugmentTest {
+
+    private final URI types1NS = URI.create("urn:simple.nodes.test");
+    private final URI types2NS = URI.create("urn:simple.types.test");
+    private final URI types3NS = URI.create("urn:custom.nodes.test");
+    private Date types1Rev;
+    private Date types2Rev;
+    private Date types3Rev;
+    private final String t1 = "n";
+    private final String t2 = "t";
+    private final String t3 = "c";
+    private QName q0;
+    private QName q1;
+    private QName q2;
+
+    private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+    private Set<Module> modules;
+
+    @Before
+    public void init() throws FileNotFoundException, ParseException {
+        types1Rev = simpleDateFormat.parse("2013-02-27");
+        types2Rev = simpleDateFormat.parse("2013-07-03");
+        types3Rev = simpleDateFormat.parse("2013-02-27");
+
+        q0 = new QName(types2NS, types2Rev, t2, "interfaces");
+        q1 = new QName(types2NS, types2Rev, t2, "ifEntry");
+        q2 = new QName(types3NS, types3Rev, t3, "augment-holder");
+
+        modules = TestUtils.loadModules(getClass().getResource("/model").getPath());
+        assertEquals(3, modules.size());
+    }
+
+    @Test
+    public void testAugmentParsing() {
+        SchemaPath expectedPath = null;
+        QName[] qnames = null;
+
+        // testfile1
+        Module module1 = TestUtils.findModule(modules, "nodes");
+        Set<AugmentationSchema> augmentations = module1.getAugmentations();
+        assertEquals(1, augmentations.size());
+        AugmentationSchema augment = augmentations.iterator().next();
+
+        Set<DataSchemaNode> augmentChildren = augment.getChildNodes();
+        assertEquals(5, augmentChildren.size());
+        for(DataSchemaNode dsn : augmentChildren) {
+            assertTrue(dsn.isAugmenting());
+        }
+
+        LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augment.getDataChildByName("ds0ChannelNumber");
+        LeafSchemaNode interfaceId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
+        LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
+        ContainerSchemaNode schemas = (ContainerSchemaNode) augment.getDataChildByName("schemas");
+        ChoiceNode odl = (ChoiceNode)augment.getDataChildByName("odl");
+
+        assertNotNull(ds0ChannelNumber);
+        assertNotNull(interfaceId);
+        assertNotNull(myType);
+        assertNotNull(schemas);
+        assertNotNull(odl);
+
+        qnames = new QName[4];
+        qnames[0] = q0;
+        qnames[1] = q1;
+        qnames[2] = q2;
+
+        // leaf ds0ChannelNumber
+        qnames[3] = new QName(types1NS, types1Rev, t1, "ds0ChannelNumber");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, ds0ChannelNumber.getPath());
+
+        // leaf interface-id
+        qnames[3] = new QName(types1NS, types1Rev, t1, "interface-id");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, interfaceId.getPath());
+
+        // leaf my-type
+        qnames[3] = new QName(types1NS, types1Rev, t1, "my-type");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, myType.getPath());
+
+        // container schemas
+        qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, schemas.getPath());
+
+        // choice odl
+        qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, odl.getPath());
+
+
+        // testfile3
+        Module module3 = TestUtils.findModule(modules, "custom");
+        augmentations = module3.getAugmentations();
+        assertEquals(3, augmentations.size());
+        AugmentationSchema augment1 = null;
+        AugmentationSchema augment2 = null;
+        AugmentationSchema augment3 = null;
+        for (AugmentationSchema as : augmentations) {
+            if("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
+                augment1 = as;
+            } else if("if:ifType='ds2'".equals(as.getWhenCondition().toString())) {
+                augment2 = as;
+            } else if ("if:leafType='ds1'".equals(as.getWhenCondition().toString())) {
+                augment3 = as;
+            }
+        }
+        assertNotNull(augment1);
+        assertNotNull(augment2);
+        assertNotNull(augment3);
+
+        assertEquals(1, augment1.getChildNodes().size());
+        ContainerSchemaNode augmentHolder = (ContainerSchemaNode) augment1.getDataChildByName("augment-holder");
+        assertTrue(augmentHolder.isAugmenting());
+
+        assertEquals(1, augment2.getChildNodes().size());
+        ContainerSchemaNode augmentHolder2 = (ContainerSchemaNode) augment2.getDataChildByName("augment-holder2");
+        assertTrue(augmentHolder2.isAugmenting());
+
+        assertEquals(1, augment3.getChildNodes().size());
+        LeafSchemaNode linkleaf = (LeafSchemaNode) augment3.getDataChildByName("linkleaf");
+        assertTrue(linkleaf.isAugmenting());
+    }
+
+    @Test
+    public void testAugmentResolving() throws ParseException {
+        SchemaPath expectedPath = null;
+        QName[] qnames = null;
+
+        Module module2 = TestUtils.findModule(modules, "types");
+        ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
+        ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+        ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
+
+        // testfile1.yang
+        // augment "/data:interfaces/data:ifEntry/t3:augment-holder"
+        LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augmentedContainer.getDataChildByName("ds0ChannelNumber");
+        LeafSchemaNode interfaceId = (LeafSchemaNode) augmentedContainer.getDataChildByName("interface-id");
+        LeafSchemaNode myType = (LeafSchemaNode) augmentedContainer.getDataChildByName("my-type");
+        ContainerSchemaNode schemas = (ContainerSchemaNode) augmentedContainer.getDataChildByName("schemas");
+        ChoiceNode odl = (ChoiceNode)augmentedContainer.getDataChildByName("odl");
+
+        assertNotNull(ds0ChannelNumber);
+        assertNotNull(interfaceId);
+        assertNotNull(myType);
+        assertNotNull(schemas);
+        assertNotNull(odl);
+
+        qnames = new QName[4];
+        qnames[0] = q0;
+        qnames[1] = q1;
+        qnames[2] = q2;
+
+        // leaf ds0ChannelNumber
+        qnames[3] = new QName(types1NS, types1Rev, t1, "ds0ChannelNumber");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, ds0ChannelNumber.getPath());
+
+        // leaf interface-id
+        qnames[3] = new QName(types1NS, types1Rev, t1, "interface-id");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, interfaceId.getPath());
+
+        // leaf my-type
+        qnames[3] = new QName(types1NS, types1Rev, t1, "my-type");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, myType.getPath());
+
+        // container schemas
+        qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, schemas.getPath());
+
+        // choice odl
+        qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, odl.getPath());
+
+        // testfile3.yang
+        // augment "/data:interfaces/data:ifEntry/t3:augment-holder/t1:schemas"
+        LeafSchemaNode linkleaf = (LeafSchemaNode) schemas.getDataChildByName("linkleaf");
+        assertNotNull(linkleaf);
+
+        qnames = new QName[5];
+        qnames[0] = q0;
+        qnames[1] = q1;
+        qnames[2] = q2;
+        qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+        qnames[4] = new QName(types3NS, types3Rev, t3, "linkleaf");
+        expectedPath = new SchemaPath(Arrays.asList(qnames), true);
+        assertEquals(expectedPath, linkleaf.getPath());
+    }
+
+    @Test
+    public void testAugmentChoice() throws ParseException {
+        SchemaPath expectedPath = null;
+        QName[] qnames = null;
+
+        Module module2 = TestUtils.findModule(modules, "types");
+        ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
+        ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+        ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
+
+        // testfile1.yang
+        // augment "/data:interfaces/data:ifEntry/t3:augment-holder"
+        ChoiceNode odl = (ChoiceNode)augmentedContainer.getDataChildByName("odl");
+        assertNotNull(odl);
+        Set<ChoiceCaseNode> cases = odl.getCases();
+        assertEquals(4, cases.size());
+
+        ChoiceCaseNode id = null;
+        ChoiceCaseNode node1 = null;
+        ChoiceCaseNode node2 = null;
+        ChoiceCaseNode node3 = null;
+
+        for(ChoiceCaseNode ccn : cases) {
+            if("id".equals(ccn.getQName().getLocalName())) {
+                id = ccn;
+            } else if("node1".equals(ccn.getQName().getLocalName())) {
+                node1 = ccn;
+            } else if("node2".equals(ccn.getQName().getLocalName())) {
+                node2 = ccn;
+            } else if("node3".equals(ccn.getQName().getLocalName())) {
+                node3 = ccn;
+            }
+        }
+
+        assertNotNull(id);
+        assertNotNull(node1);
+        assertNotNull(node2);
+        assertNotNull(node3);
+
+        qnames = new QName[5];
+        qnames[0] = q0;
+        qnames[1] = q1;
+        qnames[2] = q2;
+        qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+
+        // case id
+        qnames[4] = new QName(types1NS, types1Rev, t1, "id");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, id.getPath());
+        Set<DataSchemaNode> idChildren = id.getChildNodes();
+        assertEquals(1, idChildren.size());
+
+        // case node1
+        qnames[4] = new QName(types1NS, types1Rev, t1, "node1");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, node1.getPath());
+        Set<DataSchemaNode> node1Children = node1.getChildNodes();
+        assertTrue(node1Children.isEmpty());
+
+        // case node2
+        qnames[4] = new QName(types1NS, types1Rev, t1, "node2");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, node2.getPath());
+        Set<DataSchemaNode> node2Children = node2.getChildNodes();
+        assertTrue(node2Children.isEmpty());
+
+        // case node3
+        qnames[4] = new QName(types1NS, types1Rev, t1, "node3");
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, node3.getPath());
+        Set<DataSchemaNode> node3Children = node3.getChildNodes();
+        assertEquals(1, node3Children.size());
+
+        // test cases
+        qnames = new QName[6];
+        qnames[0] = q0;
+        qnames[1] = q1;
+        qnames[2] = q2;
+        qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+
+        // case id child
+        qnames[4] = new QName(types1NS, types1Rev, t1, "id");
+        qnames[5] = new QName(types1NS, types1Rev, t1, "id");
+        LeafSchemaNode caseIdChild = (LeafSchemaNode)idChildren.iterator().next();
+        assertNotNull(caseIdChild);
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, caseIdChild.getPath());
+
+        // case node3 child
+        qnames[4] = new QName(types1NS, types1Rev, t1, "node3");
+        qnames[5] = new QName(types1NS, types1Rev, t1, "node3");
+        ContainerSchemaNode caseNode3Child = (ContainerSchemaNode)node3Children.iterator().next();
+        assertNotNull(caseNode3Child);
+        expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+        assertEquals(expectedPath, caseNode3Child.getPath());
+    }
+
+    @Test
+    public void testAugmentNodesTypeSchemaPath() throws Exception {
+        Module testModule = TestUtils.findModule(modules, "nodes");
+        Set<AugmentationSchema> augments = testModule.getAugmentations();
+        assertEquals(1, augments.size());
+        AugmentationSchema augment = augments.iterator().next();
+
+        LeafSchemaNode ifcId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
+        Leafref ifcIdType = (Leafref) ifcId.getType();
+        SchemaPath ifcIdTypeSchemaPath = ifcIdType.getPath();
+        List<QName> ifcIdTypePath = ifcIdTypeSchemaPath.getPath();
+
+        Date expectedDate = simpleDateFormat.parse("2013-02-27");
+
+        QName q3 = new QName(types1NS, expectedDate, "data", "interface-id");
+        assertEquals(q0, ifcIdTypePath.get(0));
+        assertEquals(q1, ifcIdTypePath.get(1));
+        assertEquals(q2, ifcIdTypePath.get(2));
+        assertEquals(q3, ifcIdTypePath.get(3));
+
+        LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
+        ExtendedType leafType = (ExtendedType) myType.getType();
+
+        testModule = TestUtils.findModule(modules, "types");
+        TypeDefinition<?> typedef = TestUtils.findTypedef(testModule.getTypeDefinitions(), "int32-ext2");
+
+        assertEquals(typedef, leafType);
+    }
+
+}
index 2442f51da3d62f90fb521eb2339477d31e4314e3..88d7543520cf79b5b6446c11deaf52fb11b1582b 100644 (file)
@@ -43,7 +43,7 @@ public class GroupingTest {
 
     @Test
     public void testRefine() {
-        Module testModule = TestUtils.findModule(modules, "types2");
+        Module testModule = TestUtils.findModule(modules, "nodes");
 
         ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
         ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
@@ -119,7 +119,7 @@ public class GroupingTest {
 
     @Test
     public void testGrouping() {
-        Module testModule = TestUtils.findModule(modules, "types2");
+        Module testModule = TestUtils.findModule(modules, "custom");
         Set<GroupingDefinition> groupings = testModule.getGroupings();
         assertEquals(1, groupings.size());
         GroupingDefinition grouping = groupings.iterator().next();
@@ -132,13 +132,15 @@ public class GroupingTest {
         // suffix _u = added by uses
         // suffix _g = defined in grouping
 
-        Module testModule = TestUtils.findModule(modules, "types2");
+        Module testModule = TestUtils.findModule(modules, "custom");
 
         // get grouping
         Set<GroupingDefinition> groupings = testModule.getGroupings();
         assertEquals(1, groupings.size());
         GroupingDefinition grouping = groupings.iterator().next();
 
+        testModule = TestUtils.findModule(modules, "nodes");
+
         // get node containing uses
         ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
         ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
index 3eff948d8b65b81df3c776d2f2507d68eaa466bb..f2478e741dddeb3dd65db2740f334e599ffe0274 100644 (file)
@@ -34,7 +34,6 @@ import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
 import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
 import org.opendaylight.controller.yang.model.api.FeatureDefinition;
 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
-import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
 import org.opendaylight.controller.yang.model.api.Module;
@@ -52,42 +51,51 @@ import org.opendaylight.controller.yang.model.util.Decimal64;
 import org.opendaylight.controller.yang.model.util.ExtendedType;
 import org.opendaylight.controller.yang.model.util.Int16;
 import org.opendaylight.controller.yang.model.util.Int32;
-import org.opendaylight.controller.yang.model.util.Int8;
-import org.opendaylight.controller.yang.model.util.Leafref;
 import org.opendaylight.controller.yang.model.util.StringType;
 import org.opendaylight.controller.yang.model.util.Uint32;
 import org.opendaylight.controller.yang.model.util.UnionType;
 
 public class YangParserTest {
+
+    private final URI nodesNS = URI.create("urn:simple.nodes.test");
+    private final URI typesNS = URI.create("urn:simple.types.test");
+    private final URI customNS = URI.create("urn:custom.nodes.test");
+    private Date nodesRev;
+    private Date typesRev;
+    private Date customRev;
+
     private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
     private Set<Module> modules;
 
     @Before
-    public void init() throws FileNotFoundException {
+    public void init() throws FileNotFoundException, ParseException {
+        nodesRev = simpleDateFormat.parse("2013-02-27");
+        typesRev = simpleDateFormat.parse("2013-07-03");
+        customRev = simpleDateFormat.parse("2013-02-27");
+
         modules = TestUtils.loadModules(getClass().getResource("/model").getPath());
         assertEquals(3, modules.size());
     }
 
     @Test
-    public void testHeaders() {
-        Module test = TestUtils.findModule(modules, "types1");
+    public void testHeaders() throws ParseException {
+        Module test = TestUtils.findModule(modules, "nodes");
 
-        assertEquals("types1", test.getName());
+        assertEquals("nodes", test.getName());
         assertEquals("1", test.getYangVersion());
-        URI expectedNamespace = URI.create("urn:simple.container.demo");
-        assertEquals(expectedNamespace, test.getNamespace());
-        assertEquals("t1", test.getPrefix());
+        assertEquals(nodesNS, test.getNamespace());
+        assertEquals("n", test.getPrefix());
 
         Set<ModuleImport> imports = test.getImports();
         assertEquals(2, imports.size());
 
-        ModuleImport import2 = TestUtils.findImport(imports, "data");
-        assertEquals("types2", import2.getModuleName());
-        assertEquals(TestUtils.createDate("2013-02-27"), import2.getRevision());
+        ModuleImport import2 = TestUtils.findImport(imports, "t");
+        assertEquals("types", import2.getModuleName());
+        assertEquals(typesRev, import2.getRevision());
 
-        ModuleImport import3 = TestUtils.findImport(imports, "t3");
-        assertEquals("types3", import3.getModuleName());
-        assertEquals(TestUtils.createDate("2013-02-27"), import3.getRevision());
+        ModuleImport import3 = TestUtils.findImport(imports, "c");
+        assertEquals("custom", import3.getModuleName());
+        assertEquals(customRev, import3.getRevision());
 
         assertEquals("opendaylight", test.getOrganization());
         assertEquals("http://www.opendaylight.org/", test.getContact());
@@ -98,12 +106,10 @@ public class YangParserTest {
 
     @Test
     public void testOrderingTypedef() {
-        Module test = TestUtils.findModule(modules, "types2");
+        Module test = TestUtils.findModule(modules, "types");
         Set<TypeDefinition<?>> typedefs = test.getTypeDefinitions();
-        String[] expectedOrder = new String[] { "my-base-int32-type", "my-custom-string", "my-decimal-type",
-                "my-decimal-type-ext", "my-int-type", "my-int-type-ext", "my-int-type2", "my-string-type",
-                "my-string-type-ext", "my-string-type2", "my-type1", "my-union", "my-union-ext", "nested-union1",
-                "nested-union2" };
+        String[] expectedOrder = new String[] { "int32-ext1", "int32-ext2", "my-decimal-type", "my-union",
+                "my-union-ext", "nested-union2", "string-ext1", "string-ext2", "string-ext3", "string-ext4" };
         String[] actualOrder = new String[typedefs.size()];
 
         int i = 0;
@@ -116,23 +122,31 @@ public class YangParserTest {
 
     @Test
     public void testOrderingChildNodes() {
-        Module test = TestUtils.findModule(modules, "types2");
-        Set<DataSchemaNode> childNodes = test.getChildNodes();
-        String[] expectedOrder = new String[] { "count", "if-name", "interfaces", "name", "nested-type-leaf", "peer",
-                "system" };
-        String[] actualOrder = new String[childNodes.size()];
+        Module test = TestUtils.findModule(modules, "nodes");
+        AugmentationSchema augment1 = null;
+        for (AugmentationSchema as : test.getAugmentations()) {
+            if ("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
+                augment1 = as;
+                break;
+            }
+        }
+        assertNotNull(augment1);
+
+        String[] expectedOrder = new String[] { "ds0ChannelNumber", "interface-id", "my-type", "odl", "schemas" };
+        String[] actualOrder = new String[expectedOrder.length];
 
         int i = 0;
-        for (DataSchemaNode child : childNodes) {
-            actualOrder[i] = child.getQName().getLocalName();
+        for (DataSchemaNode augmentChild : augment1.getChildNodes()) {
+            actualOrder[i] = augmentChild.getQName().getLocalName();
             i++;
         }
+
         assertArrayEquals(expectedOrder, actualOrder);
     }
 
     @Test
     public void testOrderingNestedChildNodes() {
-        Module test = TestUtils.findModule(modules, "types2");
+        Module test = TestUtils.findModule(modules, "custom");
         Set<GroupingDefinition> groupings = test.getGroupings();
         assertEquals(1, groupings.size());
         GroupingDefinition target = groupings.iterator().next();
@@ -151,17 +165,15 @@ public class YangParserTest {
 
     @Test
     public void testParseContainer() {
-        Module test = TestUtils.findModule(modules, "types2");
-        URI expectedNamespace = URI.create("urn:simple.types.data.demo");
-        String expectedPrefix = "t2";
-        Date expectedRevision = TestUtils.createDate("2013-02-27");
+        Module test = TestUtils.findModule(modules, "types");
+        URI expectedNamespace = URI.create("urn:simple.types.test");
+        String expectedPrefix = "t";
 
         ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
         // test SchemaNode args
-        QName expectedQName = new QName(expectedNamespace, expectedRevision, expectedPrefix, "interfaces");
+        QName expectedQName = new QName(expectedNamespace, typesRev, expectedPrefix, "interfaces");
         assertEquals(expectedQName, interfaces.getQName());
-        SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, expectedRevision, expectedPrefix,
-                "interfaces");
+        SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, typesRev, expectedPrefix, "interfaces");
         assertEquals(expectedPath, interfaces.getPath());
         assertNull(interfaces.getDescription());
         assertNull(interfaces.getReference());
@@ -192,19 +204,18 @@ public class YangParserTest {
 
     @Test
     public void testParseList() {
-        Module test = TestUtils.findModule(modules, "types2");
-        URI expectedNamespace = URI.create("urn:simple.types.data.demo");
-        String expectedPrefix = "t2";
-        Date expectedRevision = TestUtils.createDate("2013-02-27");
+        Module test = TestUtils.findModule(modules, "types");
+        URI expectedNamespace = URI.create("urn:simple.types.test");
+        String expectedPrefix = "t";
 
         ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
 
         ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
         // test SchemaNode args
-        QName expectedQName = new QName(expectedNamespace, expectedRevision, expectedPrefix, "ifEntry");
+        QName expectedQName = new QName(expectedNamespace, typesRev, expectedPrefix, "ifEntry");
         assertEquals(expectedQName, ifEntry.getQName());
-        SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, expectedRevision, expectedPrefix,
-                "interfaces", "ifEntry");
+        SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, typesRev, expectedPrefix, "interfaces",
+                "ifEntry");
         assertEquals(expectedPath, ifEntry.getPath());
         assertNull(ifEntry.getDescription());
         assertNull(ifEntry.getReference());
@@ -224,7 +235,7 @@ public class YangParserTest {
         assertEquals(2, availableAugmentations.size());
         // test ListSchemaNode args
         List<QName> expectedKey = new ArrayList<QName>();
-        expectedKey.add(new QName(expectedNamespace, expectedRevision, expectedPrefix, "ifIndex"));
+        expectedKey.add(new QName(expectedNamespace, typesRev, expectedPrefix, "ifIndex"));
         assertEquals(expectedKey, ifEntry.getKeyDefinition());
         assertFalse(ifEntry.isUserOrdered());
         // test DataNodeContainer args
@@ -239,237 +250,228 @@ public class YangParserTest {
         assertTrue(ifMtu.getType() instanceof Int32);
     }
 
-    @Test
-    public void testParseLeaf() throws ParseException {
-        Module test = TestUtils.findModule(modules, "types2");
-
-        // leaf if-name
-        LeafSchemaNode ifName = (LeafSchemaNode) test.getDataChildByName("if-name");
-        Leafref ifNameType = (Leafref) ifName.getType();
-        QName qname = ifNameType.getQName();
-
-        URI baseYangTypeNS = URI.create("urn:ietf:params:xml:ns:yang:1");
-        assertEquals(baseYangTypeNS, qname.getNamespace());
-        assertNull(qname.getRevision());
-        assertEquals("", qname.getPrefix());
-        assertEquals("leafref", qname.getLocalName());
-
-        // leaf name
-        LeafSchemaNode name = (LeafSchemaNode) test.getDataChildByName("name");
-        StringType nameType = (StringType) name.getType();
-        QName nameQName = nameType.getQName();
-
-        assertEquals(baseYangTypeNS, nameQName.getNamespace());
-        assertNull(nameQName.getRevision());
-        assertEquals("", nameQName.getPrefix());
-        assertEquals("string", nameQName.getLocalName());
-
-        // leaf count
-        LeafSchemaNode count = (LeafSchemaNode) test.getDataChildByName("count");
-        ExtendedType countType = (ExtendedType) count.getType();
-        QName countTypeQName = countType.getQName();
-
-        URI expectedNS = URI.create("urn:simple.types.data.demo");
-        Date expectedDate = simpleDateFormat.parse("2013-02-27");
-        assertEquals(expectedNS, countTypeQName.getNamespace());
-        assertEquals(expectedDate, countTypeQName.getRevision());
-        assertEquals("t2", countTypeQName.getPrefix());
-        assertEquals("int8", countTypeQName.getLocalName());
-
-        Int8 countTypeBase = (Int8) countType.getBaseType();
-        QName countTypeBaseQName = countTypeBase.getQName();
-
-        assertEquals(baseYangTypeNS, countTypeBaseQName.getNamespace());
-        assertNull(countTypeBaseQName.getRevision());
-        assertEquals("", countTypeBaseQName.getPrefix());
-        assertEquals("int8", countTypeBaseQName.getLocalName());
-    }
-
-    @Test
-    public void testAugmentResolving() {
-        // testfile1
-        Module module1 = TestUtils.findModule(modules, "types1");
-
-        Set<AugmentationSchema> module1Augmentations = module1.getAugmentations();
-        AugmentationSchema augment1 = module1Augmentations.iterator().next();
-        LeafSchemaNode augmentedLeafDefinition = (LeafSchemaNode) augment1.getDataChildByName("ds0ChannelNumber");
-        assertTrue(augmentedLeafDefinition.isAugmenting());
-
-        // testfile2
-        Module module2 = TestUtils.findModule(modules, "types2");
-
-        ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
-        ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
-        ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
-
-        ContainerSchemaNode schemas = (ContainerSchemaNode) augmentedContainer.getDataChildByName("schemas");
-        LeafSchemaNode linkleaf = (LeafSchemaNode) schemas.getDataChildByName("linkleaf");
-        assertNotNull(linkleaf);
-
-        // augmentation defined in testfile1 and augmentation returned from
-        // augmented container have to be same
-        Set<AugmentationSchema> augmentedContainerAugments = augmentedContainer.getAvailableAugmentations();
-        AugmentationSchema augmentDefinition = augmentedContainerAugments.iterator().next();
-        assertEquals(augment1, augmentDefinition);
-
-        LeafSchemaNode augmentedLeaf = (LeafSchemaNode) augmentedContainer.getDataChildByName("ds0ChannelNumber");
-        assertTrue(augmentedLeaf.isAugmenting());
-        assertEquals(augmentedLeafDefinition, augmentedLeaf);
-
-        Set<AugmentationSchema> ifEntryAugments = ifEntry.getAvailableAugmentations();
-        assertEquals(2, ifEntryAugments.size());
-
-        // testfile3
-        Module module3 = TestUtils.findModule(modules, "types3");
-
-        Set<AugmentationSchema> module3Augmentations = module3.getAugmentations();
-        assertEquals(3, module3Augmentations.size());
-        AugmentationSchema augment3 = null;
-        for (AugmentationSchema as : module3Augmentations) {
-            if ("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
-                augment3 = as;
-            }
-        }
-        ContainerSchemaNode augmentedContainerDefinition = (ContainerSchemaNode) augment3
-                .getDataChildByName("augment-holder");
-        assertTrue(augmentedContainerDefinition.isAugmenting());
-
-        // check
-        assertEquals(augmentedContainer, augmentedContainerDefinition);
-        assertEquals(augmentedLeaf, augmentedLeafDefinition);
-    }
-
-    @Test
-    public void testAugmentTarget() {
-        Module test = TestUtils.findModule(modules, "types2");
-
-        ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
-        ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
-        Set<AugmentationSchema> augmentations = ifEntry.getAvailableAugmentations();
-        assertEquals(2, augmentations.size());
-
-        AugmentationSchema augment = null;
-        for (AugmentationSchema as : augmentations) {
-            if ("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
-                augment = as;
-            }
-        }
-        ContainerSchemaNode augmentHolder = (ContainerSchemaNode) augment.getDataChildByName("augment-holder");
-        assertNotNull(augmentHolder);
-        assertTrue(augmentHolder.isAugmenting());
-        QName augmentHolderQName = augmentHolder.getQName();
-        assertEquals("augment-holder", augmentHolderQName.getLocalName());
-        assertEquals("t3", augmentHolderQName.getPrefix());
-        assertEquals("Description for augment holder", augmentHolder.getDescription());
-    }
-
     @Test
     public void testTypedefRangesResolving() throws ParseException {
-        Module testModule = TestUtils.findModule(modules, "types1");
+        Module testModule = TestUtils.findModule(modules, "nodes");
+        LeafSchemaNode int32Leaf = (LeafSchemaNode) testModule.getDataChildByName("int32-leaf");
 
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("testleaf");
-        ExtendedType leafType = (ExtendedType) testleaf.getType();
+        ExtendedType leafType = (ExtendedType) int32Leaf.getType();
         QName leafTypeQName = leafType.getQName();
-        assertEquals("my-type1", leafTypeQName.getLocalName());
-        assertEquals("t1", leafTypeQName.getPrefix());
-        assertEquals(URI.create("urn:simple.container.demo"), leafTypeQName.getNamespace());
-        Date expectedDate = simpleDateFormat.parse("2013-02-27");
-        assertEquals(expectedDate, leafTypeQName.getRevision());
-        assertEquals(1, leafType.getRanges().size());
-
-        ExtendedType baseType = (ExtendedType) leafType.getBaseType();
-        QName baseTypeQName = baseType.getQName();
-        assertEquals("my-type1", baseTypeQName.getLocalName());
-        assertEquals("t2", baseTypeQName.getPrefix());
-        assertEquals(URI.create("urn:simple.types.data.demo"), baseTypeQName.getNamespace());
-        assertEquals(expectedDate, baseTypeQName.getRevision());
-        assertEquals(2, baseType.getRanges().size());
-
+        assertEquals("int32-ext2", leafTypeQName.getLocalName());
+        assertEquals("n", leafTypeQName.getPrefix());
+        assertEquals(nodesNS, leafTypeQName.getNamespace());
+        assertEquals(nodesRev, leafTypeQName.getRevision());
+        assertNull(leafType.getUnits());
+        assertNull(leafType.getDefaultValue());
+        assertTrue(leafType.getLengths().isEmpty());
+        assertTrue(leafType.getPatterns().isEmpty());
         List<RangeConstraint> ranges = leafType.getRanges();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
         assertEquals(12L, range.getMin());
         assertEquals(20L, range.getMax());
+
+        ExtendedType baseType = (ExtendedType) leafType.getBaseType();
+        QName baseTypeQName = baseType.getQName();
+        assertEquals("int32-ext2", baseTypeQName.getLocalName());
+        assertEquals("t", baseTypeQName.getPrefix());
+        assertEquals(typesNS, baseTypeQName.getNamespace());
+        assertEquals(typesRev, baseTypeQName.getRevision());
+        assertEquals("mile", baseType.getUnits());
+        assertEquals("11", baseType.getDefaultValue());
+        assertTrue(leafType.getLengths().isEmpty());
+        assertTrue(leafType.getPatterns().isEmpty());
+        List<RangeConstraint> baseTypeRanges = baseType.getRanges();
+        assertEquals(2, baseTypeRanges.size());
+        RangeConstraint baseTypeRange1 = baseTypeRanges.get(0);
+        assertEquals(3L, baseTypeRange1.getMin());
+        assertEquals(9L, baseTypeRange1.getMax());
+        RangeConstraint baseTypeRange2 = baseTypeRanges.get(1);
+        assertEquals(11L, baseTypeRange2.getMin());
+        assertEquals(20L, baseTypeRange2.getMax());
+
+        ExtendedType base = (ExtendedType) baseType.getBaseType();
+        QName baseQName = base.getQName();
+        assertEquals("int32-ext1", baseQName.getLocalName());
+        assertEquals("t", baseQName.getPrefix());
+        assertEquals(typesNS, baseQName.getNamespace());
+        assertEquals(typesRev, baseQName.getRevision());
+        assertNull(base.getUnits());
+        assertNull(base.getDefaultValue());
+        assertTrue(leafType.getLengths().isEmpty());
+        assertTrue(leafType.getPatterns().isEmpty());
+        List<RangeConstraint> baseRanges = base.getRanges();
+        assertEquals(1, baseRanges.size());
+        RangeConstraint baseRange = baseRanges.get(0);
+        assertEquals(2L, baseRange.getMin());
+        assertEquals(20L, baseRange.getMax());
+
+        assertTrue(base.getBaseType() instanceof Int32);
     }
 
     @Test
     public void testTypedefPatternsResolving() {
-        Module testModule = TestUtils.findModule(modules, "types1");
-
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("test-string-leaf");
-        ExtendedType testleafType = (ExtendedType) testleaf.getType();
-        QName testleafTypeQName = testleafType.getQName();
-        assertEquals("my-string-type-ext", testleafTypeQName.getLocalName());
-        assertEquals("t2", testleafTypeQName.getPrefix());
-
-        List<PatternConstraint> patterns = testleafType.getPatterns();
+        Module testModule = TestUtils.findModule(modules, "nodes");
+        LeafSchemaNode stringleaf = (LeafSchemaNode) testModule.getDataChildByName("string-leaf");
+
+        ExtendedType type = (ExtendedType) stringleaf.getType();
+        QName typeQName = type.getQName();
+        assertEquals("string-ext4", typeQName.getLocalName());
+        assertEquals("t", typeQName.getPrefix());
+        assertEquals(typesNS, typeQName.getNamespace());
+        assertEquals(typesRev, typeQName.getRevision());
+        assertNull(type.getUnits());
+        assertNull(type.getDefaultValue());
+        List<PatternConstraint> patterns = type.getPatterns();
         assertEquals(1, patterns.size());
         PatternConstraint pattern = patterns.iterator().next();
         assertEquals("[e-z]*", pattern.getRegularExpression());
-
-        ExtendedType baseType = (ExtendedType) testleafType.getBaseType();
-        assertEquals("my-string-type2", baseType.getQName().getLocalName());
-
-        patterns = baseType.getPatterns();
+        assertTrue(type.getLengths().isEmpty());
+        assertTrue(type.getRanges().isEmpty());
+
+        ExtendedType baseType1 = (ExtendedType) type.getBaseType();
+        QName baseType1QName = baseType1.getQName();
+        assertEquals("string-ext3", baseType1QName.getLocalName());
+        assertEquals("t", baseType1QName.getPrefix());
+        assertEquals(typesNS, baseType1QName.getNamespace());
+        assertEquals(typesRev, baseType1QName.getRevision());
+        assertNull(baseType1.getUnits());
+        assertNull(baseType1.getDefaultValue());
+        patterns = baseType1.getPatterns();
         assertEquals(1, patterns.size());
         pattern = patterns.iterator().next();
         assertEquals("[b-u]*", pattern.getRegularExpression());
-
-        List<LengthConstraint> lengths = testleafType.getLengths();
-        assertTrue(lengths.isEmpty());
+        assertTrue(baseType1.getLengths().isEmpty());
+        assertTrue(baseType1.getRanges().isEmpty());
+
+        ExtendedType baseType2 = (ExtendedType) baseType1.getBaseType();
+        QName baseType2QName = baseType2.getQName();
+        assertEquals("string-ext2", baseType2QName.getLocalName());
+        assertEquals("t", baseType2QName.getPrefix());
+        assertEquals(typesNS, baseType2QName.getNamespace());
+        assertEquals(typesRev, baseType2QName.getRevision());
+        assertNull(baseType2.getUnits());
+        assertNull(baseType2.getDefaultValue());
+        assertTrue(baseType2.getPatterns().isEmpty());
+        List<LengthConstraint> baseType2Lengths = baseType2.getLengths();
+        assertEquals(1, baseType2Lengths.size());
+        LengthConstraint length = baseType2Lengths.get(0);
+        assertEquals(6L, length.getMin());
+        assertEquals(10L, length.getMax());
+        assertTrue(baseType2.getRanges().isEmpty());
+
+        ExtendedType baseType3 = (ExtendedType) baseType2.getBaseType();
+        QName baseType3QName = baseType3.getQName();
+        assertEquals("string-ext1", baseType3QName.getLocalName());
+        assertEquals("t", baseType3QName.getPrefix());
+        assertEquals(typesNS, baseType3QName.getNamespace());
+        assertEquals(typesRev, baseType3QName.getRevision());
+        assertNull(baseType3.getUnits());
+        assertNull(baseType3.getDefaultValue());
+        patterns = baseType3.getPatterns();
+        assertEquals(1, patterns.size());
+        pattern = patterns.iterator().next();
+        assertEquals("[a-k]*", pattern.getRegularExpression());
+        List<LengthConstraint> baseType3Lengths = baseType3.getLengths();
+        assertEquals(1, baseType3Lengths.size());
+        length = baseType3Lengths.get(0);
+        assertEquals(5L, length.getMin());
+        assertEquals(11L, length.getMax());
+        assertTrue(baseType3.getRanges().isEmpty());
+
+        assertTrue(baseType3.getBaseType() instanceof StringType);
     }
 
     @Test
     public void testTypedefLengthsResolving() {
-        Module testModule = TestUtils.findModule(modules, "types1");
-
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("leaf-with-length");
-        ExtendedType testleafType = (ExtendedType) testleaf.getType();
-        assertEquals("my-string-type", testleafType.getQName().getLocalName());
-
-        List<LengthConstraint> lengths = testleafType.getLengths();
-        assertEquals(1, lengths.size());
-
-        LengthConstraint length = lengths.get(0);
+        Module testModule = TestUtils.findModule(modules, "nodes");
+
+        LeafSchemaNode lengthLeaf = (LeafSchemaNode) testModule.getDataChildByName("length-leaf");
+        ExtendedType type = (ExtendedType) lengthLeaf.getType();
+
+        QName typeQName = type.getQName();
+        assertEquals("string-ext2", typeQName.getLocalName());
+        assertEquals("n", typeQName.getPrefix());
+        assertEquals(nodesNS, typeQName.getNamespace());
+        assertEquals(nodesRev, typeQName.getRevision());
+        assertNull(type.getUnits());
+        assertNull(type.getDefaultValue());
+        assertTrue(type.getPatterns().isEmpty());
+        List<LengthConstraint> typeLengths = type.getLengths();
+        assertEquals(1, typeLengths.size());
+        LengthConstraint length = typeLengths.get(0);
         assertEquals(7L, length.getMin());
         assertEquals(10L, length.getMax());
-    }
-
-    @Test
-    public void testTypeDef() {
-        Module testModule = TestUtils.findModule(modules, "types2");
-
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("nested-type-leaf");
-        ExtendedType testleafType = (ExtendedType) testleaf.getType();
-        assertEquals("my-type1", testleafType.getQName().getLocalName());
-
-        ExtendedType baseType = (ExtendedType) testleafType.getBaseType();
-        assertEquals("my-base-int32-type", baseType.getQName().getLocalName());
-
-        Int32 int32Type = (Int32) baseType.getBaseType();
-        QName qname = int32Type.getQName();
-        assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), qname.getNamespace());
-        assertNull(qname.getRevision());
-        assertEquals("", qname.getPrefix());
-        assertEquals("int32", qname.getLocalName());
-        List<RangeConstraint> ranges = baseType.getRanges();
-        assertEquals(1, ranges.size());
-        RangeConstraint range = ranges.get(0);
-        assertEquals(2L, range.getMin());
-        assertEquals(20L, range.getMax());
+        assertTrue(type.getRanges().isEmpty());
+
+        ExtendedType baseType1 = (ExtendedType) type.getBaseType();
+        QName baseType1QName = baseType1.getQName();
+        assertEquals("string-ext2", baseType1QName.getLocalName());
+        assertEquals("t", baseType1QName.getPrefix());
+        assertEquals(typesNS, baseType1QName.getNamespace());
+        assertEquals(typesRev, baseType1QName.getRevision());
+        assertNull(baseType1.getUnits());
+        assertNull(baseType1.getDefaultValue());
+        assertTrue(baseType1.getPatterns().isEmpty());
+        List<LengthConstraint> baseType2Lengths = baseType1.getLengths();
+        assertEquals(1, baseType2Lengths.size());
+        length = baseType2Lengths.get(0);
+        assertEquals(6L, length.getMin());
+        assertEquals(10L, length.getMax());
+        assertTrue(baseType1.getRanges().isEmpty());
+
+        ExtendedType baseType2 = (ExtendedType) baseType1.getBaseType();
+        QName baseType2QName = baseType2.getQName();
+        assertEquals("string-ext1", baseType2QName.getLocalName());
+        assertEquals("t", baseType2QName.getPrefix());
+        assertEquals(typesNS, baseType2QName.getNamespace());
+        assertEquals(typesRev, baseType2QName.getRevision());
+        assertNull(baseType2.getUnits());
+        assertNull(baseType2.getDefaultValue());
+        List<PatternConstraint> patterns = baseType2.getPatterns();
+        assertEquals(1, patterns.size());
+        PatternConstraint pattern = patterns.iterator().next();
+        assertEquals("[a-k]*", pattern.getRegularExpression());
+        List<LengthConstraint> baseType3Lengths = baseType2.getLengths();
+        assertEquals(1, baseType3Lengths.size());
+        length = baseType3Lengths.get(0);
+        assertEquals(5L, length.getMin());
+        assertEquals(11L, length.getMax());
+        assertTrue(baseType2.getRanges().isEmpty());
+
+        assertTrue(baseType2.getBaseType() instanceof StringType);
     }
 
     @Test
     public void testTypedefDecimal1() {
-        Module testModule = TestUtils.findModule(modules, "types1");
+        Module testModule = TestUtils.findModule(modules, "nodes");
+        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("decimal-leaf");
 
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("test-decimal-leaf");
         ExtendedType type = (ExtendedType) testleaf.getType();
+        QName typeQName = type.getQName();
+        assertEquals("my-decimal-type", typeQName.getLocalName());
+        assertEquals("n", typeQName.getPrefix());
+        assertEquals(nodesNS, typeQName.getNamespace());
+        assertEquals(nodesRev, typeQName.getRevision());
+        assertNull(type.getUnits());
+        assertNull(type.getDefaultValue());
         assertEquals(4, (int) type.getFractionDigits());
+        assertTrue(type.getLengths().isEmpty());
+        assertTrue(type.getPatterns().isEmpty());
+        assertTrue(type.getRanges().isEmpty());
 
         ExtendedType typeBase = (ExtendedType) type.getBaseType();
-        assertEquals("my-decimal-type", typeBase.getQName().getLocalName());
+        QName typeBaseQName = typeBase.getQName();
+        assertEquals("my-decimal-type", typeBaseQName.getLocalName());
+        assertEquals("t", typeBaseQName.getPrefix());
+        assertEquals(typesNS, typeBaseQName.getNamespace());
+        assertEquals(typesRev, typeBaseQName.getRevision());
+        assertNull(typeBase.getUnits());
+        assertNull(typeBase.getDefaultValue());
         assertNull(typeBase.getFractionDigits());
+        assertTrue(typeBase.getLengths().isEmpty());
+        assertTrue(typeBase.getPatterns().isEmpty());
+        assertTrue(typeBase.getRanges().isEmpty());
 
         Decimal64 decimal = (Decimal64) typeBase.getBaseType();
         assertEquals(6, (int) decimal.getFractionDigits());
@@ -477,147 +479,195 @@ public class YangParserTest {
 
     @Test
     public void testTypedefDecimal2() {
-        Module testModule = TestUtils.findModule(modules, "types1");
+        Module testModule = TestUtils.findModule(modules, "nodes");
+        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("decimal-leaf2");
 
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("test-decimal-leaf2");
-        TypeDefinition<?> baseType = testleaf.getType().getBaseType();
-        assertTrue(testleaf.getType().getBaseType() instanceof Decimal64);
-        Decimal64 baseTypeCast = (Decimal64) baseType;
-        assertEquals(5, (int) baseTypeCast.getFractionDigits());
+        ExtendedType type = (ExtendedType) testleaf.getType();
+        QName typeQName = type.getQName();
+        assertEquals("my-decimal-type", typeQName.getLocalName());
+        assertEquals("t", typeQName.getPrefix());
+        assertEquals(typesNS, typeQName.getNamespace());
+        assertEquals(typesRev, typeQName.getRevision());
+        assertNull(type.getUnits());
+        assertNull(type.getDefaultValue());
+        assertNull(type.getFractionDigits());
+        assertTrue(type.getLengths().isEmpty());
+        assertTrue(type.getPatterns().isEmpty());
+        assertTrue(type.getRanges().isEmpty());
+
+        Decimal64 baseTypeDecimal = (Decimal64) type.getBaseType();
+        assertEquals(6, (int) baseTypeDecimal.getFractionDigits());
     }
 
     @Test
     public void testTypedefUnion() {
-        Module testModule = TestUtils.findModule(modules, "types1");
-
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("union-leaf");
-        ExtendedType testleafType = (ExtendedType) testleaf.getType();
-        assertEquals("my-union-ext", testleafType.getQName().getLocalName());
-
-        ExtendedType baseType = (ExtendedType) testleafType.getBaseType();
-        assertEquals("my-union", baseType.getQName().getLocalName());
-
-        UnionType unionBase = (UnionType) baseType.getBaseType();
+        Module testModule = TestUtils.findModule(modules, "nodes");
+        LeafSchemaNode unionleaf = (LeafSchemaNode) testModule.getDataChildByName("union-leaf");
+
+        ExtendedType type = (ExtendedType) unionleaf.getType();
+        QName typeQName = type.getQName();
+        assertEquals("my-union-ext", typeQName.getLocalName());
+        assertEquals("t", typeQName.getPrefix());
+        assertEquals(typesNS, typeQName.getNamespace());
+        assertEquals(typesRev, typeQName.getRevision());
+        assertNull(type.getUnits());
+        assertNull(type.getDefaultValue());
+        assertNull(type.getFractionDigits());
+        assertTrue(type.getLengths().isEmpty());
+        assertTrue(type.getPatterns().isEmpty());
+        assertTrue(type.getRanges().isEmpty());
+
+        ExtendedType baseType = (ExtendedType) type.getBaseType();
+        QName baseTypeQName = baseType.getQName();
+        assertEquals("my-union", baseTypeQName.getLocalName());
+        assertEquals("t", baseTypeQName.getPrefix());
+        assertEquals(typesNS, baseTypeQName.getNamespace());
+        assertEquals(typesRev, baseTypeQName.getRevision());
+        assertNull(baseType.getUnits());
+        assertNull(baseType.getDefaultValue());
+        assertNull(baseType.getFractionDigits());
+        assertTrue(baseType.getLengths().isEmpty());
+        assertTrue(baseType.getPatterns().isEmpty());
+        assertTrue(baseType.getRanges().isEmpty());
+
+        UnionType unionType = (UnionType) baseType.getBaseType();
+        List<TypeDefinition<?>> unionTypes = unionType.getTypes();
+        assertEquals(2, unionTypes.size());
 
-        List<TypeDefinition<?>> unionTypes = unionBase.getTypes();
         ExtendedType unionType1 = (ExtendedType) unionTypes.get(0);
+        QName unionType1QName = baseType.getQName();
+        assertEquals("my-union", unionType1QName.getLocalName());
+        assertEquals("t", unionType1QName.getPrefix());
+        assertEquals(typesNS, unionType1QName.getNamespace());
+        assertEquals(typesRev, unionType1QName.getRevision());
+        assertNull(unionType1.getUnits());
+        assertNull(unionType1.getDefaultValue());
+        assertNull(unionType1.getFractionDigits());
+        assertTrue(unionType1.getLengths().isEmpty());
+        assertTrue(unionType1.getPatterns().isEmpty());
         List<RangeConstraint> ranges = unionType1.getRanges();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
         assertEquals(1L, range.getMin());
         assertEquals(100L, range.getMax());
-
         assertTrue(unionType1.getBaseType() instanceof Int16);
-        assertTrue(unionTypes.get(1) instanceof Int32);
-    }
-
-    @Test
-    public void testNestedUnionResolving1() {
-        Module testModule = TestUtils.findModule(modules, "types1");
-
-        LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("nested-union-leaf");
-
-        ExtendedType nestedUnion1 = (ExtendedType) testleaf.getType();
-        assertEquals("nested-union1", nestedUnion1.getQName().getLocalName());
-
-        ExtendedType nestedUnion2 = (ExtendedType) nestedUnion1.getBaseType();
-        assertEquals("nested-union2", nestedUnion2.getQName().getLocalName());
-
-        UnionType unionType1 = (UnionType) nestedUnion2.getBaseType();
-        List<TypeDefinition<?>> unionTypes = unionType1.getTypes();
-        assertEquals(2, unionTypes.size());
-        assertTrue(unionTypes.get(0) instanceof StringType);
-        assertTrue(unionTypes.get(1) instanceof ExtendedType);
-
-        ExtendedType extendedUnion = (ExtendedType) unionTypes.get(1);
-        ExtendedType extendedUnionBase = (ExtendedType) extendedUnion.getBaseType();
-        assertEquals("my-union", extendedUnionBase.getQName().getLocalName());
 
-        UnionType extendedTargetUnion = (UnionType) extendedUnionBase.getBaseType();
-        List<TypeDefinition<?>> extendedTargetTypes = extendedTargetUnion.getTypes();
-        assertTrue(extendedTargetTypes.get(0).getBaseType() instanceof Int16);
-        assertTrue(extendedTargetTypes.get(1) instanceof Int32);
-
-        ExtendedType int16 = (ExtendedType) extendedTargetTypes.get(0);
-        assertTrue(int16.getBaseType() instanceof Int16);
-        List<RangeConstraint> ranges = int16.getRanges();
-        assertEquals(1, ranges.size());
-        RangeConstraint range = ranges.get(0);
-        assertEquals(1L, range.getMin());
-        assertEquals(100L, range.getMax());
+        assertTrue(unionTypes.get(1) instanceof Int32);
     }
 
     @Test
-    public void testNestedUnionResolving2() {
-        Module testModule = TestUtils.findModule(modules, "types1");
-
+    public void testNestedUnionResolving() {
+        Module testModule = TestUtils.findModule(modules, "nodes");
         LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("custom-union-leaf");
 
-        ExtendedType testleafType = (ExtendedType) testleaf.getType();
-        QName testleafTypeQName = testleafType.getQName();
-        assertEquals(URI.create("urn:simple.container.demo.test"), testleafTypeQName.getNamespace());
-        assertEquals(TestUtils.createDate("2013-02-27"), testleafTypeQName.getRevision());
-        assertEquals("t3", testleafTypeQName.getPrefix());
+        ExtendedType type = (ExtendedType) testleaf.getType();
+        QName testleafTypeQName = type.getQName();
+        assertEquals(customNS, testleafTypeQName.getNamespace());
+        assertEquals(customRev, testleafTypeQName.getRevision());
+        assertEquals("c", testleafTypeQName.getPrefix());
         assertEquals("union1", testleafTypeQName.getLocalName());
+        assertNull(type.getUnits());
+        assertNull(type.getDefaultValue());
+        assertNull(type.getFractionDigits());
+        assertTrue(type.getLengths().isEmpty());
+        assertTrue(type.getPatterns().isEmpty());
+        assertTrue(type.getRanges().isEmpty());
 
-        ExtendedType union2 = (ExtendedType) testleafType.getBaseType();
-        QName union2QName = union2.getQName();
-        assertEquals(URI.create("urn:simple.container.demo.test"), union2QName.getNamespace());
-        assertEquals(TestUtils.createDate("2013-02-27"), union2QName.getRevision());
-        assertEquals("t3", union2QName.getPrefix());
-        assertEquals("union2", union2QName.getLocalName());
+        ExtendedType typeBase = (ExtendedType) type.getBaseType();
+        QName typeBaseQName = typeBase.getQName();
+        assertEquals(customNS, typeBaseQName.getNamespace());
+        assertEquals(customRev, typeBaseQName.getRevision());
+        assertEquals("c", typeBaseQName.getPrefix());
+        assertEquals("union2", typeBaseQName.getLocalName());
+        assertNull(typeBase.getUnits());
+        assertNull(typeBase.getDefaultValue());
+        assertNull(typeBase.getFractionDigits());
+        assertTrue(typeBase.getLengths().isEmpty());
+        assertTrue(typeBase.getPatterns().isEmpty());
+        assertTrue(typeBase.getRanges().isEmpty());
 
-        UnionType union2Base = (UnionType) union2.getBaseType();
-        List<TypeDefinition<?>> unionTypes = union2Base.getTypes();
+        UnionType union = (UnionType) typeBase.getBaseType();
+        List<TypeDefinition<?>> unionTypes = union.getTypes();
         assertEquals(2, unionTypes.size());
         assertTrue(unionTypes.get(0) instanceof Int32);
         assertTrue(unionTypes.get(1) instanceof ExtendedType);
 
-        ExtendedType nestedUnion2 = (ExtendedType) unionTypes.get(1);
-        QName nestedUnion2QName = nestedUnion2.getQName();
-        assertEquals(URI.create("urn:simple.types.data.demo"), nestedUnion2QName.getNamespace());
-        assertEquals(TestUtils.createDate("2013-02-27"), nestedUnion2QName.getRevision());
-        assertEquals("t2", nestedUnion2QName.getPrefix());
-        assertEquals("nested-union2", nestedUnion2QName.getLocalName());
-
-        UnionType nestedUnion2Base = (UnionType) nestedUnion2.getBaseType();
-        List<TypeDefinition<?>> nestedUnion2Types = nestedUnion2Base.getTypes();
+        ExtendedType unionType1 = (ExtendedType) unionTypes.get(1);
+        QName uniontType1QName = unionType1.getQName();
+        assertEquals(typesNS, uniontType1QName.getNamespace());
+        assertEquals(typesRev, uniontType1QName.getRevision());
+        assertEquals("t", uniontType1QName.getPrefix());
+        assertEquals("nested-union2", uniontType1QName.getLocalName());
+        assertNull(unionType1.getUnits());
+        assertNull(unionType1.getDefaultValue());
+        assertNull(unionType1.getFractionDigits());
+        assertTrue(unionType1.getLengths().isEmpty());
+        assertTrue(unionType1.getPatterns().isEmpty());
+        assertTrue(unionType1.getRanges().isEmpty());
+
+        UnionType nestedUnion = (UnionType) unionType1.getBaseType();
+        List<TypeDefinition<?>> nestedUnion2Types = nestedUnion.getTypes();
         assertEquals(2, nestedUnion2Types.size());
         assertTrue(nestedUnion2Types.get(0) instanceof StringType);
         assertTrue(nestedUnion2Types.get(1) instanceof ExtendedType);
 
         ExtendedType myUnionExt = (ExtendedType) nestedUnion2Types.get(1);
         QName myUnionExtQName = myUnionExt.getQName();
-        assertEquals(URI.create("urn:simple.types.data.demo"), myUnionExtQName.getNamespace());
-        assertEquals(TestUtils.createDate("2013-02-27"), myUnionExtQName.getRevision());
-        assertEquals("t2", myUnionExtQName.getPrefix());
+        assertEquals(typesNS, myUnionExtQName.getNamespace());
+        assertEquals(typesRev, myUnionExtQName.getRevision());
+        assertEquals("t", myUnionExtQName.getPrefix());
         assertEquals("my-union-ext", myUnionExtQName.getLocalName());
+        assertNull(myUnionExt.getUnits());
+        assertNull(myUnionExt.getDefaultValue());
+        assertNull(myUnionExt.getFractionDigits());
+        assertTrue(myUnionExt.getLengths().isEmpty());
+        assertTrue(myUnionExt.getPatterns().isEmpty());
+        assertTrue(myUnionExt.getRanges().isEmpty());
 
         ExtendedType myUnion = (ExtendedType) myUnionExt.getBaseType();
         QName myUnionQName = myUnion.getQName();
-        assertEquals(URI.create("urn:simple.types.data.demo"), myUnionQName.getNamespace());
-        assertEquals(TestUtils.createDate("2013-02-27"), myUnionQName.getRevision());
-        assertEquals("t2", myUnionQName.getPrefix());
+        assertEquals(typesNS, myUnionQName.getNamespace());
+        assertEquals(typesRev, myUnionQName.getRevision());
+        assertEquals("t", myUnionQName.getPrefix());
         assertEquals("my-union", myUnionQName.getLocalName());
+        assertNull(myUnion.getUnits());
+        assertNull(myUnion.getDefaultValue());
+        assertNull(myUnion.getFractionDigits());
+        assertTrue(myUnion.getLengths().isEmpty());
+        assertTrue(myUnion.getPatterns().isEmpty());
+        assertTrue(myUnion.getRanges().isEmpty());
 
         UnionType myUnionBase = (UnionType) myUnion.getBaseType();
         List<TypeDefinition<?>> myUnionBaseTypes = myUnionBase.getTypes();
         assertEquals(2, myUnionBaseTypes.size());
-        assertTrue(myUnionBaseTypes.get(0).getBaseType() instanceof Int16);
+        assertTrue(myUnionBaseTypes.get(0) instanceof ExtendedType);
         assertTrue(myUnionBaseTypes.get(1) instanceof Int32);
-        ExtendedType int16 = (ExtendedType) myUnionBaseTypes.get(0);
-        List<RangeConstraint> ranges = int16.getRanges();
+
+        ExtendedType int16Ext = (ExtendedType) myUnionBaseTypes.get(0);
+        QName int16ExtQName = int16Ext.getQName();
+        assertEquals(typesNS, int16ExtQName.getNamespace());
+        assertEquals(typesRev, int16ExtQName.getRevision());
+        assertEquals("t", int16ExtQName.getPrefix());
+        assertEquals("int16", int16ExtQName.getLocalName());
+        assertNull(int16Ext.getUnits());
+        assertNull(int16Ext.getDefaultValue());
+        assertNull(int16Ext.getFractionDigits());
+        assertTrue(int16Ext.getLengths().isEmpty());
+        assertTrue(int16Ext.getPatterns().isEmpty());
+        List<RangeConstraint> ranges = int16Ext.getRanges();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
         assertEquals(1L, range.getMin());
         assertEquals(100L, range.getMax());
+
+        assertTrue(int16Ext.getBaseType() instanceof Int16);
     }
 
     @Test
     public void testChoice() {
-        Module testModule = TestUtils.findModule(modules, "types1");
-        ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("transfer");
-        ChoiceNode how = (ChoiceNode) peer.getDataChildByName("how");
+        Module testModule = TestUtils.findModule(modules, "nodes");
+        ContainerSchemaNode transfer = (ContainerSchemaNode) testModule.getDataChildByName("transfer");
+        ChoiceNode how = (ChoiceNode) transfer.getDataChildByName("how");
         Set<ChoiceCaseNode> cases = how.getCases();
         assertEquals(5, cases.size());
         ChoiceCaseNode input = null;
@@ -637,26 +687,52 @@ public class YangParserTest {
 
     @Test
     public void testAnyXml() {
-        Module testModule = TestUtils.findModule(modules, "types1");
+        Module testModule = TestUtils.findModule(modules, "nodes");
         AnyXmlSchemaNode data = (AnyXmlSchemaNode) testModule.getDataChildByName("data");
-        assertNotNull(data);
+        assertNotNull("anyxml data not found", data);
+
+        // test SchemaNode args
+        QName qname = data.getQName();
+        assertEquals("data", qname.getLocalName());
+        assertEquals("n", qname.getPrefix());
+        assertEquals(nodesNS, qname.getNamespace());
+        assertEquals(nodesRev, qname.getRevision());
+        assertTrue(data.getDescription().contains("Copy of the source typesstore subset that matched"));
+        assertNull(data.getReference());
+        assertEquals(Status.OBSOLETE, data.getStatus());
+        assertEquals(0, data.getUnknownSchemaNodes().size());
+        // test DataSchemaNode args
+        assertFalse(data.isAugmenting());
+        assertTrue(data.isConfiguration());
+        ConstraintDefinition constraints = data.getConstraints();
+        assertNull(constraints.getWhenCondition());
+        assertEquals(0, constraints.getMustConstraints().size());
+        assertFalse(constraints.isMandatory());
+        assertNull(constraints.getMinElements());
+        assertNull(constraints.getMaxElements());
     }
 
     @Test
     public void testDeviation() {
-        Module testModule = TestUtils.findModule(modules, "types1");
+        Module testModule = TestUtils.findModule(modules, "nodes");
         Set<Deviation> deviations = testModule.getDeviations();
         assertEquals(1, deviations.size());
-
         Deviation dev = deviations.iterator().next();
-        SchemaPath expectedPath = TestUtils.createPath(true, null, null, "data", "system", "user");
+
+        assertEquals("system/user ref", dev.getReference());
+
+        List<QName> path = new ArrayList<QName>();
+        path.add(new QName(typesNS, typesRev, "t", "interfaces"));
+        path.add(new QName(typesNS, typesRev, "t", "ifEntry"));
+        SchemaPath expectedPath = new SchemaPath(path, true);
+
         assertEquals(expectedPath, dev.getTargetPath());
         assertEquals(Deviate.ADD, dev.getDeviate());
     }
 
     @Test
     public void testUnknownNode() {
-        Module testModule = TestUtils.findModule(modules, "types3");
+        Module testModule = TestUtils.findModule(modules, "custom");
         ContainerSchemaNode network = (ContainerSchemaNode) testModule.getDataChildByName("network");
         List<UnknownSchemaNode> unknownNodes = network.getUnknownSchemaNodes();
         assertEquals(1, unknownNodes.size());
@@ -667,37 +743,34 @@ public class YangParserTest {
 
     @Test
     public void testFeature() {
-        Module testModule = TestUtils.findModule(modules, "types3");
+        Module testModule = TestUtils.findModule(modules, "custom");
         Set<FeatureDefinition> features = testModule.getFeatures();
         assertEquals(1, features.size());
     }
 
     @Test
     public void testExtension() {
-        Module testModule = TestUtils.findModule(modules, "types3");
+        Module testModule = TestUtils.findModule(modules, "custom");
         List<ExtensionDefinition> extensions = testModule.getExtensionSchemaNodes();
         assertEquals(1, extensions.size());
         ExtensionDefinition extension = extensions.get(0);
         assertEquals("name", extension.getArgument());
-        assertFalse(extension.isYinElement());
+        assertTrue(extension.isYinElement());
     }
 
     @Test
     public void testNotification() {
-        Module testModule = TestUtils.findModule(modules, "types3");
-        URI expectedNamespace = URI.create("urn:simple.container.demo.test");
-        String expectedPrefix = "t3";
-        Date expectedRevision = TestUtils.createDate("2013-02-27");
+        Module testModule = TestUtils.findModule(modules, "custom");
+        String expectedPrefix = "c";
 
         Set<NotificationDefinition> notifications = testModule.getNotifications();
         assertEquals(1, notifications.size());
 
         NotificationDefinition notification = notifications.iterator().next();
         // test SchemaNode args
-        QName expectedQName = new QName(expectedNamespace, expectedRevision, expectedPrefix, "event");
+        QName expectedQName = new QName(customNS, customRev, expectedPrefix, "event");
         assertEquals(expectedQName, notification.getQName());
-        SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, expectedRevision, expectedPrefix,
-                "event");
+        SchemaPath expectedPath = TestUtils.createPath(true, customNS, customRev, expectedPrefix, "event");
         assertEquals(expectedPath, notification.getPath());
         assertNull(notification.getDescription());
         assertNull(notification.getReference());
@@ -719,7 +792,7 @@ public class YangParserTest {
 
     @Test
     public void testRpc() {
-        Module testModule = TestUtils.findModule(modules, "types3");
+        Module testModule = TestUtils.findModule(modules, "custom");
 
         Set<RpcDefinition> rpcs = testModule.getRpcs();
         assertEquals(1, rpcs.size());
@@ -735,66 +808,19 @@ public class YangParserTest {
         assertNotNull(output.getDataChildByName("data"));
     }
 
-    @Test
-    public void testAugmentNodesTypesSchemaPath() throws Exception {
-        Module testModule = TestUtils.findModule(modules, "types1");
-        Set<AugmentationSchema> augments = testModule.getAugmentations();
-        assertEquals(1, augments.size());
-        AugmentationSchema augment = augments.iterator().next();
-
-        LeafSchemaNode ifcId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
-        Leafref ifcIdType = (Leafref) ifcId.getType();
-        SchemaPath ifcIdTypeSchemaPath = ifcIdType.getPath();
-        List<QName> ifcIdTypePath = ifcIdTypeSchemaPath.getPath();
-
-        URI types1URI = URI.create("urn:simple.container.demo");
-        URI types2URI = URI.create("urn:simple.types.data.demo");
-        URI types3URI = URI.create("urn:simple.container.demo.test");
-        Date expectedDate = simpleDateFormat.parse("2013-02-27");
-
-        QName q0 = new QName(types2URI, expectedDate, "data", "interfaces");
-        QName q1 = new QName(types2URI, expectedDate, "data", "ifEntry");
-        QName q2 = new QName(types3URI, expectedDate, "data", "augment-holder");
-        QName q3 = new QName(types1URI, expectedDate, "data", "interface-id");
-        assertEquals(q0, ifcIdTypePath.get(0));
-        assertEquals(q1, ifcIdTypePath.get(1));
-        assertEquals(q2, ifcIdTypePath.get(2));
-        assertEquals(q3, ifcIdTypePath.get(3));
-
-        LeafListSchemaNode higherLayer = (LeafListSchemaNode) augment.getDataChildByName("higher-layer-if");
-        Leafref higherLayerType = (Leafref) higherLayer.getType();
-        SchemaPath higherLayerTypeSchemaPath = higherLayerType.getPath();
-        List<QName> higherLayerTypePath = higherLayerTypeSchemaPath.getPath();
-        assertEquals(q0, higherLayerTypePath.get(0));
-        assertEquals(q1, higherLayerTypePath.get(1));
-        assertEquals(q2, higherLayerTypePath.get(2));
-        q3 = new QName(types1URI, expectedDate, "data", "higher-layer-if");
-        assertEquals(q3, higherLayerTypePath.get(3));
-
-        LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
-        ExtendedType leafType = (ExtendedType) myType.getType();
-
-        testModule = TestUtils.findModule(modules, "types2");
-        TypeDefinition<?> typedef = TestUtils.findTypedef(testModule.getTypeDefinitions(), "my-type1");
-
-        assertEquals(typedef, leafType);
-    }
-
     @Test
     public void testTypePath() throws ParseException {
-        Module test = TestUtils.findModule(modules, "types2");
+        Module test = TestUtils.findModule(modules, "types");
         Set<TypeDefinition<?>> types = test.getTypeDefinitions();
 
         // my-base-int32-type
-        ExtendedType int32Typedef = (ExtendedType) TestUtils.findTypedef(types, "my-base-int32-type");
+        ExtendedType int32Typedef = (ExtendedType) TestUtils.findTypedef(types, "int32-ext1");
         QName int32TypedefQName = int32Typedef.getQName();
 
-        URI expectedNS = URI.create("urn:simple.types.data.demo");
-        Date expectedDate = simpleDateFormat.parse("2013-02-27");
-        assertEquals(expectedNS, int32TypedefQName.getNamespace());
-        assertEquals(expectedDate, int32TypedefQName.getRevision());
-        assertEquals("t2", int32TypedefQName.getPrefix());
-        assertEquals("my-base-int32-type", int32TypedefQName.getLocalName());
+        assertEquals(typesNS, int32TypedefQName.getNamespace());
+        assertEquals(typesRev, int32TypedefQName.getRevision());
+        assertEquals("t", int32TypedefQName.getPrefix());
+        assertEquals("int32-ext1", int32TypedefQName.getLocalName());
 
         SchemaPath typeSchemaPath = int32Typedef.getPath();
         List<QName> typePath = typeSchemaPath.getPath();
@@ -818,18 +844,16 @@ public class YangParserTest {
 
     @Test
     public void testTypePath2() throws ParseException {
-        Module test = TestUtils.findModule(modules, "types2");
+        Module test = TestUtils.findModule(modules, "types");
         Set<TypeDefinition<?>> types = test.getTypeDefinitions();
 
         // my-base-int32-type
         ExtendedType myDecType = (ExtendedType) TestUtils.findTypedef(types, "my-decimal-type");
         QName myDecTypeQName = myDecType.getQName();
 
-        URI expectedNS = URI.create("urn:simple.types.data.demo");
-        Date expectedDate = simpleDateFormat.parse("2013-02-27");
-        assertEquals(expectedNS, myDecTypeQName.getNamespace());
-        assertEquals(expectedDate, myDecTypeQName.getRevision());
-        assertEquals("t2", myDecTypeQName.getPrefix());
+        assertEquals(typesNS, myDecTypeQName.getNamespace());
+        assertEquals(typesRev, myDecTypeQName.getRevision());
+        assertEquals("t", myDecTypeQName.getPrefix());
         assertEquals("my-decimal-type", myDecTypeQName.getLocalName());
 
         SchemaPath typeSchemaPath = myDecType.getPath();
index be7b7ef7aa6974864cbad524fd97760ed36c55ec..b730445478721616294241e64f2f7d5cacbe2f38 100644 (file)
@@ -15,6 +15,7 @@ import java.net.URI;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -25,6 +26,8 @@ import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.controller.yang.model.api.ChoiceNode;
 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.Deviation;
+import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
@@ -77,7 +80,7 @@ public class YangParserWithContextTest {
         assertEquals("inet", qname.getPrefix());
         assertEquals("port-number", qname.getLocalName());
 
-        ExtendedType dscpExt = (ExtendedType)TestUtils.findTypedef(module.getTypeDefinitions(), "dscp-ext");
+        ExtendedType dscpExt = (ExtendedType) TestUtils.findTypedef(module.getTypeDefinitions(), "dscp-ext");
         List<RangeConstraint> ranges = dscpExt.getRanges();
         assertEquals(1, ranges.size());
         RangeConstraint range = ranges.get(0);
@@ -88,8 +91,10 @@ public class YangParserWithContextTest {
     @Test
     public void testUsesFromContext() throws Exception {
         SchemaContext context = null;
-        try (InputStream stream = new FileInputStream(getClass().getResource("/model/testfile2.yang").getPath())) {
-            context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+        try (InputStream stream1 = new FileInputStream(getClass().getResource("/model/custom.yang").getPath());
+                InputStream stream2 = new FileInputStream(getClass().getResource("/model/types.yang").getPath());
+                InputStream stream3 = new FileInputStream(getClass().getResource("/model/nodes.yang").getPath())) {
+            context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream1, stream2, stream3)));
         }
         Module testModule = null;
         try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test2.yang").getPath())) {
@@ -101,62 +106,62 @@ public class YangParserWithContextTest {
         // suffix _g = defined in grouping from context
 
         // get grouping
-        Module contextModule = context.findModuleByNamespace(URI.create("urn:simple.types.data.demo"));
+        Module contextModule = context.findModuleByNamespace(URI.create("urn:custom.nodes.test"));
         assertNotNull(contextModule);
         Set<GroupingDefinition> groupings = contextModule.getGroupings();
         assertEquals(1, groupings.size());
         GroupingDefinition grouping = groupings.iterator().next();
 
         // get node containing uses
-        ContainerSchemaNode peer = (ContainerSchemaNode)testModule.getDataChildByName("peer");
-        ContainerSchemaNode destination = (ContainerSchemaNode)peer.getDataChildByName("destination");
+        ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
+        ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
 
         // check uses
         Set<UsesNode> uses = destination.getUses();
         assertEquals(1, uses.size());
 
         // check uses process
-        AnyXmlSchemaNode data_u = (AnyXmlSchemaNode)destination.getDataChildByName("data");
+        AnyXmlSchemaNode data_u = (AnyXmlSchemaNode) destination.getDataChildByName("data");
         assertNotNull(data_u);
         assertTrue(data_u.isAddedByUses());
 
-        AnyXmlSchemaNode data_g = (AnyXmlSchemaNode)grouping.getDataChildByName("data");
+        AnyXmlSchemaNode data_g = (AnyXmlSchemaNode) grouping.getDataChildByName("data");
         assertNotNull(data_g);
         assertFalse(data_g.isAddedByUses());
         assertFalse(data_u.equals(data_g));
 
-        ChoiceNode how_u = (ChoiceNode)destination.getDataChildByName("how");
+        ChoiceNode how_u = (ChoiceNode) destination.getDataChildByName("how");
         assertNotNull(how_u);
         assertTrue(how_u.isAddedByUses());
 
-        ChoiceNode how_g = (ChoiceNode)grouping.getDataChildByName("how");
+        ChoiceNode how_g = (ChoiceNode) grouping.getDataChildByName("how");
         assertNotNull(how_g);
         assertFalse(how_g.isAddedByUses());
         assertFalse(how_u.equals(how_g));
 
-        LeafSchemaNode address_u = (LeafSchemaNode)destination.getDataChildByName("address");
+        LeafSchemaNode address_u = (LeafSchemaNode) destination.getDataChildByName("address");
         assertNotNull(address_u);
         assertTrue(address_u.isAddedByUses());
 
-        LeafSchemaNode address_g = (LeafSchemaNode)grouping.getDataChildByName("address");
+        LeafSchemaNode address_g = (LeafSchemaNode) grouping.getDataChildByName("address");
         assertNotNull(address_g);
         assertFalse(address_g.isAddedByUses());
         assertFalse(address_u.equals(address_g));
 
-        ContainerSchemaNode port_u = (ContainerSchemaNode)destination.getDataChildByName("port");
+        ContainerSchemaNode port_u = (ContainerSchemaNode) destination.getDataChildByName("port");
         assertNotNull(port_u);
         assertTrue(port_u.isAddedByUses());
 
-        ContainerSchemaNode port_g = (ContainerSchemaNode)grouping.getDataChildByName("port");
+        ContainerSchemaNode port_g = (ContainerSchemaNode) grouping.getDataChildByName("port");
         assertNotNull(port_g);
         assertFalse(port_g.isAddedByUses());
         assertFalse(port_u.equals(port_g));
 
-        ListSchemaNode addresses_u = (ListSchemaNode)destination.getDataChildByName("addresses");
+        ListSchemaNode addresses_u = (ListSchemaNode) destination.getDataChildByName("addresses");
         assertNotNull(addresses_u);
         assertTrue(addresses_u.isAddedByUses());
 
-        ListSchemaNode addresses_g = (ListSchemaNode)grouping.getDataChildByName("addresses");
+        ListSchemaNode addresses_g = (ListSchemaNode) grouping.getDataChildByName("addresses");
         assertNotNull(addresses_g);
         assertFalse(addresses_g.isAddedByUses());
         assertFalse(addresses_u.equals(addresses_g));
@@ -189,8 +194,10 @@ public class YangParserWithContextTest {
     @Test
     public void testUsesRefineFromContext() throws Exception {
         SchemaContext context = null;
-        try (InputStream stream = new FileInputStream(getClass().getResource("/model/testfile2.yang").getPath())) {
-            context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+        try (InputStream stream1 = new FileInputStream(getClass().getResource("/model/custom.yang").getPath());
+                InputStream stream2 = new FileInputStream(getClass().getResource("/model/types.yang").getPath());
+                InputStream stream3 = new FileInputStream(getClass().getResource("/model/nodes.yang").getPath())) {
+            context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream1, stream2, stream3)));
         }
         Module module = null;
         try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test2.yang").getPath())) {
@@ -206,7 +213,7 @@ public class YangParserWithContextTest {
 
         // test grouping path
         List<QName> path = new ArrayList<QName>();
-        QName qname = new QName(URI.create("urn:simple.types.data.demo"), simpleDateFormat.parse("2013-02-27"), "t2",
+        QName qname = new QName(URI.create("urn:custom.nodes.test"), simpleDateFormat.parse("2013-02-27"), "c",
                 "target");
         path.add(qname);
         SchemaPath expectedPath = new SchemaPath(path, true);
@@ -314,7 +321,8 @@ public class YangParserWithContextTest {
     @Test
     public void testUnknownNodes() throws Exception {
         SchemaContext context = null;
-        try (InputStream stream = new FileInputStream(getClass().getResource("/types/custom-types-test@2012-4-4.yang").getPath())) {
+        try (InputStream stream = new FileInputStream(getClass().getResource("/types/custom-types-test@2012-4-4.yang")
+                .getPath())) {
             context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
         }
 
@@ -327,7 +335,7 @@ public class YangParserWithContextTest {
         List<UnknownSchemaNode> unknownNodes = network.getUnknownSchemaNodes();
         assertEquals(1, unknownNodes.size());
 
-        UnknownSchemaNode un = unknownNodes.iterator().next();
+        UnknownSchemaNode un = unknownNodes.get(0);
         QName unType = un.getNodeType();
         assertEquals(URI.create("urn:simple.container.demo"), unType.getNamespace());
         assertEquals(simpleDateFormat.parse("2012-04-16"), unType.getRevision());
@@ -382,4 +390,43 @@ public class YangParserWithContextTest {
         assertTrue(ifEntry == ifEntryAfterAugment);
     }
 
+    @Test
+    public void testDeviation() throws Exception {
+        // load first module
+        SchemaContext context = null;
+        String resource = "/model/types.yang";
+
+        try (InputStream stream = new FileInputStream(getClass().getResource(resource).getPath())) {
+            context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+        }
+
+        // load another modules and parse them against already existing context
+        Set<Module> modules = null;
+        try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/deviation-test.yang")
+                .getPath())) {
+            List<InputStream> input = Lists.newArrayList(stream);
+            modules = TestUtils.loadModulesWithContext(input, context);
+        }
+        assertNotNull(modules);
+
+        // test deviation
+        Module testModule = TestUtils.findModule(modules, "deviation-test");
+        Set<Deviation> deviations = testModule.getDeviations();
+        assertEquals(1, deviations.size());
+        Deviation dev = deviations.iterator().next();
+
+        assertEquals("system/user ref", dev.getReference());
+
+        URI expectedNS = URI.create("urn:simple.types.test");
+        DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        Date expectedRev = simpleDateFormat.parse("2013-07-03");
+        List<QName> path = new ArrayList<QName>();
+        path.add(new QName(expectedNS, expectedRev, "t", "interfaces"));
+        path.add(new QName(expectedNS, expectedRev, "t", "ifEntry"));
+        SchemaPath expectedPath = new SchemaPath(path, true);
+
+        assertEquals(expectedPath, dev.getTargetPath());
+        assertEquals(Deviate.ADD, dev.getDeviate());
+    }
+
 }
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/context-test/deviation-test.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/context-test/deviation-test.yang
new file mode 100644 (file)
index 0000000..eafcb56
--- /dev/null
@@ -0,0 +1,27 @@
+module deviation-test {
+    yang-version 1;
+    namespace "urn:simple.deviation.test";
+    prefix "dev";
+
+    import types {
+        prefix "t";
+        revision-date 2013-07-03;
+    }
+
+    organization "opendaylight";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+
+    deviation /t:interfaces/t:ifEntry {
+        deviate add {
+            default "admin"; // new users are 'admin' by default
+            config "true";
+        }
+        reference "system/user ref";
+    }
+
+}
index 74704d5c22ae0afbdc8377f2448c72776939002a..4cff19259e4de0767545f66f13facbee592b6c14 100644 (file)
@@ -4,7 +4,7 @@ module test2 {
     namespace "urn:simple.demo.test2";
     prefix "t2";
 
-    import types2 {
+    import custom {
         prefix "data";
     }
 
similarity index 63%
rename from opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile3.yang
rename to opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/custom.yang
index c507da55e521612178a2bde2aa9f01fbb5b21b4c..d8d6054b597b6e7a43d7cb34e194d0f479fa6880 100644 (file)
@@ -1,11 +1,11 @@
-module types3 {
+module custom {
     yang-version 1;
-    namespace "urn:simple.container.demo.test";
-    prefix "t3";
+    namespace "urn:custom.nodes.test";
+    prefix "c";
 
-    import types2 {
-        prefix "data";
-        revision-date 2013-02-27;
+    import types {
+        prefix "types";
+        revision-date 2013-07-03;
     }
 
     organization "opendaylight";
@@ -22,25 +22,25 @@ module types3 {
     typedef union2 {
         type union {
             type int32;
-            type data:nested-union2;
+            type types:nested-union2;
         }
     }
 
-    augment "/data:interfaces/data:ifEntry" {
+    augment "/types:interfaces/types:ifEntry" {
         when "if:ifType='ds0'";
         container augment-holder {
             description "Description for augment holder";
         }
     }
 
-    augment "/data:interfaces/data:ifEntry" {
+    augment "/types:interfaces/types:ifEntry" {
         when "if:ifType='ds2'";
         container augment-holder2 {
             description "Description for augment holder";
         }
     }
 
-    augment "/data:interfaces/data:ifEntry/t3:augment-holder/t1:schemas" {
+    augment "/types:interfaces/types:ifEntry/t3:augment-holder/t1:schemas" {
         when "if:leafType='ds1'";
         leaf linkleaf {
             type binary;
@@ -68,10 +68,10 @@ module types3 {
 
     extension c-define {
         description
-            "Takes as argument a name string.
-             Makes the code generator use the given name in the
-             #define.";
-        argument "name";
+        "Takes as argument a name string. Makes the code generator use the given name in the #define.";
+        argument "name" {
+            yin-element "true";
+        }
     }
 
     notification event {
@@ -145,4 +145,61 @@ module types3 {
         }
     }
 
+    grouping target {
+        anyxml data {
+            config true;
+            description "Copy of the source datastore subset.";
+            mandatory false;
+            must "test-condition-text";
+            reference "test-no-reference";
+            status "obsolete";
+            when "test-when-text";
+        }
+        choice how {
+            description "test choice description";
+            default interval;
+            case interval {
+                leaf interval {
+                    type uint16;
+                    default 30;
+                    units minutes;
+                }
+            }
+            case daily {
+                leaf daily {
+                    type empty;
+                }
+                leaf time-of-day {
+                    type string;
+                    units 24-hour-clock;
+                    default 1am;
+                }
+            }
+        }
+        leaf address {
+            type string;
+            description "Target IP address";
+        }
+        container port {
+            description "Target port container";
+        }
+        list addresses {
+            key "id";
+            leaf id {
+                type int8;
+            }
+        }
+        grouping target-inner {
+            description "target-inner default description";
+            leaf inner-grouping-id {
+                type int8;
+            }
+        }
+        typedef group-type {
+            type types:my-decimal-type;
+        }
+
+        opendaylight;
+    }
+
 }
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/nodes.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/nodes.yang
new file mode 100644 (file)
index 0000000..e27dd0b
--- /dev/null
@@ -0,0 +1,192 @@
+module nodes {
+    yang-version 1;
+    namespace "urn:simple.nodes.test";
+    prefix "n";
+
+    import types {
+        prefix "t";
+        revision-date 2013-07-03;
+    }
+
+   import custom {
+        prefix "c";
+        revision-date 2013-02-27;
+    }
+
+    organization "opendaylight";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    leaf int32-leaf {
+        type t:int32-ext2 {
+            range "12..max";
+        }
+    }
+
+    leaf string-leaf {
+        type t:string-ext4;
+    }
+
+    leaf length-leaf {
+        type t:string-ext2 {
+            length "7..max";
+        }
+    }
+
+    leaf decimal-leaf {
+        type t:my-decimal-type {
+            fraction-digits 4;
+        }
+    }
+
+    leaf decimal-leaf2 {
+        type t:my-decimal-type;
+    }
+
+    container ext {
+        types:c-define "MY_INTERFACES";
+    }
+
+    leaf union-leaf {
+        type t:my-union-ext;
+    }
+
+    deviation /t:interfaces/t:ifEntry {
+        deviate add {
+            default "admin"; // new users are 'admin' by default
+            config "true";
+        }
+        reference "system/user ref";
+    }
+
+    leaf custom-union-leaf {
+        type c:union1;
+    }
+
+    container transfer {
+        choice how {
+            default interval;
+            container input {
+            }
+            list output {
+                leaf id {
+                    type string;
+                }
+            }
+            case interval {
+                leaf interval {
+                    type uint16;
+                    default 30;
+                    units minutes;
+                }
+            }
+            case daily {
+                leaf daily {
+                    type empty;
+                }
+                leaf time-of-day {
+                    type string;
+                    units 24-hour-clock;
+                    default 1am;
+                }
+            }
+            case manual {
+                leaf manual {
+                    type empty;
+                }
+            }
+        }
+    }
+
+    anyxml data {
+        description
+          "Copy of the source typesstore subset that matched
+           the filter criteria (if any).  An empty types container
+           indicates that the request did not produce any results.";
+        status obsolete;
+    }
+
+    augment "/t:interfaces/t:ifEntry/c:augment-holder" {
+        when "if:ifType='ds0'";
+        leaf ds0ChannelNumber {
+            type string;
+        }
+        leaf interface-id {
+            type leafref {
+                path "/if:interfaces/if:interface/if:name";
+            }
+        }
+        leaf my-type {
+            type t:int32-ext2;
+        }
+        container schemas {
+        }
+        choice odl {
+            leaf id {
+                type int8;
+            }
+            case node1 {
+                description "node1";
+            }
+            case node2 {
+                description "node2";
+            }
+            container node3 {
+                description "node3";
+            }
+        }
+    }
+
+    container mycont {
+        container innercont {
+            typedef mytype {
+                type string;
+            }
+            leaf myleaf {
+                type mytype;
+            }
+        }
+    }
+
+    container peer {
+        container destination {
+            uses c:target {
+                refine address {
+                    default "1.2.3.4";
+                    description "IP address of target node";
+                    reference "address reference added by refine";
+                    config false;
+                    mandatory true;
+                    must "ifType != 'ethernet' or " +
+                            "(ifType = 'ethernet' and ifMTU = 1500)" {
+                        error-message "An ethernet MTU must be 1500";
+                    }
+                }
+                refine port {
+                    description "description of port defined by refine";
+                    reference "port reference added by refine";
+                    config false;
+                    presence "presence is required";
+                }
+                refine addresses {
+                    description "description of addresses defined by refine";
+                    reference "addresses reference added by refine";
+                    config false;
+                    min-elements 2;
+                    max-elements 12;
+                }
+                refine target-inner {
+                    description "new target-inner grouping description";
+                }
+                refine group-type {
+                    description "new group-type description";
+                    reference "new group-type reference";
+                }
+            }
+        }
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang
deleted file mode 100644 (file)
index 47e6491..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-module types1 {
-    yang-version 1;
-    namespace "urn:simple.container.demo";
-    prefix "t1";
-
-    import types2 {
-        prefix "data";
-        revision-date 2013-02-27;
-    }
-
-   import types3 {
-        prefix "t3";
-        revision-date 2013-02-27;
-    }
-
-    organization "opendaylight";
-    contact "http://www.opendaylight.org/";
-
-    revision "2013-02-27" {
-        reference " WILL BE DEFINED LATER";
-    }
-
-    leaf testleaf {
-        type data:my-type1 {
-            range "12..max";
-        }
-    }
-
-    leaf test-string-leaf {
-        type data:my-string-type-ext;
-    }
-
-    leaf leaf-with-length {
-        type data:my-string-type {
-            length "7..max";
-        }
-    }
-
-    leaf test-int-leaf {
-        type data:my-int-type-ext;
-    }
-
-    leaf test-decimal-leaf {
-        type data:my-decimal-type {
-            fraction-digits 4;
-        }
-    }
-
-    leaf test-decimal-leaf2 {
-        type data:my-decimal-type-ext;
-    }
-
-    container ext {
-        data:c-define "MY_INTERFACES";
-    }
-
-    leaf union-leaf {
-        type data:my-union-ext;
-    }
-
-    deviation /data:system/data:user {
-        deviate add {
-            default "admin"; // new users are 'admin' by default
-            config "true";
-        }
-    }
-
-    leaf nested-union-leaf {
-        type data:nested-union1;
-    }
-
-    leaf custom-union-leaf {
-        type t3:union1;
-    }
-
-    container transfer {
-        choice how {
-            default interval;
-            container input {
-            }
-            list output {
-                leaf id {
-                    type string;
-                }
-            }
-            case interval {
-                leaf interval {
-                    type uint16;
-                    default 30;
-                    units minutes;
-                }
-            }
-            case daily {
-                leaf daily {
-                    type empty;
-                }
-                leaf time-of-day {
-                    type string;
-                    units 24-hour-clock;
-                    default 1am;
-                }
-            }
-            case manual {
-                leaf manual {
-                    type empty;
-                }
-            }
-        }
-    }
-
-    anyxml data {
-        description
-          "Copy of the source datastore subset that matched
-           the filter criteria (if any).  An empty data container
-           indicates that the request did not produce any results.";
-    }
-
-    augment "/data:interfaces/data:ifEntry/t3:augment-holder" {
-        when "if:ifType='ds0'";
-        leaf ds0ChannelNumber {
-            type string;
-        }
-        leaf interface-id {
-            type leafref {
-                path "/if:interfaces/if:interface/if:name";
-            }
-        }
-        leaf-list higher-layer-if {
-            type leafref {
-                path "/if:interfaces/if:interface/if:higher-layer-if";
-            }
-        }
-        leaf my-type {
-            type data:my-type1;
-        }
-        container schemas {
-        }
-        choice odl {
-            leaf id {
-                type int8;
-            }
-        }
-    }
-    
-    container mycont {
-        container innercont {
-            typedef mytype {
-                type string;
-            }
-        
-            leaf myleaf {
-                type mytype;
-            }
-        }
-    }
-    
-}
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile2.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile2.yang
deleted file mode 100644 (file)
index b25f65e..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-module types2 {
-    yang-version 1;
-    namespace "urn:simple.types.data.demo";
-    prefix "t2";
-    
-    organization "opendaylight";
-    contact "http://www.opendaylight.org/";
-    
-    description "This is types-data test description";
-
-    revision "2013-02-27" {
-        reference " WILL BE DEFINED LATER";
-    }
-
-    typedef my-base-int32-type {
-        type int32 {
-            range "2..20";
-        }
-    }
-
-    typedef my-type1 {
-        type my-base-int32-type {
-            range "3..9|11..max";
-        }
-        units "mile";
-        default "11";
-    }
-
-    typedef my-custom-string {
-        type string {
-            pattern "[a-k]*";
-            length "5..11";
-        }
-    }
-
-    typedef my-string-type {
-        type my-custom-string {
-            length "6..10";
-        }
-    }
-    
-    typedef my-string-type2 {
-        type my-string-type {
-            pattern "[b-u]*";
-        }
-    }
-
-    typedef my-string-type-ext {
-        type my-string-type2 {
-            pattern "[e-z]*";
-        }
-    }
-
-    typedef my-int-type {
-        type int32 {
-            range "10..20";
-        }
-    }
-
-    typedef my-int-type2 {
-        type my-int-type {
-            range "12..18";
-        }
-    }
-
-    typedef my-int-type-ext {
-        type my-int-type2 {
-            range "14..16";
-        }
-    }
-
-    typedef my-decimal-type {
-        type decimal64 {
-            fraction-digits 6;
-        }
-    }
-
-    typedef my-decimal-type-ext {
-        type decimal64 {
-            fraction-digits 5;
-        }
-    }
-
-    typedef my-union {
-        type union {
-            type int16 {
-                range "1..100";
-            }
-            type int32;
-        }
-    }
-
-    typedef my-union-ext {
-        type my-union;
-    }
-
-    typedef nested-union1 {
-        type nested-union2;
-    }
-
-    typedef nested-union2 {
-        type union {
-            type my-union-ext;
-            type string;
-        }
-    }
-
-    leaf if-name {
-        type leafref {
-            path "/interface/name";
-        }
-    }
-
-    leaf name {
-        type string;
-    }
-
-    leaf count {
-        type int8 {
-            range "1..10";
-        }
-    }
-
-    leaf nested-type-leaf {
-        type my-type1;
-    }
-
-    extension c-define {
-        description
-        "Takes as argument a name string.
-        Makes the code generator use the given name in the
-        #define.";
-        argument "name" {
-            yin-element "true";
-        }
-    }
-
-    container system {
-        leaf user {
-            type string;
-        }
-    }
-
-    grouping target {
-        anyxml data {
-            config true;
-            description "Copy of the source datastore subset.";
-            mandatory false;
-            must "test-condition-text";
-            reference "test-no-reference";
-            status "obsolete";
-            when "test-when-text";
-        }
-        choice how {
-            description "test choice description";
-            default interval;
-            case interval {
-                leaf interval {
-                    type uint16;
-                    default 30;
-                    units minutes;
-                }
-            }
-            case daily {
-                leaf daily {
-                    type empty;
-                }
-                leaf time-of-day {
-                    type string;
-                    units 24-hour-clock;
-                    default 1am;
-                }
-            }
-        }
-        leaf address {
-            type string;
-            description "Target IP address";
-        }
-        container port {
-            description "Target port container";
-        }
-        list addresses {
-            key "id";
-            leaf id {
-                type int8;
-            }
-        }
-        grouping target-inner {
-            description "target-inner default description";
-            leaf inner-grouping-id {
-                type int8;
-            }
-        }
-        typedef group-type {
-            type my-decimal-type;
-        }
-
-        opendaylight;
-    }
-
-    container peer {
-        container destination {
-            uses target {
-                refine address {
-                    default "1.2.3.4";
-                    description "IP address of target node";
-                    reference "address reference added by refine";
-                    config false;
-                    mandatory true;
-                    must "ifType != 'ethernet' or " +
-                            "(ifType = 'ethernet' and ifMTU = 1500)" {
-                        error-message "An ethernet MTU must be 1500";
-                    }
-                }
-                refine port {
-                    description "description of port defined by refine";
-                    reference "port reference added by refine";
-                    config false;
-                    presence "presence is required";
-                }
-                refine addresses {
-                    description "description of addresses defined by refine";
-                    reference "addresses reference added by refine";
-                    config false;
-                    min-elements 2;
-                    max-elements 12;
-                }
-                refine target-inner {
-                    description "new target-inner grouping description";
-                }
-                refine group-type {
-                    description "new group-type description";
-                    reference "new group-type reference";
-                }
-            }
-        }
-    }
-
-    container interfaces {
-         list ifEntry {
-             key "ifIndex";
-
-             leaf ifIndex {
-                 type uint32;
-                 units minutes;
-             }
-
-             leaf ifMtu {
-                 type int32;
-             }
-
-             min-elements 1;
-             max-elements 11;
-         }
-    }
-
-}
diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/types.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/types.yang
new file mode 100644 (file)
index 0000000..d9d5064
--- /dev/null
@@ -0,0 +1,97 @@
+module types {
+    yang-version 1;
+    namespace "urn:simple.types.test";
+    prefix "t";
+    
+    organization "opendaylight";
+    contact "http://www.opendaylight.org/";
+    description "This is types-data test description";
+
+    revision "2013-07-03" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    typedef int32-ext1 {
+        type int32 {
+            range "2..20";
+        }
+    }
+
+    typedef int32-ext2 {
+        type int32-ext1 {
+            range "3..9|11..max";
+        }
+        units "mile";
+        default "11";
+    }
+
+    typedef string-ext1 {
+        type string {
+            pattern "[a-k]*";
+            length "5..11";
+        }
+    }
+
+    typedef string-ext2 {
+        type string-ext1 {
+            length "6..10";
+        }
+    }
+    
+    typedef string-ext3 {
+        type string-ext2 {
+            pattern "[b-u]*";
+        }
+    }
+
+    typedef string-ext4 {
+        type string-ext3 {
+            pattern "[e-z]*";
+        }
+    }
+
+    typedef my-decimal-type {
+        type decimal64 {
+            fraction-digits 6;
+        }
+    }
+
+    typedef my-union {
+        type union {
+            type int16 {
+                range "1..100";
+            }
+            type int32;
+        }
+    }
+
+    typedef my-union-ext {
+        type my-union;
+    }
+
+    typedef nested-union2 {
+        type union {
+            type my-union-ext;
+            type string;
+        }
+    }
+
+    container interfaces {
+         list ifEntry {
+             key "ifIndex";
+
+             leaf ifIndex {
+                 type uint32;
+                 units minutes;
+             }
+
+             leaf ifMtu {
+                 type int32;
+             }
+
+             min-elements 1;
+             max-elements 11;
+         }
+    }
+
+}
index 33c160446301d5a19e635e2ee9d13b9ce2433630..3076a6fd679fdbc75509dd6dd4036bbf2f10be01 100644 (file)
@@ -19,6 +19,7 @@
                <module>yang-common</module>
                <module>yang-data-api</module>
                <module>yang-data-util</module>
+               <module>yang-data-impl</module>
                <module>yang-model-api</module>
                <module>yang-model-util</module>
                <module>yang-binding</module>
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java
deleted file mode 100644 (file)
index 1772ddf..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.yang.data.api;\r
-\r
-import org.opendaylight.controller.yang.common.QName;\r
-\r
-/**\r
- * For the use cases of changing the state data, the node modifications are\r
- * modeled as part of additional metadata in data tree. The modification types\r
- * are based on Netconf edit-config RPCs. In order to modify the configuration\r
- * or state data tree the user must create a tree representing the modification\r
- * of the data and apply that modification to the target tree.\r
- * \r
- * \r
- * @see <a href="http://tools.ietf.org/html/rfc6241">Network Configuration\r
- *      Protocol (NETCONF)</a>\r
- * \r
- */\r
-public interface CompositeNodeModification extends CompositeNode {\r
-\r
-    ModifyAction getModificationAction();\r
-\r
-    // Container Modification\r
-\r
-    /**\r
-     * The data identified by the node containing this modification is merged\r
-     * with the data at the corresponding level in the data tree\r
-     * \r
-     * @param node\r
-     *            in data tree\r
-     */\r
-    void mergeChild(CompositeNode node);\r
-\r
-    /**\r
-     * The data identified by the node containing this modification replaces any\r
-     * related data in the target data tree If no such data exists in the target\r
-     * data tree, the child node is created.\r
-     * \r
-     * @param node\r
-     *            composite node\r
-     */\r
-    void replaceChild(CompositeNode node);\r
-\r
-    /**\r
-     * Adds new composite node into data tree\r
-     * \r
-     * @param node\r
-     *            composite node\r
-     */\r
-    void addChild(CompositeNode node);\r
-\r
-    /**\r
-     * The data identified by the node containing this modification is deleted\r
-     * from the target data tree if and only if the data currently exists in the\r
-     * target data tree. If the data does not exist, an error is returned with\r
-     * an error value of "data-missing".\r
-     * \r
-     * @param node\r
-     */\r
-    void deleteChild(CompositeNode node);\r
-\r
-    /**\r
-     * The data identified by the node containing this attribute is deleted from\r
-     * the target data tree if the data currently exists in the target data\r
-     * tree. If the data does not exist, the modification is silently ignored.\r
-     * \r
-     * @param node\r
-     *            composite node\r
-     */\r
-    void removeChild(CompositeNode node);\r
-\r
-    // Leaf Modifications\r
-\r
-    /**\r
-     * The data identified by the node containing this modification replaces any\r
-     * related data in the target data tree If no such data exists in the target\r
-     * data tree, it is created.\r
-     * \r
-     * @param leaf\r
-     */\r
-    void replaceSimpleNode(SimpleNode<?> leaf);\r
-\r
-    /**\r
-     * The data identified by the node containing this modification is deleted\r
-     * from the target data tree if and only if the data currently exists in the\r
-     * target data tree. If the data does not exist, an error is returned with\r
-     * an error value of "data-missing".\r
-     * \r
-     * @param leaf\r
-     */\r
-    void deleteSimpleNode(SimpleNode<?> leaf);\r
-\r
-    /**\r
-     * The data identified by the node containing this attribute is deleted from\r
-     * the target data tree if the data currently exists in the target data\r
-     * tree. If the data does not exist, the modification is silently ignored.\r
-     * \r
-     * @param leaf\r
-     */\r
-    void removeSimpleNode(SimpleNode<?> leaf);\r
-\r
-    void removeLeaf(SimpleNode<?> leaf);\r
-\r
-    void removeLeaf(QName leaf);\r
-}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableCompositeNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableCompositeNode.java
new file mode 100755 (executable)
index 0000000..b1baf30
--- /dev/null
@@ -0,0 +1,23 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+import java.util.List;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public interface MutableCompositeNode extends MutableNode<List<Node<?>>>, CompositeNode {\r
+    \r
+    /**\r
+     * update internal map\r
+     */\r
+    public void init();\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableNode.java
new file mode 100755 (executable)
index 0000000..3eddbe5
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+\r
+/**\r
+ * Base representation of node in the data tree, defines basic parameters of\r
+ * node such as a QName.\r
+ * \r
+ * \r
+ * @param <T>\r
+ */\r
+public interface MutableNode<T> extends Node<T> {\r
+\r
+    /**\r
+     * @param parent value to set\r
+     */\r
+    void setParent(CompositeNode parent);\r
+    \r
+    /**\r
+     * @param value value to set (children list or leaf value)\r
+     */\r
+    void setValue(T value);\r
+    \r
+    /**\r
+     * @param action value to set\r
+     */\r
+    void setModifyAction(ModifyAction action);\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableSimpleNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableSimpleNode.java
new file mode 100755 (executable)
index 0000000..9519fac
--- /dev/null
@@ -0,0 +1,20 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> node value type\r
+ *\r
+ */\r
+public interface MutableSimpleNode<T> extends MutableNode<T>, SimpleNode<T> {\r
+    \r
+   // nothing\r
+    \r
+}\r
index 341a2866f0627aacb4fa5adb8bf2fbf1eb9e7345..f107dd89640b0f832f655dea35ced8d3724eda88 100644 (file)
@@ -21,7 +21,7 @@ public interface Node<T> {
     /**\r
      * Returns the name of the Node\r
      * \r
-     * @return\r
+     * @return qName of node\r
      */\r
     QName getNodeType();\r
 \r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModification.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModification.java
new file mode 100755 (executable)
index 0000000..c6b64f3
--- /dev/null
@@ -0,0 +1,21 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public interface NodeModification {\r
+\r
+    /**\r
+     * @return modify action\r
+     */\r
+    ModifyAction getModificationAction();\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModificationBuilder.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModificationBuilder.java
new file mode 100755 (executable)
index 0000000..4e4af9b
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public interface NodeModificationBuilder {\r
+\r
+    public abstract Node<?> getMutableEquivalent(Node<?> originalNode);\r
+\r
+    public abstract CompositeNode buildDiffTree();\r
+\r
+    public abstract void mergeNode(MutableCompositeNode alteredNode);\r
+\r
+    public abstract void removeNode(MutableCompositeNode deadNode);\r
+\r
+    public abstract void removeNode(MutableSimpleNode<?> deadNode);\r
+\r
+    public abstract void deleteNode(MutableSimpleNode<?> deadNode);\r
+\r
+    public abstract void deleteNode(MutableCompositeNode deadNode);\r
+\r
+    public abstract void replaceNode(MutableCompositeNode replacementNode);\r
+\r
+    public abstract void replaceNode(MutableSimpleNode<?> replacementNode);\r
+\r
+    public abstract void addNode(MutableCompositeNode newNode);\r
+\r
+    public abstract void addNode(MutableSimpleNode<?> newNode);\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/pom.xml
new file mode 100755 (executable)
index 0000000..5843de1
--- /dev/null
@@ -0,0 +1,72 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"\r
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+    <modelVersion>4.0.0</modelVersion>\r
+    <parent>\r
+        <groupId>org.opendaylight.controller</groupId>\r
+        <artifactId>yang</artifactId>\r
+        <version>0.5.3-SNAPSHOT</version>\r
+    </parent>\r
+    <artifactId>yang-data-impl</artifactId>\r
+\r
+    <properties>\r
+        <groovy.version>2.1.5</groovy.version>\r
+    </properties>\r
+\r
+    <build>\r
+        <plugins>\r
+            <plugin>\r
+                <groupId>org.apache.maven.plugins</groupId>\r
+                <artifactId>maven-surefire-plugin</artifactId>\r
+                <configuration>\r
+                    <argLine>-Dlog4j.configuration=log4j-test.xml</argLine>\r
+                    <redirectTestOutputToFile>true</redirectTestOutputToFile>\r
+                </configuration>\r
+            </plugin>\r
+        </plugins>\r
+    </build>\r
+\r
+\r
+    <dependencies>\r
+        <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>yang-common</artifactId>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>yang-data-api</artifactId>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>yang-model-parser-impl</artifactId>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>com.google.guava</groupId>\r
+            <artifactId>guava</artifactId>\r
+            <version>14.0.1</version>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>junit</groupId>\r
+            <artifactId>junit</artifactId>\r
+            <scope>test</scope>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.slf4j</groupId>\r
+            <artifactId>slf4j-log4j12</artifactId>\r
+            <version>${slf4j.version}</version>\r
+            <scope>test</scope>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.codehaus.groovy</groupId>\r
+            <artifactId>groovy</artifactId>\r
+            <version>${groovy.version}</version>\r
+            <scope>test</scope>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.codehaus.groovy</groupId>\r
+            <artifactId>groovy-xml</artifactId>\r
+            <version>${groovy.version}</version>\r
+            <scope>test</scope>\r
+        </dependency>\r
+    </dependencies>\r
+</project>
\ No newline at end of file
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/AbstractNodeTO.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/AbstractNodeTO.java
new file mode 100755 (executable)
index 0000000..cc4dfee
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T>\r
+ *            type of node value\r
+ * \r
+ */\r
+public abstract class AbstractNodeTO<T> implements Node<T> {\r
+\r
+    private QName qName;\r
+    private CompositeNode parent;\r
+    private T value;\r
+\r
+    /**\r
+     * @param qname\r
+     * @param parent\r
+     * @param value\r
+     */\r
+    public AbstractNodeTO(QName qname, CompositeNode parent, T value) {\r
+        this.qName = qname;\r
+        this.parent = parent;\r
+        this.value = value;\r
+    }\r
+\r
+    @Override\r
+    public QName getNodeType() {\r
+        return qName;\r
+    }\r
+\r
+    /**\r
+     * @return the qName\r
+     */\r
+    protected QName getQName() {\r
+        return qName;\r
+    }\r
+\r
+    @Override\r
+    public CompositeNode getParent() {\r
+        return parent;\r
+    }\r
+    \r
+    /**\r
+     * @param parent the parent to set\r
+     */\r
+    public void setParent(CompositeNode parent) {\r
+        this.parent = parent;\r
+    }\r
+    \r
+    /**\r
+     * @param value the value to set\r
+     */\r
+    protected void setValue(T value) {\r
+        this.value = value;\r
+    }\r
+\r
+    @Override\r
+    public T getValue() {\r
+        return value;\r
+    }\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeModificationTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeModificationTOImpl.java
new file mode 100755 (executable)
index 0000000..7981df2
--- /dev/null
@@ -0,0 +1,52 @@
+/**\r
+ * \r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class CompositeNodeModificationTOImpl extends CompositeNodeTOImpl\r
+        implements NodeModification {\r
+\r
+    private ModifyAction modifyAction;\r
+\r
+    /**\r
+     * @param qname\r
+     * @param parent\r
+     * @param value\r
+     * @param modifyAction\r
+     */\r
+    public CompositeNodeModificationTOImpl(QName qname, CompositeNode parent,\r
+            List<Node<?>> value, ModifyAction modifyAction) {\r
+        super(qname, parent, value);\r
+        this.modifyAction = modifyAction;\r
+    }\r
+\r
+    /**\r
+     * @return modification action\r
+     * @see org.opendaylight.controller.yang.data.impl.NodeModificationSupport#getModificationAction()\r
+     */\r
+    @Override\r
+    public ModifyAction getModificationAction() {\r
+        return modifyAction;\r
+    }\r
+\r
+    /**\r
+     * @param modifyAction\r
+     *            the modifyAction to set\r
+     */\r
+    protected void setModificationAction(ModifyAction modifyAction) {\r
+        this.modifyAction = modifyAction;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeTOImpl.java
new file mode 100755 (executable)
index 0000000..f94163a
--- /dev/null
@@ -0,0 +1,120 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class CompositeNodeTOImpl extends AbstractNodeTO<List<Node<?>>>\r
+        implements CompositeNode {\r
+\r
+    private Map<QName, List<Node<?>>> nodeMap;\r
+\r
+    /**\r
+     * @param qname\r
+     * @param parent use null to create top composite node (without parent)\r
+     * @param value\r
+     */\r
+    public CompositeNodeTOImpl(QName qname, CompositeNode parent,\r
+            List<Node<?>> value) {\r
+        super(qname, parent, value);\r
+        if (value != null) {\r
+            nodeMap = NodeUtils.buildNodeMap(getValue());\r
+        }\r
+    }\r
+    \r
+\r
+    /**\r
+     * @return the nodeMap\r
+     */\r
+    protected Map<QName, List<Node<?>>> getNodeMap() {\r
+        return nodeMap;\r
+    }\r
+    \r
+    @Override\r
+    public List<Node<?>> getChildren() {\r
+        return getValue();\r
+    }\r
+\r
+    @Override\r
+    public SimpleNode<?> getFirstSimpleByName(QName leafQName) {\r
+        List<SimpleNode<?>> list = getSimpleNodesByName(leafQName);\r
+        if (list.isEmpty())\r
+            return null;\r
+        return list.get(0);\r
+    }\r
+\r
+    @Override\r
+    public List<CompositeNode> getCompositesByName(QName children) {\r
+        List<Node<?>> toFilter = getNodeMap().get(children);\r
+        List<CompositeNode> list = new ArrayList<CompositeNode>();\r
+        for (Node<?> node : toFilter) {\r
+            if (node instanceof CompositeNode)\r
+                list.add((CompositeNode) node);\r
+        }\r
+        return list;\r
+    }\r
+\r
+    @Override\r
+    public List<SimpleNode<?>> getSimpleNodesByName(QName children) {\r
+        List<Node<?>> toFilter = getNodeMap().get(children);\r
+        List<SimpleNode<?>> list = new ArrayList<SimpleNode<?>>();\r
+\r
+        for (Node<?> node : toFilter) {\r
+            if (node instanceof SimpleNode<?>)\r
+                list.add((SimpleNode<?>) node);\r
+        }\r
+        return list;\r
+    }\r
+\r
+    @Override\r
+    public CompositeNode getFirstCompositeByName(QName container) {\r
+        List<CompositeNode> list = getCompositesByName(container);\r
+        if (list.isEmpty()) {\r
+            return null;\r
+        }\r
+        return list.get(0);\r
+    }\r
+\r
+    /**\r
+     * @param leaf\r
+     * @return TODO:: do we need this method?\r
+     */\r
+    public SimpleNode<?> getFirstLeafByName(QName leaf) {\r
+        List<SimpleNode<?>> list = getSimpleNodesByName(leaf);\r
+        if (list.isEmpty()) {\r
+            return null;\r
+        }\r
+        return list.get(0);\r
+    }\r
+\r
+    @Override\r
+    public List<CompositeNode> getCompositesByName(String children) {\r
+        return getCompositesByName(localQName(children));\r
+    }\r
+    \r
+    @Override\r
+    public List<SimpleNode<?>> getSimpleNodesByName(String children) {\r
+        return getSimpleNodesByName(localQName(children));\r
+    }\r
+\r
+    private QName localQName(String str) {\r
+        return new QName(getNodeType(), str);\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableCompositeNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableCompositeNodeTOImpl.java
new file mode 100755 (executable)
index 0000000..997b502
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class MutableCompositeNodeTOImpl extends CompositeNodeModificationTOImpl\r
+        implements MutableCompositeNode {\r
+\r
+    private Map<QName, List<Node<?>>> nodeMap;\r
+\r
+    /**\r
+     * @param qname\r
+     * @param parent\r
+     * @param value\r
+     * @param modifyAction\r
+     */\r
+    public MutableCompositeNodeTOImpl(QName qname, CompositeNode parent,\r
+            List<Node<?>> value, ModifyAction modifyAction) {\r
+        super(qname, parent, value, modifyAction);\r
+    }\r
+    \r
+    /**\r
+     * update nodeMap\r
+     */\r
+    @Override\r
+    public void init() {\r
+        nodeMap = NodeUtils.buildNodeMap(getChildren());\r
+    }\r
+\r
+    @Override\r
+    public void setValue(List<Node<?>> value) {\r
+        super.setValue(value);\r
+    }\r
+    \r
+    @Override\r
+    public void setModifyAction(ModifyAction action) {\r
+        super.setModificationAction(action);\r
+    }\r
+    \r
+    @Override\r
+    protected Map<QName, List<Node<?>>> getNodeMap() {\r
+        return nodeMap;\r
+    }\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableSimpleNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableSimpleNodeTOImpl.java
new file mode 100755 (executable)
index 0000000..17cbb8d
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> type of simple node value\r
+ * \r
+ */\r
+public class MutableSimpleNodeTOImpl<T> extends SimpleNodeModificationTOImpl<T> \r
+        implements MutableSimpleNode<T> {\r
+\r
+    /**\r
+     * @param qname\r
+     * @param parent\r
+     * @param value\r
+     * @param modifyAction\r
+     */\r
+    public MutableSimpleNodeTOImpl(QName qname, CompositeNode parent, T value,\r
+            ModifyAction modifyAction) {\r
+        super(qname, parent, value, modifyAction);\r
+    }\r
+\r
+    @Override\r
+    public void setValue(T value) {\r
+        super.setValue(value);\r
+    }\r
+    \r
+    @Override\r
+    public void setModifyAction(ModifyAction action) {\r
+        super.setModificationAction(action);\r
+    }\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeFactory.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeFactory.java
new file mode 100755 (executable)
index 0000000..8b3b7d4
--- /dev/null
@@ -0,0 +1,204 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.AbstractMap.SimpleEntry;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public abstract class NodeFactory {\r
+\r
+    /**\r
+     * @param qName\r
+     * @param parent\r
+     * @param value\r
+     * @return simple node modification, based on given qname, value and parent\r
+     */\r
+    public static <T> SimpleNode<T> createSimpleNode(QName qName,\r
+            CompositeNode parent, T value) {\r
+        SimpleNodeTOImpl<T> simpleNodeTOImpl = new SimpleNodeTOImpl<T>(qName, parent, value);\r
+        return simpleNodeTOImpl;\r
+    }\r
+    \r
+    /**\r
+     * @param qName\r
+     * @param parent\r
+     * @param value\r
+     * @return simple node modification, based on given qname, value and parent\r
+     */\r
+    public static <T> MutableSimpleNode<T> createMutableSimpleNode(QName qName,\r
+            CompositeNode parent, T value) {\r
+        MutableSimpleNodeTOImpl<T> simpleNodeTOImpl = \r
+                new MutableSimpleNodeTOImpl<T>(qName, parent, value, null);\r
+        return simpleNodeTOImpl;\r
+    }\r
+\r
+    /**\r
+     * @param qName\r
+     * @param parent\r
+     * @param value\r
+     * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
+     */\r
+    public static CompositeNode createCompositeNode(QName qName,\r
+            CompositeNode parent, List<Node<?>> value) {\r
+        CompositeNode compositeNodeTOImpl = new CompositeNodeTOImpl(qName, parent, value);\r
+        return compositeNodeTOImpl;\r
+    }\r
+    \r
+    /**\r
+     * @param qName\r
+     * @param parent\r
+     * @param value\r
+     * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
+     */\r
+    public static MutableCompositeNode createMutableCompositeNode(QName qName,\r
+            CompositeNode parent, List<Node<?>> value) {\r
+        MutableCompositeNodeTOImpl compositeNodeTOImpl = \r
+                new MutableCompositeNodeTOImpl(qName, parent, value, null);\r
+        return compositeNodeTOImpl;\r
+    }\r
+    \r
+    \r
+    /**\r
+     * @param qName\r
+     * @param parent\r
+     * @param value\r
+     * @param modifyAction\r
+     * @return simple node modification, based on given qname, value, parent and modifyAction\r
+     */\r
+    public static <T> SimpleNodeModificationTOImpl<T> createSimpleNodeModification(QName qName,\r
+            CompositeNode parent, T value, ModifyAction modifyAction) {\r
+        SimpleNodeModificationTOImpl<T> simpleNodeModTOImpl = \r
+                new SimpleNodeModificationTOImpl<T>(qName, parent, value, modifyAction);\r
+        return simpleNodeModTOImpl;\r
+    }\r
+\r
+    /**\r
+     * @param qName\r
+     * @param parent\r
+     * @param value\r
+     * @param modifyAction \r
+     * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
+     */\r
+    public static CompositeNodeModificationTOImpl createCompositeNodeModification(QName qName,\r
+            CompositeNode parent, List<Node<?>> value, ModifyAction modifyAction) {\r
+        CompositeNodeModificationTOImpl compositeNodeModTOImpl = \r
+                new CompositeNodeModificationTOImpl(qName, parent, value, modifyAction);\r
+        return compositeNodeModTOImpl;\r
+    }\r
+\r
+    /**\r
+     * @param node\r
+     * @return copy of given node, parent and value are the same, but parent \r
+     * has no reference to this copy \r
+     */\r
+    public static <T> SimpleNode<T> copyNode(SimpleNode<T> node) {\r
+        SimpleNode<T> twinNode = createSimpleNode(\r
+                    node.getNodeType(), node.getParent(), node.getValue());\r
+        return twinNode;\r
+    }\r
+    \r
+    /**\r
+     * @param node\r
+     * @return copy of given node, parent and value are the same, but parent \r
+     * has no reference to this copy \r
+     */\r
+    public static <T> SimpleNode<T> copyNodeAsMutable(SimpleNode<T> node) {\r
+        SimpleNode<T> twinNode = createMutableSimpleNode(\r
+                    node.getNodeType(), node.getParent(), node.getValue());\r
+        return twinNode;\r
+    }\r
+\r
+    /**\r
+     * @param node\r
+     * @param children \r
+     * @return copy of given node, parent and children are the same, but parent and children \r
+     * have no reference to this copy\r
+     */\r
+    public static CompositeNode copyNode(CompositeNode node, Node<?>... children) {\r
+        CompositeNode twinNode = createCompositeNode(\r
+                node.getNodeType(), node.getParent(), Arrays.asList(children));\r
+        return twinNode;\r
+    }\r
+    \r
+    /**\r
+     * @param node\r
+     * @return copy of given node, parent and children are the same, but parent and children \r
+     * have no reference to this copy\r
+     */\r
+    public static CompositeNode copyNode(CompositeNode node) {\r
+       return copyNode(node, node.getChildren().toArray(new Node<?>[0]));\r
+    }\r
+    \r
+    /**\r
+     * @param node root of original tree\r
+     * @param originalToMutable (optional) empty map, where binding between original and copy \r
+     * will be stored\r
+     * @return copy of given node, parent and children are the same, but parent and children \r
+     * have no reference to this copy\r
+     */\r
+    public static MutableCompositeNode copyDeepNode(CompositeNode node, \r
+            Map<Node<?>, Node<?>> originalToMutable) {\r
+              \r
+       MutableCompositeNode mutableRoot = \r
+               createMutableCompositeNode(node.getNodeType(), null, null);\r
+       Stack<SimpleEntry<CompositeNode, MutableCompositeNode>> jobQueue = new Stack<>();\r
+       jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(node, mutableRoot));\r
+       if (originalToMutable != null) {\r
+           originalToMutable.put(node, mutableRoot);\r
+       }\r
+       \r
+       while (!jobQueue.isEmpty()) {\r
+           SimpleEntry<CompositeNode, MutableCompositeNode> job = jobQueue.pop();\r
+           CompositeNode originalNode = job.getKey();\r
+           MutableCompositeNode mutableNode = job.getValue();\r
+           mutableNode.setValue(new ArrayList<Node<?>>());\r
+           \r
+           for (Node<?> child : originalNode.getChildren()) {\r
+               Node<?> mutableAscendant = null;\r
+               if (child instanceof CompositeNode) {\r
+                   MutableCompositeNode newMutable = \r
+                           createMutableCompositeNode(child.getNodeType(), mutableNode, null);\r
+                   jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(\r
+                           (CompositeNode) child, newMutable));\r
+                   mutableAscendant = newMutable;\r
+               } else if (child instanceof SimpleNode<?>) {\r
+                   mutableAscendant = \r
+                           createMutableSimpleNode(child.getNodeType(), mutableNode, child.getValue());\r
+               } else {\r
+                   throw new IllegalStateException("Node class deep copy not supported: "\r
+                           +child.getClass().getName());\r
+               }\r
+               \r
+               mutableNode.getChildren().add(mutableAscendant);\r
+               if (originalToMutable != null) {\r
+                   originalToMutable.put(child, mutableAscendant);\r
+               }\r
+           }\r
+           mutableNode.init();\r
+       }\r
+       \r
+       return mutableRoot;\r
+    }\r
+    \r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImpl.java
new file mode 100755 (executable)
index 0000000..cd71731
--- /dev/null
@@ -0,0 +1,204 @@
+/**\r
+ * \r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableNode;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModificationBuilder;\r
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public class NodeModificationBuilderImpl implements NodeModificationBuilder {\r
+    \r
+    private SchemaContext context;\r
+    \r
+    private Set<MutableNode<?>> changeLog;\r
+    private Map<Node<?>, Node<?>> originalToMutable;\r
+\r
+    private MutableCompositeNode mutableRoot;\r
+\r
+    /**\r
+     * @param originalTreeRootNode \r
+     * @param context\r
+     */\r
+    public NodeModificationBuilderImpl(CompositeNode originalTreeRootNode, SchemaContext context) {\r
+        this.context = context;\r
+        originalToMutable = new HashMap<>();\r
+        mutableRoot = NodeFactory.copyDeepNode(originalTreeRootNode, originalToMutable);\r
+        changeLog = new HashSet<>();\r
+    }\r
+\r
+    /**\r
+     * add given node to it's parent's list of children\r
+     * @param newNode\r
+     */\r
+    private static void fixParentRelation(Node<?> newNode) {\r
+        if (newNode.getParent() != null) {\r
+            List<Node<?>> siblings = newNode.getParent().getChildren();\r
+            if (!siblings.contains(newNode)) {\r
+                siblings.add(newNode);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @param modNode\r
+     * @param action \r
+     */\r
+    private void addModificationToLog(MutableNode<?> modNode, ModifyAction action) {\r
+        modNode.setModifyAction(action);\r
+        changeLog.add(modNode);\r
+    }\r
+\r
+    @Override\r
+    public void addNode(MutableSimpleNode<?> newNode) {\r
+        fixParentRelation(newNode);\r
+        addModificationToLog(newNode, ModifyAction.CREATE);\r
+    }\r
+    \r
+    @Override\r
+    public void addNode(MutableCompositeNode newNode) {\r
+        fixParentRelation(newNode);\r
+        addModificationToLog(newNode, ModifyAction.CREATE);\r
+    }\r
+    \r
+    @Override\r
+    public void replaceNode(MutableSimpleNode<?> replacementNode) {\r
+        addModificationToLog(replacementNode, ModifyAction.REPLACE);\r
+    }\r
+    \r
+    @Override\r
+    public void replaceNode(MutableCompositeNode replacementNode) {\r
+        addModificationToLog(replacementNode, ModifyAction.REPLACE);\r
+    }\r
+\r
+    @Override\r
+    public void deleteNode(MutableCompositeNode deadNode) {\r
+        addModificationToLog(deadNode, ModifyAction.DELETE);\r
+    }\r
+    \r
+    @Override\r
+    public void deleteNode(MutableSimpleNode<?> deadNode) {\r
+        addModificationToLog(deadNode, ModifyAction.DELETE);\r
+    }\r
+\r
+    @Override\r
+    public void removeNode(MutableSimpleNode<?> deadNode) {\r
+        addModificationToLog(deadNode, ModifyAction.REMOVE);\r
+    }\r
+    \r
+    @Override\r
+    public void removeNode(MutableCompositeNode deadNode) {\r
+        addModificationToLog(deadNode, ModifyAction.REMOVE);\r
+    }\r
+    \r
+    @Override\r
+    public void mergeNode(MutableCompositeNode alteredNode) {\r
+        addModificationToLog(alteredNode, ModifyAction.MERGE);\r
+    }\r
+\r
+    /**\r
+     * @return minimalistic tree containing diffs only\r
+     */\r
+    @Override\r
+    public CompositeNode buildDiffTree() {\r
+        Set<Node<?>> wanted = new HashSet<>();\r
+        \r
+        // walk changeLog, collect all required nodes\r
+        for (MutableNode<?> mutant : changeLog) {\r
+            wanted.addAll(collectSelfAndAllParents(mutant));\r
+        }\r
+        \r
+        // TODO:: walk wanted and add relevant keys\r
+        Map<String, ListSchemaNode>  mapOfLists = NodeUtils.buildMapOfListNodes(context);\r
+        Set<Node<?>> wantedKeys = new HashSet<>();\r
+        for (Node<?> outlaw : wanted) {\r
+            if (outlaw instanceof CompositeNode) {\r
+                String path = NodeUtils.buildPath(outlaw);\r
+                if (mapOfLists.containsKey(path)) {\r
+                    ListSchemaNode listSchema = mapOfLists.get(path);\r
+                    if (listSchema.getQName().equals(outlaw.getNodeType())) {\r
+                        // try to add key subnode to wanted list\r
+                        List<QName> supportedKeys = listSchema.getKeyDefinition();\r
+                        for (Node<?> outlawChildren : ((CompositeNode) outlaw).getChildren()) {\r
+                            if (supportedKeys.contains(outlawChildren.getNodeType())) {\r
+                                wantedKeys.add(outlawChildren);\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        wanted.addAll(wantedKeys);\r
+        \r
+        // remove all unwanted nodes from tree\r
+        removeUnrelevantNodes(mutableRoot, wanted);\r
+        \r
+        return mutableRoot;\r
+    }\r
+\r
+    /**\r
+     * @param mutableRoot2\r
+     * @param wanted\r
+     */\r
+    private static void removeUnrelevantNodes(MutableCompositeNode mutRoot,\r
+            Set<Node<?>> wanted) {\r
+        Stack<MutableNode<?>> jobQueue = new Stack<>();\r
+        jobQueue.push(mutRoot);\r
+        while (!jobQueue.isEmpty()) {\r
+            MutableNode<?> mutNode = jobQueue.pop();\r
+            if (!wanted.contains(mutNode)) {\r
+                if (mutNode.getParent() != null) {\r
+                    mutNode.getParent().getChildren().remove(mutNode);\r
+                }\r
+            } else {\r
+                if (mutNode instanceof MutableCompositeNode) {\r
+                    for (Node<?> mutChild : ((MutableCompositeNode) mutNode).getChildren()) {\r
+                        jobQueue.push((MutableNode<?>) mutChild);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @param focusedAncestor\r
+     * @return set of parents and focusedAncestor itself\r
+     */\r
+    private static Set<Node<?>> collectSelfAndAllParents(Node<?> focusedAncestor) {\r
+        Set<Node<?>> family = new HashSet<>();\r
+        Node<?> tmpNode = focusedAncestor;\r
+        while (tmpNode != null) {\r
+            family.add(tmpNode);\r
+            tmpNode = tmpNode.getParent();\r
+        }\r
+        return family;\r
+    }\r
+\r
+    /**\r
+     * @param originalNode\r
+     * @return mutable version of given node\r
+     */\r
+    @Override\r
+    public Node<?> getMutableEquivalent(Node<?> originalNode) {\r
+        return originalToMutable.get(originalNode);\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeUtils.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeUtils.java
new file mode 100755 (executable)
index 0000000..b3a7640
--- /dev/null
@@ -0,0 +1,206 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.AbstractMap.SimpleEntry;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+import java.util.Vector;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.xpath.XPath;\r
+import javax.xml.xpath.XPathConstants;\r
+import javax.xml.xpath.XPathExpression;\r
+import javax.xml.xpath.XPathExpressionException;\r
+import javax.xml.xpath.XPathFactory;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;\r
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import com.google.common.base.Joiner;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public abstract class NodeUtils {\r
+    \r
+    /**\r
+     * \r
+     */\r
+    private static final String USER_KEY_NODE = "node";\r
+    private static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class);\r
+    \r
+    /**\r
+     * @param node\r
+     * @return node path up till root node\r
+     */\r
+    public static String buildPath(Node<?> node) {\r
+        Vector<String> breadCrumbs = new Vector<>();\r
+        Node<?> tmpNode = node;\r
+        while (tmpNode != null) {\r
+            breadCrumbs.insertElementAt(tmpNode.getNodeType().getLocalName(), 0);\r
+            tmpNode = tmpNode.getParent();\r
+        }\r
+        \r
+        return Joiner.on(".").join(breadCrumbs);\r
+    }\r
+\r
+    \r
+    /**\r
+     * @param treeRootNode\r
+     * @return dom tree, containing same node structure, yang nodes are associated \r
+     * to dom nodes as user data\r
+     */\r
+    public static Document buildShadowDomTree(CompositeNode treeRootNode) {\r
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+        Document doc = null;\r
+        try {\r
+            DocumentBuilder bob = dbf.newDocumentBuilder();\r
+            doc = bob.newDocument();\r
+        } catch (ParserConfigurationException e) {\r
+            LOG.error("documentBuilder problem", e);\r
+            return null;\r
+        }\r
+        \r
+        Stack<SimpleEntry<org.w3c.dom.Node, Node<?>>> jobQueue = new Stack<>();\r
+        jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(doc, treeRootNode));\r
+        \r
+        while (!jobQueue.isEmpty()) {\r
+            SimpleEntry<org.w3c.dom.Node, Node<?>> job = jobQueue.pop();\r
+            org.w3c.dom.Node jointPlace = job.getKey();\r
+            Node<?> item = job.getValue();\r
+            Element itemEl = doc.createElement(item.getNodeType().getLocalName());\r
+            itemEl.setUserData(USER_KEY_NODE, item, null);\r
+            if (item instanceof SimpleNode<?>) {\r
+                Object value = ((SimpleNode<?>) item).getValue();\r
+                itemEl.setTextContent(String.valueOf(value));\r
+                itemEl.setAttribute("type", value.getClass().getSimpleName());\r
+            }\r
+            if (item instanceof NodeModification) {\r
+                ModifyAction modificationAction = ((NodeModification) item).getModificationAction();\r
+                if (modificationAction != null) {\r
+                    itemEl.setAttribute("modifyAction", modificationAction.toString());\r
+                }\r
+            }\r
+            \r
+            jointPlace.appendChild(itemEl);\r
+            \r
+            if (item instanceof CompositeNode) {\r
+                for (Node<?> child : ((CompositeNode) item).getChildren()) {\r
+                    jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(itemEl, child));\r
+                }\r
+            }\r
+        }\r
+        \r
+        return doc;\r
+    }\r
+    \r
+    /**\r
+     * @param doc\r
+     * @param xpathEx\r
+     * @return user data value on found node\r
+     * @throws XPathExpressionException\r
+     */\r
+    @SuppressWarnings("unchecked")\r
+    public static <T> T findNodeByXpath(Document doc, String xpathEx) \r
+            throws XPathExpressionException {\r
+        T userNode = null;\r
+        XPathFactory xPathfactory = XPathFactory.newInstance();\r
+        XPath xpath = xPathfactory.newXPath();\r
+        XPathExpression expr = xpath.compile(xpathEx);\r
+        \r
+        org.w3c.dom.Node result = (org.w3c.dom.Node) expr.evaluate(doc, XPathConstants.NODE);\r
+        if (result != null) {\r
+            userNode = (T) result.getUserData(USER_KEY_NODE);\r
+        } \r
+        \r
+        return userNode;\r
+    }\r
+\r
+\r
+    /**\r
+     * build NodeMap, where key = qName; value = node\r
+     * \r
+     * @param value\r
+     * @return map of children, where key = qName and value is list of children groupped by qName  \r
+     */\r
+    public static Map<QName, List<Node<?>>> buildNodeMap(List<Node<?>> value) {\r
+        Map<QName, List<Node<?>>> nodeMapTmp = new HashMap<>();\r
+        if (value == null || value.isEmpty()) {\r
+            throw new IllegalStateException(\r
+                    "nodeList should not be null or empty");\r
+        }\r
+        for (Node<?> node : value) {\r
+            List<Node<?>> qList = nodeMapTmp.get(node.getNodeType());\r
+            if (qList == null) {\r
+                qList = new ArrayList<>();\r
+                nodeMapTmp.put(node.getNodeType(), qList);\r
+            }\r
+            qList.add(node);\r
+        }\r
+        return nodeMapTmp;\r
+    }\r
+\r
+\r
+    /**\r
+     * @param context\r
+     * @return map of lists, where key = path; value = {@link DataSchemaNode}\r
+     */\r
+    public static Map<String, ListSchemaNode> buildMapOfListNodes(\r
+            SchemaContext context) {\r
+        Map<String, ListSchemaNode> mapOfLists = new HashMap<>();\r
+        \r
+        Stack<DataSchemaNode> jobQueue = new Stack<>();\r
+        jobQueue.addAll(context.getDataDefinitions());\r
+        \r
+        while (!jobQueue.isEmpty()) {\r
+            DataSchemaNode dataSchema = jobQueue.pop();\r
+            if (dataSchema instanceof ListSchemaNode) {\r
+                mapOfLists.put(schemaPathToPath(dataSchema.getPath().getPath()), (ListSchemaNode) dataSchema);\r
+            }\r
+            \r
+            if (dataSchema instanceof DataNodeContainer) {\r
+                jobQueue.addAll(((DataNodeContainer) dataSchema).getChildNodes());\r
+            }\r
+        }\r
+        \r
+        return mapOfLists;\r
+    }\r
+\r
+\r
+    /**\r
+     * @param path\r
+     * @return\r
+     */\r
+    private static String schemaPathToPath(List<QName> qNamesPath) {\r
+        List<String> pathSeed = new ArrayList<>();\r
+        for (QName qNameItem : qNamesPath) {\r
+            pathSeed.add(qNameItem.getLocalName());\r
+        }\r
+        return Joiner.on(".").join(pathSeed);\r
+    }\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeModificationTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeModificationTOImpl.java
new file mode 100755 (executable)
index 0000000..7268637
--- /dev/null
@@ -0,0 +1,49 @@
+/**\r
+ * \r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> type of node value\r
+ * \r
+ */\r
+public class SimpleNodeModificationTOImpl<T> extends SimpleNodeTOImpl<T>\r
+        implements NodeModification {\r
+\r
+    private ModifyAction modifyAction;\r
+\r
+    /**\r
+     * @param qname\r
+     * @param parent\r
+     * @param value\r
+     * @param modifyAction \r
+     */\r
+    public SimpleNodeModificationTOImpl(QName qname, CompositeNode parent,\r
+            T value, ModifyAction modifyAction) {\r
+        super(qname, parent, value);\r
+        this.modifyAction = modifyAction;\r
+    }\r
+\r
+    /**\r
+     * @return modification action\r
+     * @see org.opendaylight.controller.yang.data.impl.NodeModificationSupport#getModificationAction()\r
+     */\r
+    @Override\r
+    public ModifyAction getModificationAction() {\r
+        return modifyAction;\r
+    }\r
+\r
+    /**\r
+     * @param modifyAction\r
+     *            the modifyAction to set\r
+     */\r
+    protected void setModificationAction(ModifyAction modifyAction) {\r
+        this.modifyAction = modifyAction;\r
+    }\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeTOImpl.java
new file mode 100755 (executable)
index 0000000..5cfc03a
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> type of simple node value\r
+ * \r
+ */\r
+public class SimpleNodeTOImpl<T> extends AbstractNodeTO<T> implements\r
+        SimpleNode<T> {\r
+\r
+    /**\r
+     * @param qname\r
+     * @param parent\r
+     * @param value\r
+     */\r
+    public SimpleNodeTOImpl(QName qname, CompositeNode parent, T value) {\r
+        super(qname, parent, value);\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeFactoryTest.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeFactoryTest.java
new file mode 100755 (executable)
index 0000000..3d97cc8
--- /dev/null
@@ -0,0 +1,147 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.PrintStream;\r
+import java.net.URI;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class NodeFactoryTest {\r
+\r
+    /**\r
+     * Test method for methods creating immutable nodes in\r
+     * {@link org.opendaylight.controller.yang.data.impl.NodeFactory}.\r
+     * @throws Exception \r
+     */\r
+    @Test\r
+    public void testImmutableNodes() throws Exception {\r
+        QName qName = new QName(\r
+                new URI("urn:opendaylight:controller:network"), \r
+                new Date(42), "yang-data-impl-immutableTest_", null);\r
+        \r
+        CompositeNode network = NodeHelper.buildTestConfigTree(qName);\r
+        \r
+        \r
+        Assert.assertEquals(1, network.getChildren().size());\r
+        Document domTree = NodeUtils.buildShadowDomTree(network);\r
+        NodeHelper.dumpDoc(domTree, System.out);\r
+        \r
+        CompositeNode tpList = NodeUtils.findNodeByXpath(domTree, \r
+                "//node[node-id/text()='nodeId_19']/termination-points");\r
+        \r
+        \r
+        Assert.assertEquals(2, tpList.getCompositesByName("termination-point").size());\r
+//        Assert.assertEquals(1, topologies.getCompositesByName("topology").size());\r
+//        Assert.assertEquals(2, destination.getChildren().size());\r
+    }\r
+\r
+    /**\r
+     * Test method for methods creating immutable nodes in\r
+     * {@link org.opendaylight.controller.yang.data.impl.NodeFactory}.\r
+     * @throws Exception \r
+     */\r
+    @Test\r
+    public void testMutableNodes() throws Exception {\r
+        // <config>\r
+        //   <top xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+        //     <interface xc:operation="delete">\r
+        //       <name>Ethernet0/0</name>\r
+        //       <mtu>1500</mtu>\r
+        //     </interface>\r
+        //     <interface>\r
+        //       <name>Ethernet0/1</name>\r
+        //       <mtu>1501</mtu>\r
+        //     </interface>\r
+        //   </top>\r
+        // </config>\r
+        \r
+        QName qName = new QName(\r
+                new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), \r
+                new Date(42), "yang-data-impl-mutableTest");\r
+        \r
+        List<Node<?>> value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "name"), null, "Ethernet0/0"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "mtu"), null, 1500));\r
+        \r
+        CompositeNodeModificationTOImpl ifNode = NodeFactory.createCompositeNodeModification(\r
+                new QName(qName, "interface"), null, value, ModifyAction.DELETE);\r
+        NodeHelper.assignParentToChildren(ifNode);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "name"), null, "Ethernet1/0"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "mtu"), null, 1501));\r
+        \r
+        CompositeNode ifNode2 = NodeFactory.createCompositeNode(new QName(qName, "interface"), null, value);\r
+        NodeHelper.assignParentToChildren(ifNode2);\r
+\r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(ifNode);\r
+        value.add(ifNode2);\r
+        \r
+        CompositeNode topNode = NodeFactory.createCompositeNode(new QName(qName, "top"), null, value);\r
+        NodeHelper.assignParentToChildren(topNode);\r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(topNode);\r
+        \r
+        CompositeNode root = NodeFactory.createCompositeNode(new QName(qName, "config"), null, value);\r
+        \r
+        \r
+        Assert.assertEquals(1, root.getChildren().size());\r
+        Assert.assertEquals(1, ifNode.getSimpleNodesByName("name").size());\r
+        Assert.assertEquals(1, ifNode.getSimpleNodesByName("mtu").size());\r
+        Assert.assertEquals(2, topNode.getCompositesByName("interface").size());\r
+        NodeModification interfaceMod = (NodeModification) \r
+                topNode.getCompositesByName("interface").get(0);\r
+        Assert.assertEquals(ModifyAction.DELETE, interfaceMod.getModificationAction());\r
+    }\r
+\r
+    /**\r
+     * test modifications builder\r
+     * @throws Exception \r
+     */\r
+    @Test\r
+    public void testCopyDeepNode() throws Exception {\r
+        QName qName = new QName(\r
+                new URI("urn:opendaylight:controller:network"), \r
+                new Date(42), "yang-data-impl-immutableTest_", null);\r
+        \r
+        CompositeNode network = NodeHelper.buildTestConfigTree(qName);\r
+        Map<Node<?>, Node<?>> mutableToOrig = new HashMap<>();\r
+        MutableCompositeNode mutableNetwork = NodeFactory.copyDeepNode(network, mutableToOrig );\r
+\r
+        Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+        ByteArrayOutputStream expected = new ByteArrayOutputStream();\r
+        NodeHelper.dumpDoc(networkShadow, new PrintStream(expected));\r
+        \r
+        Document mutableNetworkShadow = NodeUtils.buildShadowDomTree(mutableNetwork);\r
+        ByteArrayOutputStream actual = new ByteArrayOutputStream();\r
+        NodeHelper.dumpDoc(mutableNetworkShadow, new PrintStream(actual));\r
+        \r
+        Assert.assertEquals(new String(expected.toByteArray()), new String(actual.toByteArray()));\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeHelper.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeHelper.java
new file mode 100755 (executable)
index 0000000..3b7c0d0
--- /dev/null
@@ -0,0 +1,327 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.io.InputStream;\r
+import java.io.PrintStream;\r
+import java.io.StringWriter;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.model.api.Module;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.opendaylight.controller.yang.model.parser.api.YangModelParser;\r
+import org.opendaylight.controller.yang.parser.impl.YangParserImpl;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public abstract class NodeHelper {\r
+    \r
+    /** xml source of example network configuration */\r
+    public static final String NETWORK_XML = \r
+      "<network xmlns=\"urn:opendaylight:controller:network\">\n" +\r
+      //"<network>\n" +\r
+      "    <topologies>\n" +\r
+      "        <topology>\n" +\r
+      "            <topology-id>topId_01</topology-id>\n" +\r
+      "            <nodes>\n" +\r
+      "                <node>\n" +\r
+      "                    <node-id>nodeId_02</node-id>\n" +\r
+      "                    <supporting-ne>networkId_02</supporting-ne>\n" +\r
+      "                    <termination-points>\n" +\r
+      "                        <termination-point>\n" +\r
+      "                            <tp-id>tpId_03</tp-id>\n" +\r
+      "                        </termination-point>\n" +\r
+      "                    </termination-points>\n" +\r
+      "                </node>\n" +\r
+      "                <node>\n" +\r
+      "                    <node-id>nodeId_16</node-id>\n" +\r
+      "                    <supporting-ne>networkId_17</supporting-ne>\n" +\r
+      "                    <termination-points>\n" +\r
+      "                        <termination-point>\n" +\r
+      "                            <tp-id>tpId_18</tp-id>\n" +\r
+      "                        </termination-point>\n" +\r
+      "                    </termination-points>\n" +\r
+      "                </node>\n" +\r
+      "                <node>\n" +\r
+      "                    <node-id>nodeId_19</node-id>\n" +\r
+      "                    <supporting-ne>networkId_20</supporting-ne>\n" +\r
+      "                    <termination-points>\n" +\r
+      "                        <termination-point>\n" +\r
+      "                            <tp-id>tpId_18</tp-id>\n" +\r
+      "                        </termination-point>\n" +\r
+      "                        <termination-point>\n" +\r
+      "                            <tp-id>tpId_19</tp-id>\n" +\r
+      "                        </termination-point>\n" +\r
+      "                    </termination-points>\n" +\r
+      "                </node>\n" +\r
+      "            </nodes>\n" +\r
+      "            <links>\n" +\r
+      "                <link>\n" +\r
+      "                    <link-id>linkId_04</link-id>\n" +\r
+      "                    <source>\n" +\r
+      "                        <source-node>nodeId_05</source-node>\n" +\r
+      "                        <source-tp>tpId_06</source-tp>\n" +\r
+      "                    </source>\n" +\r
+      "                    <destination>\n" +\r
+      "                        <dest-node>nodeId_07</dest-node>\n" +\r
+      "                        <dest-tp>tpId_08</dest-tp>\n" +\r
+      "                    </destination>\n" +\r
+      "                </link>\n" +\r
+      "                <link>\n" +\r
+      "                    <link-id>linkId_11</link-id>\n" +\r
+      "                    <source>\n" +\r
+      "                        <source-node>nodeId_12</source-node>\n" +\r
+      "                        <source-tp>tpId_13</source-tp>\n" +\r
+      "                    </source>\n" +\r
+      "                    <destination>\n" +\r
+      "                        <dest-node>nodeId_14</dest-node>\n" +\r
+      "                        <dest-tp>tpId_15</dest-tp>\n" +\r
+      "                    </destination>\n" +\r
+      "                </link>\n" +\r
+      "            </links>\n" +\r
+      "        </topology>\n" +\r
+      "    </topologies>\n" +\r
+      "    <network-elements>\n" +\r
+      "        <network-element>\n" +\r
+      "            <element-id>ntElementId_09</element-id>\n" +\r
+      "        </network-element>\n" +\r
+      "        <network-element>\n" +\r
+      "            <element-id>ntElementId_10</element-id>\n" +\r
+      "        </network-element>\n" +\r
+      "    </network-elements>\n" +\r
+      "</network>";\r
+\r
+    /**\r
+     * @param domTree\r
+     * @param out\r
+     * @throws Exception \r
+     */\r
+    public static void dumpDoc(Document domTree, PrintStream out) throws Exception {\r
+      TransformerFactory transformerFact = TransformerFactory.newInstance();\r
+      transformerFact.setAttribute("indent-number", 4);\r
+      Transformer transformer = transformerFact.newTransformer();\r
+      transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+      //initialize StreamResult with File object to save to file\r
+      StreamResult result = new StreamResult(new StringWriter());\r
+      DOMSource source = new DOMSource(domTree);\r
+      transformer.transform(source, result);\r
+      String xmlString = result.getWriter().toString();\r
+      out.println(xmlString);\r
+    }\r
+\r
+    /**\r
+     * @param qName\r
+     * @return example tree, see {@link #NETWORK_XML}\r
+     */\r
+    public static CompositeNode buildTestConfigTree(QName qName) {\r
+        List<Node<?>> value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "element-id"), null, "ntElementId_09"));\r
+        CompositeNode ntElementNode1 = NodeFactory.createCompositeNode(new QName(qName, "network-element"), null, value);\r
+        assignParentToChildren(ntElementNode1);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "element-id"), null, "ntElementId_10"));\r
+        CompositeNode ntElementNode2 = NodeFactory.createCompositeNode(new QName(qName, "network-element"), null, value);\r
+        assignParentToChildren(ntElementNode2);\r
+        \r
+        value = new ArrayList<Node<?>>();\r
+        value.add(ntElementNode1);\r
+        value.add(ntElementNode2);\r
+        CompositeNode ntElementsNode = NodeFactory.createCompositeNode(\r
+                new QName(qName, "network-elements"), null, value);\r
+        assignParentToChildren(ntElementsNode);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-node"), null, "nodeId_07"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-tp"), null, "tpId_08"));\r
+        CompositeNode destination = NodeFactory.createCompositeNode(\r
+                new QName(qName, "destination"), null, value);\r
+        assignParentToChildren(destination);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "source-node"), null, "nodeId_05"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "source-tp"), null, "tpId_06"));\r
+        CompositeNode source = NodeFactory.createCompositeNode(\r
+                new QName(qName, "source"), null, value);\r
+        assignParentToChildren(source);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "link-id"), null, "linkId_04"));\r
+        value.add(source);\r
+        value.add(destination);\r
+        CompositeNode link1 = NodeFactory.createCompositeNode(\r
+                new QName(qName, "link"), null, value);\r
+        assignParentToChildren(link1);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-node"), null, "nodeId_14"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-tp"), null, "tpId_15"));\r
+        destination = NodeFactory.createCompositeNode(\r
+                new QName(qName, "destination"), null, value);\r
+        assignParentToChildren(destination);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "source-node"), null, "nodeId_12"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "source-tp"), null, "tpId_13"));\r
+        source = NodeFactory.createCompositeNode(\r
+                new QName(qName, "source"), null, value);\r
+        assignParentToChildren(source);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "link-id"), null, "linkId_11"));\r
+        value.add(source);\r
+        value.add(destination);\r
+        CompositeNode link2 = NodeFactory.createCompositeNode(\r
+                new QName(qName, "link"), null, value);\r
+        assignParentToChildren(link2);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(link1);\r
+        value.add(link2);\r
+        CompositeNode links = NodeFactory.createCompositeNode(\r
+                new QName(qName, "links"), null, value);\r
+        assignParentToChildren(links);\r
+        \r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_03"));\r
+        CompositeNode terminationPointNode1 = NodeFactory.createCompositeNode(\r
+                new QName(qName, "termination-point"), null, value);\r
+        assignParentToChildren(terminationPointNode1);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(terminationPointNode1);\r
+        CompositeNode terminationPointsNode = NodeFactory.createCompositeNode(\r
+                new QName(qName, "termination-points"), null, value);\r
+        assignParentToChildren(terminationPointsNode);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_02"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_02"));\r
+        value.add(terminationPointsNode);\r
+        CompositeNode node1Node = NodeFactory.createCompositeNode(\r
+                new QName(qName, "node"), null, value);\r
+        assignParentToChildren(node1Node);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_18"));\r
+        terminationPointNode1 = NodeFactory.createCompositeNode(\r
+                new QName(qName, "termination-point"), null, value);\r
+        assignParentToChildren(terminationPointNode1);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(terminationPointNode1);\r
+        terminationPointsNode = NodeFactory.createCompositeNode(\r
+                new QName(qName, "termination-points"), null, value);\r
+        assignParentToChildren(terminationPointsNode);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_16"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_17"));\r
+        value.add(terminationPointsNode);\r
+        CompositeNode node2Node = NodeFactory.createCompositeNode(\r
+                new QName(qName, "node"), null, value);\r
+        assignParentToChildren(node2Node);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_18"));\r
+        terminationPointNode1 = NodeFactory.createCompositeNode(\r
+                new QName(qName, "termination-point"), null, value);\r
+        assignParentToChildren(terminationPointNode1);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_19"));\r
+        CompositeNode terminationPointNode2 = NodeFactory.createCompositeNode(\r
+                new QName(qName, "termination-point"), null, value);\r
+        assignParentToChildren(terminationPointNode2);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(terminationPointNode1);\r
+        value.add(terminationPointNode2);\r
+        terminationPointsNode = NodeFactory.createCompositeNode(\r
+                new QName(qName, "termination-points"), null, value);\r
+        assignParentToChildren(terminationPointsNode);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_19"));\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_20"));\r
+        value.add(terminationPointsNode);\r
+        CompositeNode node3Node = NodeFactory.createCompositeNode(\r
+                new QName(qName, "node"), null, value);\r
+        assignParentToChildren(node3Node);\r
+        \r
+        value = new ArrayList<Node<?>>(); \r
+        value.add(node1Node);\r
+        value.add(node2Node);\r
+        value.add(node3Node);\r
+        CompositeNode nodesNode = NodeFactory.createCompositeNode(\r
+                new QName(qName, "nodes"), null, value);\r
+        assignParentToChildren(nodesNode);\r
+        \r
+        value = new ArrayList<Node<?>>();\r
+        value.add(links);\r
+        value.add(nodesNode);\r
+        value.add(NodeFactory.createSimpleNode(new QName(qName, "topology-id"), null, "topId_01"));\r
+        CompositeNode topology = NodeFactory.createCompositeNode(\r
+                new QName(qName, "topology"), null, value);\r
+        assignParentToChildren(topology);\r
+        \r
+        value = new ArrayList<Node<?>>();\r
+        value.add(topology);\r
+        CompositeNode topologies = NodeFactory.createCompositeNode(\r
+                new QName(qName, "topologies"), null, value);\r
+        assignParentToChildren(topologies);\r
+        \r
+        value = new ArrayList<Node<?>>();\r
+        value.add(topologies);\r
+        CompositeNode network = NodeFactory.createCompositeNode(\r
+                new QName(qName, "network"), null, value);\r
+        assignParentToChildren(network);\r
+        \r
+        return network;\r
+    }\r
+\r
+    /**\r
+     * @param parentNode\r
+     */\r
+    public static void assignParentToChildren(CompositeNode parentNode) {\r
+        for (Node<?> child : parentNode.getChildren()) {\r
+            ((AbstractNodeTO<?>) child).setParent(parentNode);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @return schema context of controller-network.yang\r
+     */\r
+    public static SchemaContext loadSchemaContext() {\r
+        YangModelParser yParser = new YangParserImpl();\r
+        List<InputStream> yangInputStreams = new ArrayList<>();\r
+        yangInputStreams.add(NodeHelper.class.getResourceAsStream(\r
+                "/controller-network.yang"));\r
+        yangInputStreams.add(NodeHelper.class.getResourceAsStream(\r
+                "/ietf-inet-types@2010-09-24.yang"));\r
+        Set<Module> modules = yParser\r
+                .parseYangModelsFromStreams(yangInputStreams);\r
+        return yParser.resolveSchemaContext(modules);\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImplTest.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImplTest.java
new file mode 100755 (executable)
index 0000000..2df397a
--- /dev/null
@@ -0,0 +1,92 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.net.URI;\r
+import java.util.Date;\r
+\r
+import junit.framework.Assert;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class NodeModificationBuilderImplTest {\r
+\r
+    private SchemaContext schemaCtx;\r
+    private QName qName;\r
+    private CompositeNode network;\r
+    private NodeModificationBuilderImpl nodeModificationBuilder;\r
+\r
+    /**\r
+     * prepare schemaContext\r
+     * @throws Exception \r
+     */\r
+    @Before\r
+    public void setUp() throws Exception {\r
+        schemaCtx = NodeHelper.loadSchemaContext();\r
+\r
+        qName = new QName(\r
+                new URI("urn:opendaylight:controller:network"), \r
+                new Date(1369000800000L), "topos");\r
+        network = NodeHelper.buildTestConfigTree(qName);\r
+        \r
+        nodeModificationBuilder = new NodeModificationBuilderImpl(network, schemaCtx);\r
+    }\r
+\r
+    /**\r
+     * Test method for\r
+     * {@link org.opendaylight.controller.yang.data.impl.NodeModificationBuilderImpl#buildDiffTree()}\r
+     * .\r
+     * @throws Exception \r
+     */\r
+    @Test\r
+    public void testBuildDiffTree() throws Exception {\r
+        Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+        SimpleNode<String> needle = NodeUtils.findNodeByXpath(networkShadow, \r
+                "//node[node-id='nodeId_19']//termination-point[2]/tp-id");\r
+        \r
+        @SuppressWarnings("unchecked")\r
+        MutableSimpleNode<String> mutableNeedle = (MutableSimpleNode<String>) \r
+                nodeModificationBuilder.getMutableEquivalent(needle);\r
+        \r
+        mutableNeedle.setValue("tpId_18x");\r
+        nodeModificationBuilder.replaceNode(mutableNeedle);\r
+        CompositeNode diffTree = nodeModificationBuilder.buildDiffTree();\r
+        \r
+        Document diffShadow = NodeUtils.buildShadowDomTree(diffTree);\r
+        NodeHelper.dumpDoc(diffShadow, System.out);\r
+    }\r
+\r
+    /**\r
+     * Test method for\r
+     * {@link org.opendaylight.controller.yang.data.impl.NodeModificationBuilderImpl#getMutableEquivalent(org.opendaylight.controller.yang.data.api.Node)}\r
+     * .\r
+     */\r
+    @Test\r
+    public void testGetMutableEquivalent() {\r
+        MutableCompositeNode rootMutable = (MutableCompositeNode) \r
+                nodeModificationBuilder.getMutableEquivalent(network);\r
+        \r
+        CompositeNode topologies = network.getCompositesByName("topologies").iterator().next();\r
+        CompositeNode topologiesMutable = rootMutable.getCompositesByName("topologies").iterator().next();\r
+        \r
+        Assert.assertSame(topologiesMutable, nodeModificationBuilder.getMutableEquivalent(topologies));\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java
new file mode 100755 (executable)
index 0000000..487c10c
--- /dev/null
@@ -0,0 +1,110 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.PrintStream;\r
+import java.net.URI;\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public class NodeUtilsTest {\r
+    \r
+    private QName qName;\r
+    private CompositeNode network;\r
+\r
+    /**\r
+     * @throws Exception\r
+     */\r
+    @Before\r
+    public void setUp() throws Exception {\r
+        qName = new QName(\r
+                new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), \r
+                new Date(42), "yang-data-impl-mutableTest");\r
+        network = NodeHelper.buildTestConfigTree(qName);\r
+    }\r
+\r
+    /**\r
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildPath(org.opendaylight.controller.yang.data.api.Node)}.\r
+     * @throws Exception \r
+     */\r
+    @Test\r
+    public void testBuildPath() throws Exception {\r
+        SimpleNode<?> needle = network.getCompositesByName("topologies").iterator().next()\r
+            .getCompositesByName("topology").iterator().next()\r
+            .getSimpleNodesByName("topology-id").iterator().next();\r
+        String breadCrumbs = NodeUtils.buildPath(needle);\r
+        \r
+        Assert.assertEquals("network.topologies.topology.topology-id", breadCrumbs);\r
+    }\r
+\r
+    /**\r
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildShadowDomTree(org.opendaylight.controller.yang.data.api.CompositeNode)}.\r
+     * @throws Exception \r
+     */\r
+    @Test\r
+    public void testBuildShadowDomTree() throws Exception {\r
+        Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+        ByteArrayOutputStream actual = new ByteArrayOutputStream();\r
+        NodeHelper.dumpDoc(networkShadow, new PrintStream(actual));\r
+        \r
+        Assert.assertEquals(2760, new String(actual.toByteArray()).length());\r
+    }\r
+\r
+    /**\r
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#findNodeByXpath(org.w3c.dom.Document, java.lang.String)}.\r
+     * @throws Exception \r
+     */\r
+    @Test\r
+    public void testFindNodeByXpath() throws Exception {\r
+        Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+        SimpleNode<String> needle = NodeUtils.findNodeByXpath(networkShadow, \r
+                "//node[node-id='nodeId_19']//termination-point[2]/tp-id");\r
+        Assert.assertNotNull(needle);\r
+        Assert.assertEquals("tpId_18", needle.getValue());\r
+    }\r
+\r
+    /**\r
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildNodeMap(java.util.List)}.\r
+     */\r
+    @Test\r
+    public void testBuildNodeMap() {\r
+        CompositeNode topology = network.getCompositesByName("topologies").iterator().next()\r
+            .getCompositesByName("topology").iterator().next();\r
+        \r
+        Map<QName, List<Node<?>>> nodeMap = NodeUtils.buildNodeMap(topology.getChildren());\r
+        Assert.assertEquals(3, nodeMap.size());\r
+    }\r
+    \r
+    /**\r
+     * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildMapOfListNodes(org.opendaylight.controller.yang.model.api.SchemaContext)}.\r
+     */\r
+    @Test\r
+    public void testBuildMapOfListNodes() {\r
+        SchemaContext schemaCtx = NodeHelper.loadSchemaContext();\r
+        Map<String, ListSchemaNode> mapOfLists = NodeUtils.buildMapOfListNodes(schemaCtx);\r
+        Assert.assertEquals(5, mapOfLists.size());\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config01.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config01.xml
new file mode 100755 (executable)
index 0000000..8ffac5b
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>\r
+<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+    <edit-config>\r
+        <target>\r
+            <running />\r
+        </target>\r
+        <config>\r
+            <top xmlns="http://example.com/schema/1.2/config">\r
+                <interface>\r
+                    <name>Ethernet0/0</name>\r
+                    <mtu>1500</mtu>\r
+                </interface>\r
+            </top>\r
+        </config>\r
+    </edit-config>\r
+</rpc>\r
+     
\ No newline at end of file
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.content b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.content
new file mode 100755 (executable)
index 0000000..e9c05c9
--- /dev/null
@@ -0,0 +1,73 @@
+xmlDoc.network(xmlns: 'urn:opendaylight:controller:network') {\r
+    topologies {\r
+      topology {\r
+        'topology-id'('topId_'+cnt.get())\r
+        \r
+        types()\r
+        nodes {\r
+          node {\r
+            'node-id'('nodeId_'+cnt.get())\r
+            'supporting-ne'('networkId_'+cnt.get())\r
+            'termination-points' {\r
+              'termination-point' {\r
+                'tp-id'('tpId_'+cnt.get())\r
+              }\r
+            }\r
+          }\r
+          node {\r
+            'node-id'('nodeId_'+cnt.get())\r
+            'supporting-ne'('networkId_'+cnt.get())\r
+            'termination-points' {\r
+              'termination-point' {\r
+                'tp-id'('tpId_'+cnt.get())\r
+              }\r
+            }\r
+          }\r
+          node {\r
+            'node-id'('nodeId_'+cnt.get())\r
+            'supporting-ne'('networkId_'+cnt.get())\r
+            'termination-points' {\r
+              'termination-point' {\r
+                'tp-id'('tpId_'+cnt.get())\r
+              }\r
+              'termination-point' {\r
+                'tp-id'('tpId_'+cnt.get())\r
+              }\r
+            }\r
+          }\r
+        }\r
+        links {\r
+          link {\r
+            'link-id'('linkId_'+cnt.get())\r
+            source {\r
+              'source-node'('nodeId_'+cnt.get())\r
+              'source-tp'('tpId_'+cnt.get(false))\r
+            }\r
+            destination {\r
+              'dest-node'('nodeId_'+cnt.get())\r
+              'dest-tp'('tpId_'+cnt.get(false))\r
+            }\r
+          }\r
+          link {\r
+            'link-id'('linkId_'+cnt.get())\r
+            source {\r
+              'source-node'('nodeId_'+cnt.get())\r
+              'source-tp'('tpId_'+cnt.get(false))\r
+            }\r
+            destination {\r
+              'dest-node'('nodeId_'+cnt.get())\r
+              'dest-tp'('tpId_'+cnt.get(false))\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+    'network-elements' {\r
+      'network-element' {\r
+        'element-id'('ntElementId_'+cnt.get())\r
+      }\r
+      'network-element' {\r
+        'element-id'('ntElementId_'+cnt.get())\r
+      }\r
+    }\r
+  }
\ No newline at end of file
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.xml
new file mode 100755 (executable)
index 0000000..99b862b
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<network xmlns="urn:opendaylight:controller:network">\r
+    <topologies>\r
+        <topology>\r
+            <topology-id>topId_01</topology-id>\r
+            <types></types>\r
+            <nodes>\r
+                <node>\r
+                    <node-id>nodeId_02</node-id>\r
+                    <supporting-ne>networkId_02</supporting-ne>\r
+                    <termination-points>\r
+                        <termination-point>\r
+                            <tp-id>tpId_03</tp-id>\r
+                        </termination-point>\r
+                    </termination-points>\r
+                </node>\r
+                <node>\r
+                    <node-id>nodeId_16</node-id>\r
+                    <supporting-ne>networkId_17</supporting-ne>\r
+                    <termination-points>\r
+                        <termination-point>\r
+                            <tp-id>tpId_18</tp-id>\r
+                        </termination-point>\r
+                    </termination-points>\r
+                </node>\r
+                <node>\r
+                    <node-id>nodeId_19</node-id>\r
+                    <supporting-ne>networkId_20</supporting-ne>\r
+                    <termination-points>\r
+                        <termination-point>\r
+                            <tp-id>tpId_18</tp-id>\r
+                        </termination-point>\r
+                        <termination-point>\r
+                            <tp-id>tpId_19</tp-id>\r
+                        </termination-point>\r
+                    </termination-points>\r
+                </node>\r
+            </nodes>\r
+            <links>\r
+                <link>\r
+                    <link-id>linkId_04</link-id>\r
+                    <source>\r
+                        <source-node>nodeId_05</source-node>\r
+                        <source-tp>tpId_06</source-tp>\r
+                    </source>\r
+                    <destination>\r
+                        <dest-node>nodeId_07</dest-node>\r
+                        <dest-tp>tpId_08</dest-tp>\r
+                    </destination>\r
+                </link>\r
+                <link>\r
+                    <link-id>linkId_11</link-id>\r
+                    <source>\r
+                        <source-node>nodeId_12</source-node>\r
+                        <source-tp>tpId_13</source-tp>\r
+                    </source>\r
+                    <destination>\r
+                        <dest-node>nodeId_14</dest-node>\r
+                        <dest-tp>tpId_15</dest-tp>\r
+                    </destination>\r
+                </link>\r
+            </links>\r
+        </topology>\r
+    </topologies>\r
+    <network-elements>\r
+        <network-element>\r
+            <element-id>ntElementId_09</element-id>\r
+        </network-element>\r
+        <network-element>\r
+            <element-id>ntElementId_10</element-id>\r
+        </network-element>\r
+    </network-elements>\r
+</network>\r
+\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02g.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02g.xml
new file mode 100644 (file)
index 0000000..d1ac68c
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<network xmlns="urn:opendaylight:controller:network">
+  <topologies>
+    <topology>
+      <topology-id>topId_01</topology-id>
+      <types />
+      <nodes>
+        <node>
+          <node-id>nodeId_02</node-id>
+          <supporting-ne>networkId_03</supporting-ne>
+          <termination-points>
+            <termination-point>
+              <tp-id>tpId_04</tp-id>
+            </termination-point>
+          </termination-points>
+        </node>
+        <node>
+          <node-id>nodeId_05</node-id>
+          <supporting-ne>networkId_06</supporting-ne>
+          <termination-points>
+            <termination-point>
+              <tp-id>tpId_07</tp-id>
+            </termination-point>
+          </termination-points>
+        </node>
+        <node>
+          <node-id>nodeId_08</node-id>
+          <supporting-ne>networkId_09</supporting-ne>
+          <termination-points>
+            <termination-point>
+              <tp-id>tpId_10</tp-id>
+            </termination-point>
+            <termination-point>
+              <tp-id>tpId_11</tp-id>
+            </termination-point>
+          </termination-points>
+        </node>
+      </nodes>
+      <links>
+        <link>
+          <link-id>linkId_12</link-id>
+          <source>
+            <source-node>nodeId_13</source-node>
+            <source-tp>tpId_13</source-tp>
+          </source>
+          <destination>
+            <dest-node>nodeId_14</dest-node>
+            <dest-tp>tpId_14</dest-tp>
+          </destination>
+        </link>
+        <link>
+          <link-id>linkId_15</link-id>
+          <source>
+            <source-node>nodeId_16</source-node>
+            <source-tp>tpId_16</source-tp>
+          </source>
+          <destination>
+            <dest-node>nodeId_17</dest-node>
+            <dest-tp>tpId_17</dest-tp>
+          </destination>
+        </link>
+      </links>
+    </topology>
+  </topologies>
+  <network-elements>
+    <network-element>
+      <element-id>ntElementId_18</element-id>
+    </network-element>
+    <network-element>
+      <element-id>ntElementId_19</element-id>
+    </network-element>
+  </network-elements>
+</network>\r
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.xsd b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.xsd
new file mode 100755 (executable)
index 0000000..6cadb69
--- /dev/null
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:yin="urn:ietf:params:xml:schema:yang:yin:1"
+           targetNamespace="urn:opendaylight:controller:network"
+           xmlns="urn:opendaylight:controller:network"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           version="2013-05-20"
+           xml:lang="en"
+           xmlns:topos="urn:opendaylight:controller:network"
+           xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types">
+
+  <xs:import namespace="urn:ietf:params:xml:ns:yang:ietf-inet-types"
+             schemaLocation="ietf-inet-types@2010-09-24.xsd"/>
+
+  <xs:annotation>
+    <xs:documentation>
+      This schema was generated from the YANG module controller-network
+      by pyang version 1.2.
+
+      The schema describes an instance document consisting
+      of the entire configuration data store, operational
+      data, rpc operations, and notifications.
+      This schema can thus NOT be used as-is to
+      validate NETCONF PDUs.
+    </xs:documentation>
+  </xs:annotation>
+
+
+  <!-- YANG typedefs -->
+  <xs:simpleType name="topology-id">
+    <xs:restriction base="xs:string">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="node-id">
+    <xs:restriction base="xs:string">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="link-id">
+    <xs:restriction base="xs:string">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="tp-id">
+    <xs:annotation>
+      <xs:documentation>
+        identifier for termination points on a port
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:string">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="tp-ref">
+    <xs:restriction base="tp-id">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="topology-ref">
+    <xs:annotation>
+      <xs:documentation>
+        This type is used for leafs that reference topology identifier instance.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="topology-id">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="node-ref">
+    <xs:annotation>
+      <xs:documentation>
+        This type is used for leafs that reference a node instance.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="node-id">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="link-ref">
+    <xs:annotation>
+      <xs:documentation>
+        This type is used for leafs that reference a link instance.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="link-id">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="network-element-ref">
+    <xs:restriction base="element-id">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="element-id">
+    <xs:restriction base="xs:string">
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:element name="network">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="topologies" minOccurs="0">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="topology" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                  <xs:documentation>
+
+                    This is the model of abstract topology which contains only Network
+                    Nodes and Network Links. Each topology MUST be identified by
+                    unique topology-id for reason that the store could contain many
+                    topologies.
+
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="topology-id"  type="topology-id">
+                      <xs:annotation>
+                        <xs:documentation>
+
+                          It is presumed that datastore will contain many topologies. To
+                          distinguish between topologies it is vital to have UNIQUE
+                          topology identifier.
+
+                        </xs:documentation>
+                      </xs:annotation>
+                    </xs:element>
+                    <xs:element name="types" minOccurs="0">
+                      <xs:annotation>
+                        <xs:documentation>
+
+                          The container for definition of topology types.
+                          The augmenting modules should add empty optional leaf 
+                          to this container to signalize topology type.
+
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:any minOccurs="0" maxOccurs="unbounded"
+                                  namespace="##other" processContents="lax"/>
+                        </xs:sequence>
+                      </xs:complexType>
+                    </xs:element>
+                    <xs:element name="nodes" minOccurs="0">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="node" minOccurs="0" maxOccurs="unbounded">
+                            <xs:annotation>
+                              <xs:documentation>
+                                The list of network nodes defined for topology.
+                              </xs:documentation>
+                            </xs:annotation>
+                            <xs:complexType>
+                              <xs:sequence>
+                                <xs:element name="node-id"  type="node-id">
+                                  <xs:annotation>
+                                    <xs:documentation>
+                                      The Topology identifier of network-node.
+                                    </xs:documentation>
+                                  </xs:annotation>
+                                </xs:element>
+                                <xs:element name="supporting-ne" minOccurs="0"  type="network-element-ref">
+                                </xs:element>
+                                <xs:element name="termination-points" minOccurs="0">
+                                  <xs:complexType>
+                                    <xs:sequence>
+                                      <xs:element name="termination-point" minOccurs="0" maxOccurs="unbounded">
+                                        <xs:complexType>
+                                          <xs:sequence>
+                                            <xs:element name="tp-id"  type="tp-id">
+                                            </xs:element>
+                                            <xs:any minOccurs="0" maxOccurs="unbounded"
+                                                    namespace="##other" processContents="lax"/>
+                                          </xs:sequence>
+                                        </xs:complexType>
+                                      </xs:element>
+                                      <xs:any minOccurs="0" maxOccurs="unbounded"
+                                              namespace="##other" processContents="lax"/>
+                                    </xs:sequence>
+                                  </xs:complexType>
+                                  <xs:key name="key_termination-points_node_nodes_topology_topologies_network_termination-point">
+                                    <xs:selector xpath="topos:termination-point"/>
+                                    <xs:field xpath="topos:tp-id"/>
+                                  </xs:key>
+                                </xs:element>
+                                <xs:any minOccurs="0" maxOccurs="unbounded"
+                                        namespace="##other" processContents="lax"/>
+                              </xs:sequence>
+                            </xs:complexType>
+                          </xs:element>
+                          <xs:any minOccurs="0" maxOccurs="unbounded"
+                                  namespace="##other" processContents="lax"/>
+                        </xs:sequence>
+                      </xs:complexType>
+                      <xs:key name="key_nodes_topology_topologies_network_node">
+                        <xs:selector xpath="topos:node"/>
+                        <xs:field xpath="topos:node-id"/>
+                      </xs:key>
+                    </xs:element>
+                    <xs:element name="links" minOccurs="0">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="link" minOccurs="0" maxOccurs="unbounded">
+                            <xs:annotation>
+                              <xs:documentation>
+
+                                The Network Link which is defined by Local (Source) and
+                                Remote (Destination) Network Nodes. Every link MUST be
+                                defined either by identifier and his local and remote
+                                Network Nodes (in real applications it is common that many
+                                links are originated from one node and end up in same
+                                remote node). To ensure that we would always know to
+                                distinguish between links, every link SHOULD have
+                                identifier.
+
+                              </xs:documentation>
+                            </xs:annotation>
+                            <xs:complexType>
+                              <xs:sequence>
+                                <xs:element name="link-id"  type="link-id">
+                                </xs:element>
+                                <xs:element name="source" minOccurs="0">
+                                  <xs:complexType>
+                                    <xs:sequence>
+                                      <xs:element name="source-node" minOccurs="0"  type="node-ref">
+                                        <xs:annotation>
+                                          <xs:documentation>
+                                            Source node identifier.
+                                          </xs:documentation>
+                                        </xs:annotation>
+                                      </xs:element>
+                                      <xs:element name="source-tp" minOccurs="0"  type="tp-ref">
+                                      </xs:element>
+                                      <xs:any minOccurs="0" maxOccurs="unbounded"
+                                              namespace="##other" processContents="lax"/>
+                                    </xs:sequence>
+                                  </xs:complexType>
+                                </xs:element>
+                                <xs:element name="destination" minOccurs="0">
+                                  <xs:complexType>
+                                    <xs:sequence>
+                                      <xs:element name="dest-node" minOccurs="0"  type="node-ref">
+                                        <xs:annotation>
+                                          <xs:documentation>
+                                            Destination node identifier.
+                                          </xs:documentation>
+                                        </xs:annotation>
+                                      </xs:element>
+                                      <xs:element name="dest-tp" minOccurs="0"  type="tp-ref">
+                                      </xs:element>
+                                      <xs:any minOccurs="0" maxOccurs="unbounded"
+                                              namespace="##other" processContents="lax"/>
+                                    </xs:sequence>
+                                  </xs:complexType>
+                                </xs:element>
+                                <xs:any minOccurs="0" maxOccurs="unbounded"
+                                        namespace="##other" processContents="lax"/>
+                              </xs:sequence>
+                            </xs:complexType>
+                          </xs:element>
+                          <xs:any minOccurs="0" maxOccurs="unbounded"
+                                  namespace="##other" processContents="lax"/>
+                        </xs:sequence>
+                      </xs:complexType>
+                      <xs:key name="key_links_topology_topologies_network_link">
+                        <xs:selector xpath="topos:link"/>
+                        <xs:field xpath="topos:link-id"/>
+                      </xs:key>
+                    </xs:element>
+                    <xs:any minOccurs="0" maxOccurs="unbounded"
+                            namespace="##other" processContents="lax"/>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+              <xs:any minOccurs="0" maxOccurs="unbounded"
+                      namespace="##other" processContents="lax"/>
+            </xs:sequence>
+          </xs:complexType>
+          <xs:key name="key_topologies_network_topology">
+            <xs:selector xpath="topos:topology"/>
+            <xs:field xpath="topos:topology-id"/>
+          </xs:key>
+        </xs:element>
+        <xs:element name="network-elements" minOccurs="0">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="network-element" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="element-id"  type="element-id">
+                    </xs:element>
+                    <xs:any minOccurs="0" maxOccurs="unbounded"
+                            namespace="##other" processContents="lax"/>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+              <xs:any minOccurs="0" maxOccurs="unbounded"
+                      namespace="##other" processContents="lax"/>
+            </xs:sequence>
+          </xs:complexType>
+          <xs:key name="key_network-elements_network_network-element">
+            <xs:selector xpath="topos:network-element"/>
+            <xs:field xpath="topos:element-id"/>
+          </xs:key>
+        </xs:element>
+        <xs:any minOccurs="0" maxOccurs="unbounded"
+                namespace="##other" processContents="lax"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+
+</xs:schema>
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.yang b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.yang
new file mode 100755 (executable)
index 0000000..022ece9
--- /dev/null
@@ -0,0 +1,172 @@
+module controller-network {
+    yang-version 1;
+    namespace "urn:opendaylight:controller:network";
+    prefix "topos";
+    
+    import ietf-inet-types { prefix "inet"; }
+    
+    revision 2013-05-20 {
+       description "Initial demo";
+    }
+    
+
+    
+    
+    typedef topology-id {
+        type string;
+    }
+
+    typedef node-id {
+        type string;
+    }
+
+    typedef link-id {
+        type string;
+    }
+
+    typedef tp-id {
+        type string;
+        description "identifier for termination points on a port";
+    }
+
+    typedef tp-ref {
+        type leafref {
+            path "/network/topologies/topology/nodes/node/termination-points/termination-point/tp-id";
+        }
+    }
+    typedef topology-ref {
+        type leafref {
+            path "/network/topologies/topology/topology-id";
+        }
+        description "This type is used for leafs that reference topology identifier instance.";
+        // currently not used
+    }
+
+    typedef node-ref {
+        type leafref {
+            path "/network/topologies/topology/nodes/node/node-id";
+        }
+        description "This type is used for leafs that reference a node instance.";
+    }
+
+    typedef link-ref {
+        type leafref {
+            path "/network/topologies/topology/links/link/link-id";
+        }
+        description "This type is used for leafs that reference a link instance.";
+        // currently not used
+    }
+    
+    typedef network-element-ref {
+        type leafref {
+            path "/network/network-elements/network-element/element-id";
+        }
+    }
+
+
+    typedef element-id {
+        type string;
+    }
+    
+    container network {
+        container topologies {
+            list topology {
+                description "
+                    This is the model of abstract topology which contains only Network
+                    Nodes and Network Links. Each topology MUST be identified by
+                    unique topology-id for reason that the store could contain many
+                    topologies.
+                ";
+                key "topology-id";
+                leaf topology-id {
+                    type topology-id; 
+                    description "
+                        It is presumed that datastore will contain many topologies. To
+                        distinguish between topologies it is vital to have UNIQUE
+                        topology identifier.
+                    ";
+                }
+
+                container types {
+                    description "
+                        The container for definition of topology types.
+                        The augmenting modules should add empty optional leaf 
+                        to this container to signalize topology type.
+                    ";
+                }
+
+                container nodes {
+                    list node {
+                        description "The list of network nodes defined for topology.";
+
+                        key "node-id";
+                        leaf node-id {
+                            type node-id;
+                            description "The Topology identifier of network-node.";
+                        }
+
+                        leaf supporting-ne {
+                            type network-element-ref;
+                        }
+                        
+                        container termination-points {
+                            list termination-point {
+                                key "tp-id";
+                                leaf tp-id {
+                                    type tp-id;
+                                }
+                            }
+                        }
+                    }
+                }
+        
+                container links {
+                    list link {
+                        description "
+                            The Network Link which is defined by Local (Source) and
+                            Remote (Destination) Network Nodes. Every link MUST be
+                            defined either by identifier and his local and remote
+                            Network Nodes (in real applications it is common that many
+                            links are originated from one node and end up in same
+                            remote node). To ensure that we would always know to
+                            distinguish between links, every link SHOULD have
+                            identifier.
+                        ";
+                        key "link-id";
+        
+                        leaf link-id {
+                            type link-id;
+                        }
+                        container source { 
+                            leaf source-node {
+                                type node-ref;
+                                description "Source node identifier.";
+                            }
+                            leaf source-tp {
+                                type tp-ref;
+                            }
+                        }
+                        container destination { 
+                            leaf dest-node {
+                                type node-ref;
+                                description "Destination node identifier.";
+                            }
+                            leaf dest-tp {
+                                type tp-ref;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        container network-elements {
+            config true;
+            list network-element {
+                key "element-id";
+                leaf element-id {
+                    type element-id;
+                }
+            }
+        }
+    }
+}
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/generateXml.groovy b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/generateXml.groovy
new file mode 100755 (executable)
index 0000000..a778137
--- /dev/null
@@ -0,0 +1,110 @@
+//import groovy.xml.StreamingMarkupBuilder
+import groovy.xml.MarkupBuilder
+import groovy.xml.XmlUtil
+
+class Counter {
+    def counter = 0
+    def get() {
+        return get(true)
+    }
+    def get(isInc) {
+        if (isInc) {
+            counter++
+        }
+        return String.format('%02d', counter)
+    }
+}
+
+
+cnt = new Counter()
+def writer = new StringWriter()
+xmlDoc = new MarkupBuilder(writer)
+xmlDoc.setDoubleQuotes(true)
+xmlDoc.getMkp().xmlDeclaration(version:'1.0', encoding: 'UTF-8')
+
+//def data = {
+//  mkp.xmlDeclaration()
+//  network(xmlns: 'urn:opendaylight:controller:network') {
+dataFile = new File(args[0])
+evaluate(dataFile)
+// xmlDoc.network(xmlns: 'urn:opendaylight:controller:network') {
+    // topologies {
+      // topology {
+        // 'topology-id'('topId_'+cnt.get())
+        // types()
+        // nodes {
+          // node {
+            // 'node-id'('nodeId_'+cnt.get())
+            // 'supporting-ne'('networkId_'+cnt.get())
+            // 'termination-points' {
+              // 'termination-point' {
+                // 'tp-id'('tpId_'+cnt.get())
+              // }
+            // }
+          // }
+          // node {
+            // 'node-id'('nodeId_'+cnt.get())
+            // 'supporting-ne'('networkId_'+cnt.get())
+            // 'termination-points' {
+              // 'termination-point' {
+                // 'tp-id'('tpId_'+cnt.get())
+              // }
+            // }
+          // }
+          // node {
+            // 'node-id'('nodeId_'+cnt.get())
+            // 'supporting-ne'('networkId_'+cnt.get())
+            // 'termination-points' {
+              // 'termination-point' {
+                // 'tp-id'('tpId_'+cnt.get())
+              // }
+              // 'termination-point' {
+                // 'tp-id'('tpId_'+cnt.get())
+              // }
+            // }
+          // }
+        // }
+        // links {
+          // link {
+            // 'link-id'('linkId_'+cnt.get())
+            // source {
+              // 'source-node'('nodeId_'+cnt.get())
+              // 'source-tp'('tpId_'+cnt.get(false))
+            // }
+            // destination {
+              // 'dest-node'('nodeId_'+cnt.get())
+              // 'dest-tp'('tpId_'+cnt.get(false))
+            // }
+          // }
+          // link {
+            // 'link-id'('linkId_'+cnt.get())
+            // source {
+              // 'source-node'('nodeId_'+cnt.get())
+              // 'source-tp'('tpId_'+cnt.get(false))
+            // }
+            // destination {
+              // 'dest-node'('nodeId_'+cnt.get())
+              // 'dest-tp'('tpId_'+cnt.get(false))
+            // }
+          // }
+        // }
+      // }
+    // }
+    // 'network-elements' {
+      // 'network-element' {
+        // 'element-id'('ntElementId_'+cnt.get())
+      // }
+      // 'network-element' {
+        // 'element-id'('ntElementId_'+cnt.get())
+      // }
+    // }
+  // }
+
+//}
+
+
+// def xmlDoc = new StreamingMarkupBuilder()
+// xmlDoc.encoding = 'UTF'
+//println XmlUtil.serialize(xmlDoc.bind(data))
+
+println writer
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.xsd b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.xsd
new file mode 100644 (file)
index 0000000..3da8ec7
--- /dev/null
@@ -0,0 +1,399 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:yin="urn:ietf:params:xml:schema:yang:yin:1"
+           targetNamespace="urn:ietf:params:xml:ns:yang:ietf-inet-types"
+           xmlns="urn:ietf:params:xml:ns:yang:ietf-inet-types"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           version="2010-09-24"
+           xml:lang="en"
+          xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types">
+
+  <xs:annotation>
+    <xs:documentation>
+      This schema was generated from the YANG module ietf-inet-types
+      by pyang version 1.2.
+
+      The schema describes an instance document consisting
+      of the entire configuration data store, operational
+      data, rpc operations, and notifications.
+      This schema can thus NOT be used as-is to
+      validate NETCONF PDUs.
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+      This module contains a collection of generally useful derived
+      YANG data types for Internet addresses and related things.
+
+      Copyright (c) 2010 IETF Trust and the persons identified as
+      authors of the code.  All rights reserved.
+
+      Redistribution and use in source and binary forms, with or without
+      modification, is permitted pursuant to, and subject to the license
+      terms contained in, the Simplified BSD License set forth in Section
+      4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+      (http://trustee.ietf.org/license-info).
+
+      This version of this YANG module is part of RFC 6021; see
+      the RFC itself for full legal notices.
+    </xs:documentation>
+  </xs:annotation>
+
+  <!-- YANG typedefs -->
+  <xs:simpleType name="ip-version">
+    <xs:annotation>
+      <xs:documentation>
+        This value represents the version of the IP protocol.
+
+        In the value set and its semantics, this type is equivalent
+        to the InetVersion textual convention of the SMIv2.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="unknown"/>
+      <xs:enumeration value="ipv4"/>
+      <xs:enumeration value="ipv6"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="dscp">
+    <xs:annotation>
+      <xs:documentation>
+        The dscp type represents a Differentiated Services Code-Point
+        that may be used for marking packets in a traffic stream.
+
+        In the value set and its semantics, this type is equivalent
+        to the Dscp textual convention of the SMIv2.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:unsignedByte">
+      <xs:minInclusive value="0"/>
+      <xs:maxInclusive value="63"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="ipv6-flow-label">
+    <xs:annotation>
+      <xs:documentation>
+        The flow-label type represents flow identifier or Flow Label
+        in an IPv6 packet header that may be used to discriminate
+        traffic flows.
+
+        In the value set and its semantics, this type is equivalent
+        to the IPv6FlowLabel textual convention of the SMIv2.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:unsignedInt">
+      <xs:minInclusive value="0"/>
+      <xs:maxInclusive value="1048575"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="port-number">
+    <xs:annotation>
+      <xs:documentation>
+        The port-number type represents a 16-bit port number of an
+        Internet transport layer protocol such as UDP, TCP, DCCP, or
+        SCTP.  Port numbers are assigned by IANA.  A current list of
+        all assignments is available from &lt;http://www.iana.org/&gt;.
+
+        Note that the port number value zero is reserved by IANA.  In
+        situations where the value zero does not make sense, it can
+        be excluded by subtyping the port-number type.
+
+        In the value set and its semantics, this type is equivalent
+        to the InetPortNumber textual convention of the SMIv2.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:unsignedShort">
+      <xs:minInclusive value="0"/>
+      <xs:maxInclusive value="65535"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="as-number">
+    <xs:annotation>
+      <xs:documentation>
+        The as-number type represents autonomous system numbers
+        which identify an Autonomous System (AS).  An AS is a set
+        of routers under a single technical administration, using
+        an interior gateway protocol and common metrics to route
+        packets within the AS, and using an exterior gateway
+        protocol to route packets to other ASs'.  IANA maintains
+        the AS number space and has delegated large parts to the
+        regional registries.
+
+        Autonomous system numbers were originally limited to 16
+        bits.  BGP extensions have enlarged the autonomous system
+        number space to 32 bits.  This type therefore uses an uint32
+        base type without a range restriction in order to support
+        a larger autonomous system number space.
+
+        In the value set and its semantics, this type is equivalent
+        to the InetAutonomousSystemNumber textual convention of
+        the SMIv2.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:unsignedInt">
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="ip-address">
+    <xs:annotation>
+      <xs:documentation>
+        The ip-address type represents an IP address and is IP
+        version neutral.  The format of the textual representations
+        implies the IP version.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:union>
+      <xs:simpleType>
+        <xs:restriction base="ipv4-address">
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction base="ipv6-address">
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:union>
+  </xs:simpleType>
+  <xs:simpleType name="ipv4-address">
+    <xs:annotation>
+      <xs:documentation>
+        The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:string">
+    <xs:pattern value="(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\p{N}\p{L}]+)?"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="ipv6-address">
+    <xs:annotation>
+      <xs:documentation>
+        The ipv6-address type represents an IPv6 address in full,
+        mixed, shortened, and shortened-mixed notation.  The IPv6
+        address may include a zone index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format of IPv6 addresses uses the compressed
+        format described in RFC 4291, Section 2.2, item 2 with the
+        following additional rules: the :: substitution must be
+        applied to the longest sequence of all-zero 16-bit chunks
+        in an IPv6 address.  If there is a tie, the first sequence
+        of all-zero 16-bit chunks is replaced by ::.  Single
+        all-zero 16-bit chunks are not compressed.  The canonical
+        format uses lowercase characters and leading zeros are
+        not allowed.  The canonical format for the zone index is
+        the numerical format as described in RFC 4007, Section
+        11.2.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:string">
+    <xs:pattern value="(((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\p{N}\p{L}]+)?)|((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(%.+)?)"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="ip-prefix">
+    <xs:annotation>
+      <xs:documentation>
+        The ip-prefix type represents an IP prefix and is IP
+        version neutral.  The format of the textual representations
+        implies the IP version.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:union>
+      <xs:simpleType>
+        <xs:restriction base="ipv4-prefix">
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction base="ipv6-prefix">
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:union>
+  </xs:simpleType>
+  <xs:simpleType name="ipv4-prefix">
+    <xs:annotation>
+      <xs:documentation>
+        The ipv4-prefix type represents an IPv4 address prefix.
+        The prefix length is given by the number following the
+        slash character and must be less than or equal to 32.
+
+        A prefix length value of n corresponds to an IP address
+        mask that has n contiguous 1-bits from the most
+        significant bit (MSB) and all other bits set to 0.
+
+        The canonical format of an IPv4 prefix has all bits of
+        the IPv4 address set to zero that are not part of the
+        IPv4 prefix.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:string">
+    <xs:pattern value="(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="ipv6-prefix">
+    <xs:annotation>
+      <xs:documentation>
+        The ipv6-prefix type represents an IPv6 address prefix.
+        The prefix length is given by the number following the
+        slash character and must be less than or equal 128.
+
+        A prefix length value of n corresponds to an IP address
+        mask that has n contiguous 1-bits from the most
+        significant bit (MSB) and all other bits set to 0.
+
+        The IPv6 address should have all bits that do not belong
+        to the prefix set to zero.
+
+        The canonical format of an IPv6 prefix has all bits of
+        the IPv6 address set to zero that are not part of the
+        IPv6 prefix.  Furthermore, IPv6 address is represented
+        in the compressed format described in RFC 4291, Section
+        2.2, item 2 with the following additional rules: the ::
+        substitution must be applied to the longest sequence of
+        all-zero 16-bit chunks in an IPv6 address.  If there is
+        a tie, the first sequence of all-zero 16-bit chunks is
+        replaced by ::.  Single all-zero 16-bit chunks are not
+        compressed.  The canonical format uses lowercase
+        characters and leading zeros are not allowed.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:string">
+    <xs:pattern value="(((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8]))))|((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(/.+))"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="domain-name">
+    <xs:annotation>
+      <xs:documentation>
+        The domain-name type represents a DNS domain name.  The
+        name SHOULD be fully qualified whenever possible.
+
+        Internet domain names are only loosely specified.  Section
+        3.5 of RFC 1034 recommends a syntax (modified in Section
+        2.1 of RFC 1123).  The pattern above is intended to allow
+        for current practice in domain name use, and some possible
+        future expansion.  It is designed to hold various types of
+        domain names, including names used for A or AAAA records
+        (host names) and other records, such as SRV records.  Note
+        that Internet host names have a stricter syntax (described
+        in RFC 952) than the DNS recommendations in RFCs 1034 and
+        1123, and that systems that want to store host names in
+        schema nodes using the domain-name type are recommended to
+        adhere to this stricter standard to ensure interoperability.
+
+        The encoding of DNS names in the DNS protocol is limited
+        to 255 characters.  Since the encoding consists of labels
+        prefixed by a length bytes and there is a trailing NULL
+        byte, only 253 characters can appear in the textual dotted
+        notation.
+
+        The description clause of schema nodes using the domain-name
+        type MUST describe when and how these names are resolved to
+        IP addresses.  Note that the resolution of a domain-name value
+        may require to query multiple DNS records (e.g., A for IPv4
+        and AAAA for IPv6).  The order of the resolution process and
+        which DNS record takes precedence can either be defined
+        explicitely or it may depend on the configuration of the
+        resolver.
+
+        Domain-name values use the US-ASCII encoding.  Their canonical
+        format uses lowercase US-ASCII characters.  Internationalized
+        domain names MUST be encoded in punycode as described in RFC
+        3492
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="t0">
+      <xs:minLength value="1"/>
+      <xs:maxLength value="253"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="host">
+    <xs:annotation>
+      <xs:documentation>
+        The host type represents either an IP address or a DNS
+        domain name.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:union>
+      <xs:simpleType>
+        <xs:restriction base="ip-address">
+        </xs:restriction>
+      </xs:simpleType>
+      <xs:simpleType>
+        <xs:restriction base="domain-name">
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:union>
+  </xs:simpleType>
+  <xs:simpleType name="uri">
+    <xs:annotation>
+      <xs:documentation>
+        The uri type represents a Uniform Resource Identifier
+        (URI) as defined by STD 66.
+
+        Objects using the uri type MUST be in US-ASCII encoding,
+        and MUST be normalized as described by RFC 3986 Sections
+        6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+        percent-encoding is removed, and all case-insensitive
+        characters are set to lowercase except for hexadecimal
+        digits, which are normalized to uppercase as described in
+        Section 6.2.2.1.
+
+        The purpose of this normalization is to help provide
+        unique URIs.  Note that this normalization is not
+        sufficient to provide uniqueness.  Two URIs that are
+        textually distinct after this normalization may still be
+        equivalent.
+
+        Objects using the uri type may restrict the schemes that
+        they permit.  For example, 'data:' and 'urn:' schemes
+        might not be appropriate.
+
+        A zero-length URI is not a valid URI.  This can be used to
+        express 'URI absent' where required.
+
+        In the value set and its semantics, this type is equivalent
+        to the Uri SMIv2 textual convention defined in RFC 5017.
+      </xs:documentation>
+    </xs:annotation>
+
+    <xs:restriction base="xs:string">
+    </xs:restriction>
+  </xs:simpleType>
+
+
+  <!-- locally generated simpleType helpers -->
+
+  <xs:simpleType name="t0">
+    <xs:restriction base="xs:string">
+    <xs:pattern value="((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)|\."/>
+    </xs:restriction>
+  </xs:simpleType>
+
+</xs:schema>
diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.yang b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.yang
new file mode 100755 (executable)
index 0000000..de20feb
--- /dev/null
@@ -0,0 +1,418 @@
+ module ietf-inet-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+   prefix "inet";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types for Internet addresses and related things.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef ip-version {
+     type enumeration {
+       enum unknown {
+         value "0";
+         description
+          "An unknown or unspecified version of the Internet protocol.";
+       }
+       enum ipv4 {
+         value "1";
+         description
+          "The IPv4 protocol as defined in RFC 791.";
+       }
+       enum ipv6 {
+         value "2";
+         description
+          "The IPv6 protocol as defined in RFC 2460.";
+       }
+     }
+     description
+      "This value represents the version of the IP protocol.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetVersion textual convention of the SMIv2.";
+     reference
+      "RFC  791: Internet Protocol
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   typedef dscp {
+     type uint8 {
+       range "0..63";
+     }
+     description
+      "The dscp type represents a Differentiated Services Code-Point
+       that may be used for marking packets in a traffic stream.
+
+       In the value set and its semantics, this type is equivalent
+       to the Dscp textual convention of the SMIv2.";
+     reference
+      "RFC 3289: Management Information Base for the Differentiated
+                 Services Architecture
+       RFC 2474: Definition of the Differentiated Services Field
+                 (DS Field) in the IPv4 and IPv6 Headers
+       RFC 2780: IANA Allocation Guidelines For Values In
+                 the Internet Protocol and Related Headers";
+   }
+
+   typedef ipv6-flow-label {
+     type uint32 {
+       range "0..1048575";
+     }
+     description
+      "The flow-label type represents flow identifier or Flow Label
+       in an IPv6 packet header that may be used to discriminate
+       traffic flows.
+
+       In the value set and its semantics, this type is equivalent
+       to the IPv6FlowLabel textual convention of the SMIv2.";
+     reference
+      "RFC 3595: Textual Conventions for IPv6 Flow Label
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+   }
+
+   typedef port-number {
+     type uint16 {
+       range "0..65535";
+     }
+     description
+      "The port-number type represents a 16-bit port number of an
+       Internet transport layer protocol such as UDP, TCP, DCCP, or
+       SCTP.  Port numbers are assigned by IANA.  A current list of
+       all assignments is available from <http://www.iana.org/>.
+
+       Note that the port number value zero is reserved by IANA.  In
+       situations where the value zero does not make sense, it can
+       be excluded by subtyping the port-number type.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetPortNumber textual convention of the SMIv2.";
+     reference
+      "RFC  768: User Datagram Protocol
+       RFC  793: Transmission Control Protocol
+       RFC 4960: Stream Control Transmission Protocol
+       RFC 4340: Datagram Congestion Control Protocol (DCCP)
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of autonomous system related types ***/
+
+   typedef as-number {
+     type uint32;
+     description
+      "The as-number type represents autonomous system numbers
+       which identify an Autonomous System (AS).  An AS is a set
+       of routers under a single technical administration, using
+       an interior gateway protocol and common metrics to route
+       packets within the AS, and using an exterior gateway
+       protocol to route packets to other ASs'.  IANA maintains
+       the AS number space and has delegated large parts to the
+       regional registries.
+
+       Autonomous system numbers were originally limited to 16
+       bits.  BGP extensions have enlarged the autonomous system
+       number space to 32 bits.  This type therefore uses an uint32
+       base type without a range restriction in order to support
+       a larger autonomous system number space.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetAutonomousSystemNumber textual convention of
+       the SMIv2.";
+     reference
+      "RFC 1930: Guidelines for creation, selection, and registration
+                 of an Autonomous System (AS)
+       RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+       RFC 4893: BGP Support for Four-octet AS Number Space
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of IP address and hostname related types ***/
+
+   typedef ip-address {
+     type union {
+       type inet:ipv4-address;
+       type inet:ipv6-address;
+     }
+     description
+      "The ip-address type represents an IP address and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+     description
+       "The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format";
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+     description
+      "The ipv6-address type represents an IPv6 address in full,
+       mixed, shortened, and shortened-mixed notation.  The IPv6
+       address may include a zone index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format of IPv6 addresses uses the compressed
+       format described in RFC 4291, Section 2.2, item 2 with the
+       following additional rules: the :: substitution must be
+       applied to the longest sequence of all-zero 16-bit chunks
+       in an IPv6 address.  If there is a tie, the first sequence
+       of all-zero 16-bit chunks is replaced by ::.  Single
+       all-zero 16-bit chunks are not compressed.  The canonical
+       format uses lowercase characters and leading zeros are
+       not allowed.  The canonical format for the zone index is
+       the numerical format as described in RFC 4007, Section
+       11.2.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text Representation";
+   }
+
+   typedef ip-prefix {
+     type union {
+       type inet:ipv4-prefix;
+       type inet:ipv6-prefix;
+     }
+     description
+      "The ip-prefix type represents an IP prefix and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-prefix {
+     type string {
+       pattern
+          '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+        +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+        + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+     }
+     description
+      "The ipv4-prefix type represents an IPv4 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal to 32.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The canonical format of an IPv4 prefix has all bits of
+       the IPv4 address set to zero that are not part of the
+       IPv4 prefix.";
+   }
+
+   typedef ipv6-prefix {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(/.+)';
+     }
+     description
+      "The ipv6-prefix type represents an IPv6 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal 128.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The IPv6 address should have all bits that do not belong
+       to the prefix set to zero.
+
+       The canonical format of an IPv6 prefix has all bits of
+       the IPv6 address set to zero that are not part of the
+       IPv6 prefix.  Furthermore, IPv6 address is represented
+       in the compressed format described in RFC 4291, Section
+       2.2, item 2 with the following additional rules: the ::
+       substitution must be applied to the longest sequence of
+       all-zero 16-bit chunks in an IPv6 address.  If there is
+       a tie, the first sequence of all-zero 16-bit chunks is
+       replaced by ::.  Single all-zero 16-bit chunks are not
+       compressed.  The canonical format uses lowercase
+       characters and leading zeros are not allowed.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+   }
+
+   /*** collection of domain name and URI types ***/
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+     description
+      "The domain-name type represents a DNS domain name.  The
+       name SHOULD be fully qualified whenever possible.
+
+       Internet domain names are only loosely specified.  Section
+       3.5 of RFC 1034 recommends a syntax (modified in Section
+       2.1 of RFC 1123).  The pattern above is intended to allow
+       for current practice in domain name use, and some possible
+       future expansion.  It is designed to hold various types of
+       domain names, including names used for A or AAAA records
+       (host names) and other records, such as SRV records.  Note
+       that Internet host names have a stricter syntax (described
+       in RFC 952) than the DNS recommendations in RFCs 1034 and
+       1123, and that systems that want to store host names in
+       schema nodes using the domain-name type are recommended to
+       adhere to this stricter standard to ensure interoperability.
+
+       The encoding of DNS names in the DNS protocol is limited
+       to 255 characters.  Since the encoding consists of labels
+       prefixed by a length bytes and there is a trailing NULL
+       byte, only 253 characters can appear in the textual dotted
+       notation.
+
+       The description clause of schema nodes using the domain-name
+       type MUST describe when and how these names are resolved to
+       IP addresses.  Note that the resolution of a domain-name value
+       may require to query multiple DNS records (e.g., A for IPv4
+       and AAAA for IPv6).  The order of the resolution process and
+       which DNS record takes precedence can either be defined
+       explicitely or it may depend on the configuration of the
+       resolver.
+
+       Domain-name values use the US-ASCII encoding.  Their canonical
+       format uses lowercase US-ASCII characters.  Internationalized
+       domain names MUST be encoded in punycode as described in RFC
+       3492";
+     reference
+      "RFC  952: DoD Internet Host Table Specification
+       RFC 1034: Domain Names - Concepts and Facilities
+       RFC 1123: Requirements for Internet Hosts -- Application
+                 and Support
+       RFC 2782: A DNS RR for specifying the location of services
+                 (DNS SRV)
+       RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                 Internationalized Domain Names in Applications
+                 (IDNA)
+       RFC 5891: Internationalizing Domain Names in Applications
+                 (IDNA): Protocol";
+   }
+
+   typedef host {
+     type union {
+       type inet:ip-address;
+       type inet:domain-name;
+     }
+     description
+      "The host type represents either an IP address or a DNS
+       domain name.";
+   }
+
+   typedef uri {
+     type string;
+     description
+      "The uri type represents a Uniform Resource Identifier
+       (URI) as defined by STD 66.
+
+       Objects using the uri type MUST be in US-ASCII encoding,
+       and MUST be normalized as described by RFC 3986 Sections
+       6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+       percent-encoding is removed, and all case-insensitive
+       characters are set to lowercase except for hexadecimal
+       digits, which are normalized to uppercase as described in
+       Section 6.2.2.1.
+
+       The purpose of this normalization is to help provide
+       unique URIs.  Note that this normalization is not
+       sufficient to provide uniqueness.  Two URIs that are
+       textually distinct after this normalization may still be
+       equivalent.
+
+       Objects using the uri type may restrict the schemes that
+       they permit.  For example, 'data:' and 'urn:' schemes
+       might not be appropriate.
+
+       A zero-length URI is not a valid URI.  This can be used to
+       express 'URI absent' where required.
+
+       In the value set and its semantics, this type is equivalent
+       to the Uri SMIv2 textual convention defined in RFC 5017.";
+     reference
+      "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+       RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                 Group: Uniform Resource Identifiers (URIs), URLs,
+                 and Uniform Resource Names (URNs): Clarifications
+                 and Recommendations
+       RFC 5017: MIB Textual Conventions for Uniform Resource
+                 Identifiers (URIs)";
+   }
+
+ }
index 8745dda8ba63112c4e221a17e8aa8260b796c94d..ec224fa0f10e2ddac4aa5ae47530261eacb50f70 100644 (file)
@@ -7,6 +7,8 @@
  */\r
 package org.opendaylight.controller.yang.model.api;\r
 \r
+import java.util.List;\r
+\r
 /**\r
  * Interface describing YANG 'deviation' statement.\r
  * <p>\r
@@ -43,4 +45,9 @@ public interface Deviation {
      */\r
     String getReference();\r
 \r
+    /**\r
+     * @return collection of all unknown nodes defined under this schema node.\r
+     */\r
+    public List<UnknownSchemaNode> getUnknownSchemaNodes();\r
+\r
 }\r
index b9729102c90b3b8d05a15f1380e5567d6663d802..6070c1c6ac563cc230dd7c9ddac921cfb9344911 100644 (file)
@@ -51,7 +51,7 @@ public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
         private List<UnknownSchemaNode> unknownSchemaNodes = Collections
                 .emptyList();
         private Status status = Status.CURRENT;
-        private String units = "";
+        private String units = null;
         private Object defaultValue = null;
         private boolean addedByUses;
 
index 83cb8b1cc9786f42757e1f609dedf724943c0f19..522f45946d98fbdc170db4ec9531d9128df53f97 100644 (file)
@@ -153,6 +153,6 @@ public class SpanConfig implements Serializable {
 
     @Override
     public String toString() {
-        return ("Span Config [nodeId=" + nodeId + " spanPort=" + spanPort + "]");
+        return ("SpanConfig [nodeId=" + nodeId + ", spanPort=" + spanPort + "]");
     }
 }
index e15303581f9ad32be958dd3971cd0cf92dc8d8bd..6a8eea2d0c7e3f75322dbf946bd90d4e190cfed2 100644 (file)
@@ -21,14 +21,14 @@ import org.opendaylight.controller.sal.core.NodeConnector;
  * The class describes subnet information including L3 address, vlan and set of
  * ports associated with the subnet.
  */
-public class Subnet implements Serializable {
+public class Subnet implements Cloneable, Serializable {
     private static final long serialVersionUID = 1L;
     // Key fields
     private InetAddress networkAddress;
     private short subnetMaskLength;
     // Property fields
     private short vlan;
-    private Set<NodeConnector> nodeConnectors;
+    private final Set<NodeConnector> nodeConnectors;
 
     public Subnet(InetAddress ip, short maskLen, short vlan) {
         this.networkAddress = ip;
@@ -43,6 +43,13 @@ public class Subnet implements Serializable {
         nodeConnectors = conf.getSubnetNodeConnectors();
     }
 
+    public Subnet(Subnet subnet) {
+        networkAddress = subnet.networkAddress;
+        subnetMaskLength = subnet.subnetMaskLength;
+        vlan = subnet.vlan;
+        nodeConnectors = new HashSet<NodeConnector>(subnet.nodeConnectors);
+    }
+
     /**
      * Add NodeConnectors to a subnet
      *
@@ -220,7 +227,7 @@ public class Subnet implements Serializable {
     public String toString() {
         return ("Subnet [networkAddress=" + networkAddress.getHostAddress()
                 + "/" + subnetMaskLength
-                + ((vlan == 0) ? "" : (" vlan=" + vlan)) + " "
+                + ((vlan == 0) ? "" : (", vlan=" + vlan)) + ", "
                 + ((isFlatLayer2()) ? "{[*, *]}" : nodeConnectors.toString()) + "]");
     }
 
@@ -246,4 +253,13 @@ public class Subnet implements Serializable {
         }
         return true;
     }
+
+    /**
+     * Implement clonable interface
+     */
+    @Override
+    public Subnet clone() {
+        return new Subnet(this);
+    }
+
 }
index 895f117321a6c61645742e425bcf0ad2d0af6cbd..52b5f5255d3e5c13f088a38c19819c8730fdf266 100644 (file)
@@ -34,7 +34,7 @@ import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
  */
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
-public class SubnetConfig implements Serializable {
+public class SubnetConfig implements Cloneable, Serializable {
     //static fields are by default excluded by Gson parser
     private static final long serialVersionUID = 1L;
     private static final String prettyFields[] = { GUIField.NAME.toString(),
@@ -60,6 +60,12 @@ public class SubnetConfig implements Serializable {
         nodePorts = sp;
     }
 
+    public SubnetConfig(SubnetConfig subnetConfig) {
+        name = subnetConfig.name;
+        subnet = subnetConfig.subnet;
+        nodePorts = new ArrayList<String>(subnetConfig.nodePorts);
+    }
+
     public String getName() {
         return name;
     }
@@ -233,7 +239,16 @@ public class SubnetConfig implements Serializable {
 
     @Override
     public String toString() {
-        return ("Subnet Config [Description=" + name + " Subnet=" + subnet
-                + " NodeConnectors=" + nodePorts + "]");
+        return ("SubnetConfig [Description=" + name + ", Subnet=" + subnet
+                + ", NodeConnectors=" + nodePorts + "]");
+    }
+
+    /**
+     * Implement clonable interface
+     */
+    @Override
+    public SubnetConfig clone() {
+        return new SubnetConfig(this);
     }
+
 }
index 61b2f0a3a8edf0a00a7a783d088b4751e379859a..c595c43e5bc48cf05d5f8b26e38d6289c915a092 100644 (file)
@@ -100,7 +100,7 @@ public class SwitchConfig implements Serializable {
 
     @Override
     public String toString() {
-        return ("Switch Config [Node=" + nodeId + " Description=" + description +
-                " Tier=" + tier + " Mode=" + mode + "]");
+        return ("SwitchConfig [Node=" + nodeId + ", Description=" + description +
+                ", Tier=" + tier + ", Mode=" + mode + "]");
     }
 }
index d32f98650b8b549ce8235fd3c14d22c55205ac56..8c95c46d72abd8e09e068da837288a4d31ad00bd 100644 (file)
@@ -40,6 +40,7 @@ import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
 import org.opendaylight.controller.sal.core.Bandwidth;
 import org.opendaylight.controller.sal.core.Config;
+import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.Description;
 import org.opendaylight.controller.sal.core.MacAddress;
 import org.opendaylight.controller.sal.core.Name;
@@ -95,7 +96,7 @@ CommandProvider {
     private final List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
     private ConcurrentMap<InetAddress, Subnet> subnets; // set of Subnets keyed by the InetAddress
     private ConcurrentMap<String, SubnetConfig> subnetsConfigList;
-    private ConcurrentMap<Integer, SpanConfig> spanConfigList;
+    private ConcurrentMap<SpanConfig, SpanConfig> spanConfigList;
     private ConcurrentMap<String, SwitchConfig> nodeConfigList; // manually configured parameters for the node like name and tier
     private ConcurrentMap<Long, String> configSaveEvent;
     private ConcurrentMap<Node, Map<String, Property>> nodeProps; // properties are maintained in global container only
@@ -114,6 +115,7 @@ CommandProvider {
     private IClusterContainerServices clusterContainerService = null;
     private String containerName = null;
     private boolean isDefaultContainer = true;
+    private static final int REPLACE_RETRY = 1;
 
     public enum ReasonCode {
         SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
@@ -206,6 +208,7 @@ CommandProvider {
     @SuppressWarnings("deprecation")
     private void allocateCaches() {
         if (this.clusterContainerService == null) {
+            this.nonClusterObjectCreate();
             log.warn("un-initialized clusterContainerService, can't create cache");
             return;
         }
@@ -251,7 +254,7 @@ CommandProvider {
             log.error("\nFailed to get cache for subnetsConfigList");
         }
 
-        spanConfigList = (ConcurrentMap<Integer, SpanConfig>) clusterContainerService
+        spanConfigList = (ConcurrentMap<SpanConfig, SpanConfig>) clusterContainerService
                 .getCache("switchmanager.spanConfigList");
         if (spanConfigList == null) {
             log.error("\nFailed to get cache for spanConfigList");
@@ -294,9 +297,9 @@ CommandProvider {
         }
     }
 
-    void nonClusterObjectCreate() {
+    private void nonClusterObjectCreate() {
         subnetsConfigList = new ConcurrentHashMap<String, SubnetConfig>();
-        spanConfigList = new ConcurrentHashMap<Integer, SpanConfig>();
+        spanConfigList = new ConcurrentHashMap<SpanConfig, SpanConfig>();
         nodeConfigList = new ConcurrentHashMap<String, SwitchConfig>();
         subnets = new ConcurrentHashMap<InetAddress, Subnet>();
         configSaveEvent = new ConcurrentHashMap<Long, String>();
@@ -305,26 +308,6 @@ CommandProvider {
         nodeConnectorNames = new ConcurrentHashMap<Node, Map<String, NodeConnector>>();
     }
 
-    @SuppressWarnings("deprecation")
-    private void destroyCaches(String container) {
-        if (this.clusterContainerService == null) {
-            log.info("un-initialized clusterContainerService, can't create cache");
-            return;
-        }
-
-        clusterContainerService.destroyCache("switchmanager.subnetsConfigList");
-        clusterContainerService.destroyCache("switchmanager.spanConfigList");
-        clusterContainerService.destroyCache("switchmanager.nodeConfigList");
-        clusterContainerService.destroyCache("switchmanager.subnets");
-        clusterContainerService.destroyCache("switchmanager.configSaveEvent");
-        clusterContainerService.destroyCache("switchmanager.nodeProps");
-        clusterContainerService
-        .destroyCache("switchmanager.nodeConnectorProps");
-        clusterContainerService
-        .destroyCache("switchmanager.nodeConnectorNames");
-        nonClusterObjectCreate();
-    }
-
     @Override
     public List<SubnetConfig> getSubnetsConfigList() {
         return new ArrayList<SubnetConfig>(subnetsConfigList.values());
@@ -390,19 +373,26 @@ CommandProvider {
         return swList;
     }
 
-    private void updateConfig(SubnetConfig conf, boolean add) {
+    private Status updateConfig(SubnetConfig conf, boolean add) {
         if (add) {
-            subnetsConfigList.put(conf.getName(), conf);
+            if(subnetsConfigList.putIfAbsent(conf.getName(), conf) != null) {
+                String msg = "Cluster conflict: Subnet with name " + conf.getName() + "already exists.";
+                return new Status(StatusCode.CONFLICT, msg);
+            }
         } else {
             subnetsConfigList.remove(conf.getName());
         }
+        return new Status(StatusCode.SUCCESS);
     }
 
-    private void updateDatabase(SubnetConfig conf, boolean add) {
-        Subnet subnet = subnets.get(conf.getIPnum());
+    private Status updateDatabase(SubnetConfig conf, boolean add) {
         if (add) {
-            if (subnet == null) {
+            Subnet subnetCurr = subnets.get(conf.getIPnum());
+            Subnet subnet;
+            if (subnetCurr == null) {
                 subnet = new Subnet(conf);
+            } else {
+                subnet = subnetCurr.clone();
             }
             // In case of API3 call we may receive the ports along with the
             // subnet creation
@@ -410,29 +400,38 @@ CommandProvider {
                 Set<NodeConnector> sp = conf.getSubnetNodeConnectors();
                 subnet.addNodeConnectors(sp);
             }
-            subnets.put(conf.getIPnum(), subnet);
-        } else { // This is the deletion of the whole subnet
-            if (subnet == null) {
-                return;
+            boolean result = false;
+            if(subnetCurr == null) {
+                if(subnets.putIfAbsent(conf.getIPnum(), subnet) == null) {
+                    result = true;
+                }
+            } else {
+                result = subnets.replace(conf.getIPnum(), subnetCurr, subnet);
+            }
+            if(!result) {
+                String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPnum();
+                return new Status(StatusCode.CONFLICT, msg);
             }
+        } else { // This is the deletion of the whole subnet
             subnets.remove(conf.getIPnum());
         }
+        return new Status(StatusCode.SUCCESS);
     }
 
     private Status semanticCheck(SubnetConfig conf) {
         Subnet newSubnet = new Subnet(conf);
         Set<InetAddress> IPs = subnets.keySet();
         if (IPs == null) {
-            return new Status(StatusCode.SUCCESS, null);
+            return new Status(StatusCode.SUCCESS);
         }
         for (InetAddress i : IPs) {
             Subnet existingSubnet = subnets.get(i);
             if ((existingSubnet != null)
                     && !existingSubnet.isMutualExclusive(newSubnet)) {
-                return new Status(StatusCode.CONFLICT, null);
+                return new Status(StatusCode.CONFLICT);
             }
         }
-        return new Status(StatusCode.SUCCESS, null);
+        return new Status(StatusCode.SUCCESS);
     }
 
     private Status addRemoveSubnet(SubnetConfig conf, boolean add) {
@@ -455,13 +454,19 @@ CommandProvider {
                 return rc;
             }
         }
-        // Update Configuration
-        updateConfig(conf, add);
 
         // Update Database
-        updateDatabase(conf, add);
+        Status rc = updateDatabase(conf, add);
+
+        if (rc.isSuccess()) {
+            // Update Configuration
+            rc = updateConfig(conf, add);
+            if(!rc.isSuccess()) {
+                updateDatabase(conf, (!add));
+            }
+        }
 
-        return new Status(StatusCode.SUCCESS, null);
+        return rc;
     }
 
     /**
@@ -488,42 +493,77 @@ CommandProvider {
 
     @Override
     public Status addPortsToSubnet(String name, String switchPorts) {
-        // Update Configuration
-        SubnetConfig conf = subnetsConfigList.get(name);
-        if (conf == null) {
+        SubnetConfig confCurr = subnetsConfigList.get(name);
+        if (confCurr == null) {
             return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
         }
-        if (!conf.isValidSwitchPort(switchPorts)) {
+        if (!confCurr.isValidSwitchPort(switchPorts)) {
             return new Status(StatusCode.BADREQUEST, "Invalid switchports");
         }
 
-        conf.addNodeConnectors(switchPorts);
-        subnetsConfigList.put(name, conf);
+        Subnet subCurr = subnets.get(confCurr.getIPnum());
+        if (subCurr == null) {
+            log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
+            return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
+        }
 
         // Update Database
-        Subnet sub = subnets.get(conf.getIPnum());
-        Set<NodeConnector> sp = conf.getNodeConnectors(switchPorts);
+        Subnet sub = subCurr.clone();
+        Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
         sub.addNodeConnectors(sp);
-        subnets.put(conf.getIPnum(), sub);
-        return new Status(StatusCode.SUCCESS, null);
+        boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
+        if (!subnetsReplace) {
+            String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
+            return new Status(StatusCode.CONFLICT, msg);
+        }
+
+        // Update Configuration
+        SubnetConfig conf = confCurr.clone();
+        conf.addNodeConnectors(switchPorts);
+        boolean result = subnetsConfigList.replace(name, confCurr, conf);
+        if (!result) {
+            // TODO: recovery using Transactionality
+            String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
+            return new Status(StatusCode.CONFLICT, msg);
+        }
+
+        return new Status(StatusCode.SUCCESS);
     }
 
     @Override
     public Status removePortsFromSubnet(String name, String switchPorts) {
-        // Update Configuration
-        SubnetConfig conf = subnetsConfigList.get(name);
-        if (conf == null) {
+        SubnetConfig confCurr = subnetsConfigList.get(name);
+        if (confCurr == null) {
+            return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
+        }
+
+        Subnet subCurr = subnets.get(confCurr.getIPnum());
+        if (subCurr == null) {
+            log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
             return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
         }
-        conf.removeNodeConnectors(switchPorts);
-        subnetsConfigList.put(name, conf);
 
         // Update Database
-        Subnet sub = subnets.get(conf.getIPnum());
-        Set<NodeConnector> sp = conf.getNodeConnectors(switchPorts);
+        Subnet sub = subCurr.clone();
+        Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
         sub.deleteNodeConnectors(sp);
-        subnets.put(conf.getIPnum(), sub);
-        return new Status(StatusCode.SUCCESS, null);
+        boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
+        if (!subnetsReplace) {
+            String msg = "Cluster conflict: Conflict while removing ports from the subnet " + name;
+            return new Status(StatusCode.CONFLICT, msg);
+        }
+
+        // Update Configuration
+        SubnetConfig conf = confCurr.clone();
+        conf.removeNodeConnectors(switchPorts);
+        boolean result = subnetsConfigList.replace(name, confCurr, conf);
+        if (!result) {
+            // TODO: recovery using Transactionality
+            String msg = "Cluster conflict: Conflict while removing ports from " + conf;
+            return new Status(StatusCode.CONFLICT, msg);
+        }
+
+        return new Status(StatusCode.SUCCESS);
     }
 
     public String getContainerName() {
@@ -606,31 +646,51 @@ CommandProvider {
             return;
         }
 
+        SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId());
+        if (sc == null) {
+            if (nodeConfigList.putIfAbsent(cfgObject.getNodeId(), cfgObject) != null) {
+                return;
+            }
+        } else {
+            if (!nodeConfigList.replace(cfgObject.getNodeId(), sc, cfgObject)) {
+                return;
+            }
+        }
+
         boolean modeChange = false;
 
-        SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId());
         if ((sc == null) || !cfgObject.getMode().equals(sc.getMode())) {
             modeChange = true;
         }
 
-        nodeConfigList.put(cfgObject.getNodeId(), cfgObject);
         try {
             String nodeId = cfgObject.getNodeId();
             Node node = Node.fromString(nodeId);
-            Map<String, Property> propMap;
-            if (nodeProps.get(node) != null) {
-                propMap = nodeProps.get(node);
-            } else {
-                propMap = new HashMap<String, Property>();
+            Map<String, Property> propMapCurr = nodeProps.get(node);
+            Map<String, Property> propMap = new HashMap<String, Property>();
+            if (propMapCurr != null) {
+                for (String s : propMapCurr.keySet()) {
+                    propMap.put(s, propMapCurr.get(s).clone());
+                }
             }
             Property desc = new Description(cfgObject.getNodeDescription());
             propMap.put(desc.getName(), desc);
             Property tier = new Tier(Integer.parseInt(cfgObject.getTier()));
             propMap.put(tier.getName(), tier);
-            addNodeProps(node, propMap);
 
-            log.info("Set Node {}'s Mode to {}", nodeId,
-                    cfgObject.getMode());
+            if (propMapCurr == null) {
+                if (nodeProps.putIfAbsent(node, propMap) != null) {
+                    // TODO rollback using Transactionality
+                    return;
+                }
+            } else {
+                if (!nodeProps.replace(node, propMapCurr, propMap)) {
+                    // TODO rollback using Transactionality
+                    return;
+                }
+            }
+
+            log.info("Set Node {}'s Mode to {}", nodeId, cfgObject.getMode());
 
             if (modeChange) {
                 notifyModeChange(node, cfgObject.isProactive());
@@ -653,7 +713,7 @@ CommandProvider {
 
         retS = objWriter.write(new ConcurrentHashMap<String, SubnetConfig>(
                 subnetsConfigList), subnetFileName);
-        retP = objWriter.write(new ConcurrentHashMap<Integer, SpanConfig>(
+        retP = objWriter.write(new ConcurrentHashMap<SpanConfig, SpanConfig>(
                 spanConfigList), spanFileName);
         retS = objWriter.write(new ConcurrentHashMap<String, SwitchConfig>(
                 nodeConfigList), switchConfigFileName);
@@ -684,17 +744,17 @@ CommandProvider {
         }
 
         // Presence check
-        if (spanConfigList.containsKey(conf.hashCode())) {
+        if (spanConfigList.containsKey(conf)) {
             return new Status(StatusCode.CONFLICT, "Same span config exists");
         }
 
-        // Update database and notify clients
-        addSpanPorts(conf.getNode(), conf.getPortArrayList());
-
         // Update configuration
-        spanConfigList.put(conf.hashCode(), conf);
+        if (spanConfigList.putIfAbsent(conf, conf) == null) {
+            // Update database and notify clients
+            addSpanPorts(conf.getNode(), conf.getPortArrayList());
+        }
 
-        return new Status(StatusCode.SUCCESS, null);
+        return new Status(StatusCode.SUCCESS);
     }
 
     @Override
@@ -702,9 +762,9 @@ CommandProvider {
         removeSpanPorts(conf.getNode(), conf.getPortArrayList());
 
         // Update configuration
-        spanConfigList.remove(conf.hashCode());
+        spanConfigList.remove(conf);
 
-        return new Status(StatusCode.SUCCESS, null);
+        return new Status(StatusCode.SUCCESS);
     }
 
     @Override
@@ -739,11 +799,12 @@ CommandProvider {
             return;
         }
 
-        Map<String, Property> propMap;
-        if (nodeProps.get(node) != null) {
-            propMap = nodeProps.get(node);
-        } else {
-            propMap = new HashMap<String, Property>();
+        Map<String, Property> propMapCurr = nodeProps.get(node);
+        Map<String, Property> propMap = new HashMap<String, Property>();
+        if (propMapCurr != null) {
+            for (String s : propMapCurr.keySet()) {
+                propMap.put(s, propMapCurr.get(s).clone());
+            }
         }
 
         // copy node properties from plugin
@@ -759,8 +820,7 @@ CommandProvider {
             String nodeId = node.toString();
             for (SwitchConfig conf : nodeConfigList.values()) {
                 if (conf.getNodeId().equals(nodeId)) {
-                    Property description = new Description(
-                            conf.getNodeDescription());
+                    Property description = new Description(conf.getNodeDescription());
                     propMap.put(description.getName(), description);
                     Property tier = new Tier(Integer.parseInt(conf.getTier()));
                     propMap.put(tier.getName(), tier);
@@ -769,7 +829,22 @@ CommandProvider {
                 }
             }
         }
-        addNodeProps(node, propMap);
+
+        boolean result = false;
+        if (propMapCurr == null) {
+            if (nodeProps.putIfAbsent(node, propMap) == null) {
+                result = true;
+            }
+        } else {
+            result = nodeProps.replace(node, propMapCurr, propMap);
+        }
+
+        if (!result) {
+            log.debug(
+                    "Cluster conflict: Conflict while adding the node properties. Node: {}  Properties: {}",
+                    node.getID(), props);
+            addNodeProps(node, propMap);
+        }
 
         // check if span ports are configed
         addSpanPorts(node);
@@ -804,11 +879,12 @@ CommandProvider {
             return;
         }
 
-        Map<String, Property> propMap;
-        if (nodeProps.get(node) != null) {
-            propMap = nodeProps.get(node);
-        } else {
-            propMap = new HashMap<String, Property>();
+        Map<String, Property> propMapCurr = nodeProps.get(node);
+        Map<String, Property> propMap = new HashMap<String, Property>();
+        if (propMapCurr != null) {
+            for (String s : propMapCurr.keySet()) {
+                propMap.put(s, propMapCurr.get(s).clone());
+            }
         }
 
         // copy node properties from plugin
@@ -817,7 +893,20 @@ CommandProvider {
                 propMap.put(prop.getName(), prop);
             }
         }
-        addNodeProps(node, propMap);
+
+        if (propMapCurr == null) {
+            if (nodeProps.putIfAbsent(node, propMap) != null) {
+                log.debug("Cluster conflict: Conflict while updating the node. Node: {}  Properties: {}",
+                        node.getID(), props);
+                addNodeProps(node, propMap);
+            }
+        } else {
+            if (!nodeProps.replace(node, propMapCurr, propMap)) {
+                log.debug("Cluster conflict: Conflict while updating the node. Node: {}  Properties: {}",
+                        node.getID(), props);
+                addNodeProps(node, propMap);
+            }
+        }
 
         /* notify node listeners */
         notifyNode(node, UpdateType.CHANGED, propMap);
@@ -928,30 +1017,67 @@ CommandProvider {
 
     @Override
     public void setNodeProp(Node node, Property prop) {
-        /* Get a copy of the property map */
-        Map<String, Property> propMap = getNodeProps(node);
-        if (propMap == null) {
-            return;
-        }
 
-        propMap.put(prop.getName(), prop);
-        this.nodeProps.put(node, propMap);
+        for (int i = 0; i <= REPLACE_RETRY; i++) {
+            /* Get a copy of the property map */
+            Map<String, Property> propMapCurr = getNodeProps(node);
+            if (propMapCurr == null) {
+                return;
+            }
+
+            Map<String, Property> propMap = new HashMap<String, Property>();
+            for (String s : propMapCurr.keySet()) {
+                propMap.put(s, propMapCurr.get(s).clone());
+            }
+
+            propMap.put(prop.getName(), prop);
+
+            if (nodeProps.replace(node, propMapCurr, propMap)) {
+                return;
+            }
+            if (!propMapCurr.get(prop.getName()).equals(nodeProps.get(node).get(prop.getName()))) {
+                log.warn("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
+                return;
+            }
+        }
+        log.warn("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
     }
 
     @Override
     public Status removeNodeProp(Node node, String propName) {
-        Map<String, Property> propMap = getNodeProps(node);
-        if (propMap != null) {
-            propMap.remove(propName);
-            this.nodeProps.put(node, propMap);
+        for (int i = 0; i <= REPLACE_RETRY; i++) {
+            Map<String, Property> propMapCurr = getNodeProps(node);
+            if (propMapCurr != null) {
+                if (!propMapCurr.containsKey(propName)) {
+                    return new Status(StatusCode.SUCCESS);
+                }
+                Map<String, Property> propMap = new HashMap<String, Property>();
+                for (String s : propMapCurr.keySet()) {
+                    propMap.put(s, propMapCurr.get(s).clone());
+                }
+
+                propMap.remove(propName);
+                if (nodeProps.replace(node, propMapCurr, propMap)) {
+                    return new Status(StatusCode.SUCCESS);
+                }
+                if (!propMapCurr.get(propName).equals(nodeProps.get(node).get(propName))) {
+                    String msg = "Cluster conflict: Unable to remove property " + propName + " for node "
+                            + node.getID();
+                    return new Status(StatusCode.CONFLICT, msg);
+                }
+
+            } else {
+                return new Status(StatusCode.SUCCESS);
+            }
         }
-        return new Status(StatusCode.SUCCESS, null);
+        String msg = "Cluster conflict: Unable to remove property " + propName + " for node " + node.getID();
+        return new Status(StatusCode.CONFLICT, msg);
     }
 
     @Override
     public Status removeNodeAllProps(Node node) {
         this.nodeProps.remove(node);
-        return new Status(StatusCode.SUCCESS, null);
+        return new Status(StatusCode.SUCCESS);
     }
 
     @Override
@@ -1100,36 +1226,73 @@ CommandProvider {
     @Override
     public Status addNodeConnectorProp(NodeConnector nodeConnector,
             Property prop) {
-        Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
+        Map<String, Property> propMapCurr = getNodeConnectorProps(nodeConnector);
+        Map<String, Property> propMap = new HashMap<String, Property>();
 
-        if (propMap == null) {
-            propMap = new HashMap<String, Property>();
+        if (propMapCurr != null) {
+            for (String s : propMapCurr.keySet()) {
+                propMap.put(s, propMapCurr.get(s).clone());
+            }
         }
 
+        String msg = "Cluster conflict: Unable to add NodeConnector Property.";
         // Just add the nodeConnector if prop is not available (in a non-default
         // container)
         if (prop == null) {
-            nodeConnectorProps.put(nodeConnector, propMap);
-            return new Status(StatusCode.SUCCESS, null);
+            if (propMapCurr == null) {
+                if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) {
+                    return new Status(StatusCode.CONFLICT, msg);
+                }
+            } else {
+                if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) {
+                    return new Status(StatusCode.CONFLICT, msg);
+                }
+            }
+            return new Status(StatusCode.SUCCESS);
         }
 
         propMap.put(prop.getName(), prop);
-        nodeConnectorProps.put(nodeConnector, propMap);
+        if (propMapCurr == null) {
+            if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) {
+                return new Status(StatusCode.CONFLICT, msg);
+            }
+        } else {
+            if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) {
+                return new Status(StatusCode.CONFLICT, msg);
+            }
+        }
 
         if (prop.getName().equals(Name.NamePropName)) {
             if (nodeConnectorNames != null) {
                 Node node = nodeConnector.getNode();
-                Map<String, NodeConnector> map = nodeConnectorNames.get(node);
-                if (map == null) {
-                    map = new HashMap<String, NodeConnector>();
+                Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
+                Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
+                if (mapCurr != null) {
+                    for (String s : mapCurr.keySet()) {
+                        try {
+                            map.put(s, new NodeConnector(mapCurr.get(s)));
+                        } catch (ConstructionException e) {
+                            e.printStackTrace();
+                        }
+                    }
                 }
 
                 map.put(((Name) prop).getValue(), nodeConnector);
-                nodeConnectorNames.put(node, map);
+                if (mapCurr == null) {
+                    if (nodeConnectorNames.putIfAbsent(node, map) != null) {
+                        // TODO: recovery using Transactionality
+                        return new Status(StatusCode.CONFLICT, msg);
+                    }
+                } else {
+                    if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+                        // TODO: recovery using Transactionality
+                        return new Status(StatusCode.CONFLICT, msg);
+                    }
+                }
             }
         }
 
-        return new Status(StatusCode.SUCCESS, null);
+        return new Status(StatusCode.SUCCESS);
     }
 
     /**
@@ -1142,32 +1305,53 @@ CommandProvider {
      * @return success or failed reason
      */
     @Override
-    public Status removeNodeConnectorProp(NodeConnector nodeConnector,
-            String propName) {
-        Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
+    public Status removeNodeConnectorProp(NodeConnector nodeConnector, String propName) {
+        Map<String, Property> propMapCurr = getNodeConnectorProps(nodeConnector);
 
-        if (propMap == null) {
+        if (propMapCurr == null) {
             /* Nothing to remove */
-            return new Status(StatusCode.SUCCESS, null);
+            return new Status(StatusCode.SUCCESS);
+        }
+
+        Map<String, Property> propMap = new HashMap<String, Property>();
+
+        for (String s : propMapCurr.keySet()) {
+            propMap.put(s, propMapCurr.get(s).clone());
         }
 
         propMap.remove(propName);
-        nodeConnectorProps.put(nodeConnector, propMap);
+        boolean result = nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap);
+        String msg = "Cluster conflict: Unable to remove NodeConnector property.";
+        if (!result) {
+            return new Status(StatusCode.CONFLICT, msg);
+        }
 
-        if (nodeConnectorNames != null) {
-            Name name = ((Name) getNodeConnectorProp(nodeConnector,
-                    Name.NamePropName));
-            if (name != null) {
-                Node node = nodeConnector.getNode();
-                Map<String, NodeConnector> map = nodeConnectorNames.get(node);
-                if (map != null) {
-                    map.remove(name.getValue());
-                    nodeConnectorNames.put(node, map);
+        if (propName.equals(Name.NamePropName)) {
+            if (nodeConnectorNames != null) {
+                Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName));
+                if (name != null) {
+                    Node node = nodeConnector.getNode();
+                    Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
+                    if (mapCurr != null) {
+                        Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
+                        for (String s : mapCurr.keySet()) {
+                            try {
+                                map.put(s, new NodeConnector(mapCurr.get(s)));
+                            } catch (ConstructionException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        map.remove(name.getValue());
+                        if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+                            // TODO: recovery using Transactionality
+                            return new Status(StatusCode.CONFLICT, msg);
+                        }
+                    }
                 }
             }
         }
 
-        return new Status(StatusCode.SUCCESS, null);
+        return new Status(StatusCode.SUCCESS);
     }
 
     /**
@@ -1180,20 +1364,31 @@ CommandProvider {
     @Override
     public Status removeNodeConnectorAllProps(NodeConnector nodeConnector) {
         if (nodeConnectorNames != null) {
-            Name name = ((Name) getNodeConnectorProp(nodeConnector,
-                    Name.NamePropName));
+            Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName));
             if (name != null) {
                 Node node = nodeConnector.getNode();
-                Map<String, NodeConnector> map = nodeConnectorNames.get(node);
-                if (map != null) {
+                Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
+                if (mapCurr != null) {
+                    Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
+                    for (String s : mapCurr.keySet()) {
+                        try {
+                            map.put(s, new NodeConnector(mapCurr.get(s)));
+                        } catch (ConstructionException e) {
+                            e.printStackTrace();
+                        }
+                    }
                     map.remove(name.getValue());
-                    nodeConnectorNames.put(node, map);
+                    if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+                        log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.",
+                                nodeConnector.getID());
+                    }
                 }
+
             }
         }
         nodeConnectorProps.remove(nodeConnector);
 
-        return new Status(StatusCode.SUCCESS, null);
+        return new Status(StatusCode.SUCCESS);
     }
 
     /**
@@ -1339,22 +1534,21 @@ CommandProvider {
         }
 
         Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
-        for(Map.Entry<Node, Map<String, Property>> entry : nodeProp.entrySet()) {
+        for (Map.Entry<Node, Map<String, Property>> entry : nodeProp.entrySet()) {
             Node node = entry.getKey();
-            log.debug("getInventories: {} added for container {}",
-                    new Object[] { node, containerName });
+            log.debug("getInventories: {} added for container {}", new Object[] { node, containerName });
             Map<String, Property> propMap = entry.getValue();
             Set<Property> props = new HashSet<Property>();
-            for(Property property : propMap.values()) {
+            for (Property property : propMap.values()) {
                 props.add(property);
             }
             addNode(node, props);
         }
 
         Map<NodeConnector, Map<String, Property>> nodeConnectorProp = this.inventoryService.getNodeConnectorProps();
-        for(Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProp.entrySet()) {
+        for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProp.entrySet()) {
             Map<String, Property> propMap = entry.getValue();
-            for(Property property : propMap.values()) {
+            for (Property property : propMap.values()) {
                 addNodeConnectorProp(entry.getKey(), property);
             }
         }
index 9bb231fb0398b1bcbf1fcaae96f606d596374676..25d54906edc74fda57bfb331af1c52f193101bbe 100644 (file)
@@ -31,7 +31,7 @@ public class SwitchManagerImplTest {
     @Test
     public void testSwitchManagerAddRemoveSubnet() {
         SwitchManagerImpl switchmgr = new SwitchManagerImpl();
-        switchmgr.nonClusterObjectCreate();
+        switchmgr.startUp();
 
         ArrayList<String> portList = new ArrayList<String>();
         portList.add("1/1");
@@ -56,7 +56,7 @@ public class SwitchManagerImplTest {
     @Test
     public void testSwitchManagerNodeConnectors() {
         SwitchManagerImpl switchmgr = new SwitchManagerImpl();
-        switchmgr.nonClusterObjectCreate();
+        switchmgr.startUp();
 
         State state;
         Bandwidth bw;
index ea24ffcf88b0e6d287367ee60748e3c87baba2f3..39a9cceb085fc68cade5c53d961b06a8a9c8d6b2 100644 (file)
@@ -8,65 +8,48 @@
 
 package org.opendaylight.controller.switchmanager.internal;
 
-import java.net.InetAddress;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemPackages;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
 import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Bundle;
 import javax.inject.Inject;
 
-import org.eclipse.osgi.framework.console.CommandProvider;
 import org.junit.Assert;
-import org.junit.Test;
 import org.junit.Before;
-import org.junit.After;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.opendaylight.controller.sal.core.Actions;
 import org.opendaylight.controller.sal.core.Bandwidth;
 import org.opendaylight.controller.sal.core.Buffers;
 import org.opendaylight.controller.sal.core.Capabilities;
+import org.opendaylight.controller.sal.core.Capabilities.CapabilitiesType;
 import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.Property;
 import org.opendaylight.controller.sal.core.State;
 import org.opendaylight.controller.sal.core.TimeStamp;
-import org.opendaylight.controller.sal.core.UpdateType;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.Capabilities.CapabilitiesType;
-import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
-import org.opendaylight.controller.sal.utils.NodeCreator;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
-import org.opendaylight.controller.switchmanager.*;
-import org.opendaylight.controller.configuration.IConfigurationContainerAware;
-import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
-
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.util.Filter;
-import org.osgi.framework.BundleContext;
-import static org.junit.Assert.*;
-import org.ops4j.pax.exam.junit.Configuration;
-import static org.ops4j.pax.exam.CoreOptions.*;
-
 import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.util.PathUtils;
-import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
-import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @RunWith(PaxExam.class)
 public class SwitchManagerIT {
-    private Logger log = LoggerFactory.getLogger(SwitchManagerIT.class);
+    private final Logger log = LoggerFactory.getLogger(SwitchManagerIT.class);
     // get the OSGI bundle context
     @Inject
     private BundleContext bc;
@@ -107,29 +90,28 @@ public class SwitchManagerIT {
                         .versionAsInProject(),
                 mavenBundle("ch.qos.logback", "logback-classic")
                         .versionAsInProject(),
-
-                mavenBundle("org.opendaylight.controller", "switchmanager")
-                        .versionAsInProject(),
-                mavenBundle("org.opendaylight.controller",
-                        "switchmanager.implementation").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "sal")
+                mavenBundle("org.opendaylight.controller", "clustering.stub")
                         .versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "sal.implementation")
+                mavenBundle("org.opendaylight.controller", "configuration")
                         .versionAsInProject(),
+                mavenBundle("org.opendaylight.controller",
+                        "configuration.implementation").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "containermanager")
                         .versionAsInProject(),
                 mavenBundle("org.opendaylight.controller",
                         "containermanager.implementation").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller",
                         "clustering.services").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "clustering.stub")
+                mavenBundle("org.opendaylight.controller", "sal")
                         .versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "configuration")
+                mavenBundle("org.opendaylight.controller", "sal.implementation")
                         .versionAsInProject(),
                 mavenBundle("org.opendaylight.controller",
-                        "configuration.implementation").versionAsInProject(),
+                                "protocol_plugins.stub").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "switchmanager")
+                        .versionAsInProject(),
                 mavenBundle("org.opendaylight.controller",
-                        "protocol_plugins.stub").versionAsInProject(),
+                        "switchmanager.implementation").versionAsInProject(),
                 mavenBundle("org.jboss.spec.javax.transaction",
                         "jboss-transaction-api_1.1_spec").versionAsInProject(),
                 mavenBundle("org.apache.commons", "commons-lang3")
@@ -203,11 +185,11 @@ public class SwitchManagerIT {
 
         Assert.assertTrue(this.switchManager.getNodeProp(node,
                 Capabilities.CapabilitiesPropName).equals(
-                new Capabilities((int) 3)));
+                new Capabilities(3)));
         Assert.assertTrue(this.switchManager.getNodeProp(node,
-                Actions.ActionsPropName).equals(new Actions((int) 2)));
+                Actions.ActionsPropName).equals(new Actions(2)));
         Assert.assertTrue(this.switchManager.getNodeProp(node,
-                Buffers.BuffersPropName).equals(new Buffers((int) 1)));
+                Buffers.BuffersPropName).equals(new Buffers(1)));
         Assert.assertTrue(this.switchManager.getNodeProp(node,
                 TimeStamp.TimeStampPropName).equals(
                 new TimeStamp(100000L, "connectedSince")));
index 534c2c293c9c9fecc9bf8467fc74d0e237261ac9..04f9863312891978502efedb34410a334da02fd1 100644 (file)
@@ -16,17 +16,11 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentMap;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.codehaus.jackson.map.ObjectMapper;
-import org.opendaylight.controller.web.DaylightWebUtil;
-import org.opendaylight.controller.web.IDaylightWeb;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
 import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
 import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig;
 import org.opendaylight.controller.sal.authorization.Privilege;
@@ -46,6 +40,13 @@ import org.opendaylight.controller.switchmanager.SpanConfig;
 import org.opendaylight.controller.switchmanager.SubnetConfig;
 import org.opendaylight.controller.switchmanager.Switch;
 import org.opendaylight.controller.switchmanager.SwitchConfig;
+import org.opendaylight.controller.web.DaylightWebUtil;
+import org.opendaylight.controller.web.IDaylightWeb;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
 
 import com.google.gson.Gson;
 
index be7560985a56fdeb3df3ae1d28020f8f87cd56a7..145ef9086e4a41ef8649470fc7ebd4f851376de6 100644 (file)
@@ -241,7 +241,7 @@ public class Flows implements IDaylightWeb {
         flow.setNode(node);
         Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
         if (action.equals("add")) {
-            result = frm.addStaticFlow(flow, false);
+            result = frm.addStaticFlow(flow);
         }
 
         return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result
index 79edf904f176a6f1c533c1e88f82bee2ff814a92..f637b21e1e8f74975858625ce20e20023a03fc26 100644 (file)
@@ -44,7 +44,7 @@ public abstract class OFActionDataLayer extends OFAction {
     @Override
     public void writeTo(ByteBuffer data) {
         super.writeTo(data);
-        data.put(this.dataLayerAddress);
+        data.put(this.dataLayerAddress, 0, OFPhysicalPort.OFP_ETH_ALEN);
         data.putInt(0);
         data.putShort((short) 0);
     }
@@ -74,4 +74,4 @@ public abstract class OFActionDataLayer extends OFAction {
         }
         return true;
     }
-}
\ No newline at end of file
+}