Merge "Added multipart table response as notification in yang model."
authorEd Warnicke <eaw@cisco.com>
Thu, 5 Dec 2013 22:14:27 +0000 (22:14 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 5 Dec 2013 22:14:27 +0000 (22:14 +0000)
76 files changed:
opendaylight/clustering/integrationtest/pom.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/configuration/integrationtest/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/forwardingrulesmanager/api/pom.xml
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java
opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java
opendaylight/forwardingrulesmanager/implementation/pom.xml
opendaylight/forwardingrulesmanager/integrationtest/pom.xml
opendaylight/hosttracker/integrationtest/pom.xml
opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingBrokerTestFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-dom-it/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java with 100% similarity]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java with 94% similarity]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java with 100% similarity]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java with 100% similarity]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java with 100% similarity]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java with 100% similarity]
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlMapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNodeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java
opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/IOThread.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java
opendaylight/northbound/flowprogrammer/pom.xml
opendaylight/northbound/integrationtest/pom.xml
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java
opendaylight/protocol_plugins/openflow/pom.xml
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TableStatisticsConverter.java
opendaylight/sal/api/pom.xml
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeTableStatisticsTest.java
opendaylight/sal/implementation/pom.xml
opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java
opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java
opendaylight/statisticsmanager/integrationtest/pom.xml
opendaylight/switchmanager/api/pom.xml
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISwitchManager.java
opendaylight/switchmanager/implementation/pom.xml
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
opendaylight/switchmanager/integrationtest/pom.xml

index 43fa74fba8dd9a10b0d167fd0a05cf4f7fcfd0c5..1e317765c4085a1866e1ab7834123f1845658ce7 100644 (file)
@@ -26,7 +26,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 1cdf391a2ee50145dc5c08d7351431e5fd5a431b..dd73815b34475757d6950662bcbcfc0dd165a51f 100644 (file)
@@ -84,9 +84,9 @@
     <netconf.version>0.2.3-SNAPSHOT</netconf.version>
     <mdsal.version>1.0-SNAPSHOT</mdsal.version>
     <containermanager.version>0.5.1-SNAPSHOT</containermanager.version>
-    <switchmanager.api.version>0.6.1-SNAPSHOT</switchmanager.api.version>
+    <switchmanager.api.version>0.7.0-SNAPSHOT</switchmanager.api.version>
     <connectionmanager.version>0.1.1-SNAPSHOT</connectionmanager.version>
-    <sal.version>0.6.0-SNAPSHOT</sal.version>
+    <sal.version>0.7.0-SNAPSHOT</sal.version>
     <sal.networkconfiguration.version>0.0.2-SNAPSHOT</sal.networkconfiguration.version>
     <sal.connection.version>0.1.1-SNAPSHOT</sal.connection.version>
     <networkconfig.bridgedomain.northbound.version>0.0.2-SNAPSHOT</networkconfig.bridgedomain.northbound.version>
index 6bcee92544327290aeea3826f79d26edaad206cf..e18fe8c1ed375ccc7ea666547914dda9c3969c4e 100644 (file)
@@ -25,7 +25,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
      <dependency>
       <groupId>org.opendaylight.controller</groupId>
index b9b9c7337d8922e82b8f1f8927c40be8422d8d51..7d57e6005e65774519d579838c90c9cbd4f8fe85 100644 (file)
@@ -17,6 +17,9 @@ osgi.bundles=\
 netconf.tcp.address=0.0.0.0
 netconf.tcp.port=8383
 
+netconf.tcp.client.address=127.0.0.1
+netconf.tcp.client.port=8383
+
 netconf.ssh.address=0.0.0.0
 netconf.ssh.port=1830
 
index f25756cc115eb9ed61c40361b9b3d4d18ce6e7d1..499b98c28ad1c04dd8512af4501b799e4a3e0124 100644 (file)
@@ -87,7 +87,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>junit</groupId>
index 43b0252df7b5c8aa83df94866632887286b44252..de7597730f9062a85d7071b3986044c4874a4e7a 100644 (file)
@@ -13,7 +13,6 @@ import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -26,6 +25,7 @@ import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.ActionType;
 import org.opendaylight.controller.sal.action.Controller;
 import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.action.Enqueue;
 import org.opendaylight.controller.sal.action.Flood;
 import org.opendaylight.controller.sal.action.HwPath;
 import org.opendaylight.controller.sal.action.Loopback;
@@ -609,25 +609,13 @@ public class FlowConfig implements Serializable {
         return true;
     }
 
-    public boolean isPortValid(Switch sw, Short port) {
-        if (port < 1) {
-            log.debug("port {} is not valid", port);
-            return false;
-        }
-
+    public boolean isPortValid(Switch sw, String port) {
         if (sw == null) {
             log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
             return true;
         }
-
-        Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
-        for (NodeConnector nodeConnector : nodeConnectorSet) {
-            if (((Short) nodeConnector.getID()).equals(port)) {
-                return true;
-            }
-        }
-        log.debug("port {} is not a valid port of node {}", port, sw.getNode());
-        return false;
+        NodeConnector nc = NodeConnectorCreator.createNodeConnector(port, sw.getNode());
+        return sw.getNodeConnectors().contains(nc);
     }
 
     public boolean isVlanIdValid(String vlanId) {
@@ -735,9 +723,8 @@ public class FlowConfig implements Serializable {
             }
 
             if (ingressPort != null) {
-                Short port = Short.decode(ingressPort);
-                if (isPortValid(sw, port) == false) {
-                    String msg = String.format("Ingress port %d is not valid for the Switch", port);
+                if (!isPortValid(sw, ingressPort)) {
+                    String msg = String.format("Ingress port %s is not valid for the Switch", ingressPort);
                     if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
                         msg += " in Container " + containerName;
                     }
@@ -850,10 +837,33 @@ public class FlowConfig implements Serializable {
                 if (sstr.matches()) {
                     for (String t : sstr.group(1).split(",")) {
                         Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
+                        if (n.matches()) {
+                            String port = n.group(1);
+                            if (port != null) {
+                                if (!isPortValid(sw, port)) {
+                                    String msg = String.format("Output port %s is not valid for this switch", port);
+                                    if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
+                                        msg += " in Container " + containerName;
+                                    }
+                                    return new Status(StatusCode.BADREQUEST, msg);
+                                }
+                            }
+                        } else {
+                            String msg = String.format("Output port %s is not valid", t);
+                            return new Status(StatusCode.BADREQUEST, msg);
+                        }
+                    }
+                    continue;
+                }
+                // check enqueue
+                sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp);
+                if (sstr.matches()) {
+                    for (String t : sstr.group(1).split(",")) {
+                        Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
                         if (n.matches()) {
                             if (n.group(1) != null) {
-                                Short port = Short.parseShort(n.group(1));
-                                if (isPortValid(sw, port) == false) {
+                                String port = n.group(1).split(":")[0];
+                                if (!isPortValid(sw, port)) {
                                     String msg = String.format("Output port %d is not valid for this switch", port);
                                     if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
                                         msg += " in Container " + containerName;
@@ -862,7 +872,7 @@ public class FlowConfig implements Serializable {
                                 }
                             }
                         } else {
-                            String msg = String.format("Output port %s is not valid", t);
+                            String msg = String.format("Enqueue port %s is not valid", t);
                             return new Status(StatusCode.BADREQUEST, msg);
                         }
                     }
@@ -990,7 +1000,7 @@ public class FlowConfig implements Serializable {
 
         if (this.ingressPort != null) {
             match.setField(MatchType.IN_PORT,
-                    NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode()));
+                    NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
         }
         if (this.dlSrc != null) {
             match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
@@ -1095,9 +1105,28 @@ public class FlowConfig implements Serializable {
                         Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
                         if (n.matches()) {
                             if (n.group(1) != null) {
-                                short ofPort = Short.parseShort(n.group(1));
-                                actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort,
-                                        this.getNode())));
+                                String nc = String.format("%s|%s@%s", node.getType(), n.group(1), node.toString());
+                                actionList.add(new Output(NodeConnector.fromString(nc)));
+                            }
+                        }
+                    }
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
+                if (sstr.matches()) {
+                    for (String t : sstr.group(1).split(",")) {
+                        Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
+                        if (n.matches()) {
+                            if (n.group(1) != null) {
+                                String parts[] = n.group(1).split(":");
+                                String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
+                                if (parts.length == 1) {
+                                    actionList.add(new Enqueue(NodeConnector.fromString(nc)));
+                                } else {
+                                    actionList
+                                            .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
+                                }
                             }
                         }
                     }
index 406970711ccf5cc8e93071f3fec172c6582f23cf..48e1f07716ec267ddb52340e3ea21ef64ac8cebd 100644 (file)
@@ -546,11 +546,6 @@ public class frmTest {
         fc.setCookie("100");
         Assert.assertTrue(fc.validate(null).isSuccess());
 
-        fc.setIngressPort("-1");
-        status = fc.validate(null);
-        Assert.assertFalse(status.isSuccess());
-        Assert.assertTrue(status.getDescription().contains("is not valid for the Switch"));
-
         fc.setIngressPort("100");
         Assert.assertTrue(fc.validate(null).isSuccess());
 
index 23c36a37528b671829584177ac0f9ed4e5498f94..6b3f5347adb58e7bb31f28d4dae6de262a15db65 100644 (file)
@@ -93,7 +93,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 95fbd5dafb66b2e376f595b9d8fa90552ab1c522..1595f257d41fc173c686f8bf30ac25aac37dbf49 100644 (file)
@@ -71,7 +71,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>switchmanager</artifactId>
-      <version>0.6.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
@@ -81,7 +81,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 2e80cac2ac540ca36a5ca8c4a6fbb80b07afbd3b..03e70002d3b2c0b6e462af5f451213384efd0ab2 100644 (file)
@@ -31,7 +31,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
@@ -70,7 +70,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>switchmanager</artifactId>
-      <version>0.6.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 968f87a40200c1bbf86ef7a196f92b8d96f9e8f4..176ab6cbe0138a5ae9cecdf4877bb5a4ebeaa5d1 100644 (file)
 
     <artifactId>clustered-datastore.integrationtest</artifactId>
     <version>0.4.0-SNAPSHOT</version>
-    <dependencies>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>xml-apis</groupId>
+                <artifactId>xml-apis</artifactId>
+                <version>1.4.01</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
             <version>1.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>xml-apis</artifactId>
+                    <groupId>xml-apis</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>reflections</artifactId>
+                    <groupId>org.reflections</groupId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-netconf-connector</artifactId>
             <version>${netconf.version}</version>
             <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <artifactId>xml-apis</artifactId>
+                    <groupId>xml-apis</groupId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
index 94c31dd0411eb041fc11fd61adcab23dd369a105..0e78598c1137a339c7368be40b0b7a7e39427b9a 100644 (file)
@@ -29,6 +29,7 @@
         <module>sal-binding-broker</module>
 
         <module>sal-binding-util</module>
+        <module>sal-binding-dom-it</module>
 
         <!-- Samples -->
         <module>samples</module>
 
     <dependencyManagement>
         <dependencies>
-
-
-
+            <dependency>
+                <groupId>xml-apis</groupId>
+                <artifactId>xml-apis</artifactId>
+                <version>1.4.01</version>
+            </dependency>
 
             <!-- YANG Tools Dependencies -->
             <dependency>
index 89bb1e8502570ee901d5e0f5f6052ce450140120..ac84aab977783edbebc416d4755379967f70e84c 100644 (file)
                     </execution>
                 </executions>
             </plugin>
+
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
             <groupId>org.reflections</groupId>
             <artifactId>reflections</artifactId>
             <version>0.9.9-RC1</version>
+            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>org.javassist</groupId>
             <groupId>org.eclipse.xtend</groupId>
             <artifactId>org.eclipse.xtend.lib</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.eclipse.xtend</groupId>
-            <artifactId>org.eclipse.xtend.standalone</artifactId>
-            <version>2.4.3</version>
-            <scope>runtime</scope>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-config</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-service</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-management</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-impl</artifactId>
             <version>${slf4j.version}</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-statistics</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.reflections</groupId>
-            <artifactId>reflections</artifactId>
-            <version>0.9.9-RC1</version>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 </project>
index de6836489e6a6b970fb96a409e832876d02e82a7..d33272d6413bfa90628f49a459671eab756ef2d0 100644 (file)
@@ -91,7 +91,7 @@ public class LazyGeneratedCodecRegistry implements //
     Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
 
     @SuppressWarnings("rawtypes")
-    private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseNodes = new ConcurrentHashMap<>();
+    private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
 
     private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
 
@@ -136,15 +136,14 @@ public class LazyGeneratedCodecRegistry implements //
         }
         return weakRef.get();
     }
-    
+
     @Override
-    public void putPathToClass(List<QName> names,Class<?> cls) {
+    public void putPathToClass(List<QName> names, Class<?> cls) {
         Type reference = Types.typeForClass(cls);
-        pathToInstantiatedType.put(names, reference );
+        pathToInstantiatedType.put(names, reference);
         bindingClassEncountered(cls);
     }
 
-
     @Override
     public IdentifierCodec<?> getKeyCodecForPath(List<QName> names) {
         @SuppressWarnings("unchecked")
@@ -297,10 +296,12 @@ public class LazyGeneratedCodecRegistry implements //
             return potential;
         }
         ConcreteType typeref = Types.typeForClass(caseClass);
-        ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref);
+        ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref);
 
+        checkState(caseCodec != null, "Case Codec was not created proactivelly for %s", caseClass.getName());
+        checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName());
         @SuppressWarnings("unchecked")
-        Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.schema);
+        Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
         BindingCodec newInstance = newInstanceOf(newCodec);
         caseCodec.setDelegate(newInstance);
         caseCodecs.put(caseClass, caseCodec);
@@ -322,17 +323,23 @@ public class LazyGeneratedCodecRegistry implements //
         for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
             ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
                     .getValue().getName());
+
+            LOG.info("Case path: {} Type : {}", caseNode.getKey(), caseNode.getValue().getFullyQualifiedName());
+            pathToType.put(caseNode.getKey(), caseNode.getValue());
+
             ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
+
             if (node == null) {
                 LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",
                         typeref.getFullyQualifiedName(), caseNode.getKey());
+                @SuppressWarnings("rawtypes")
+                ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl();
+                typeToCaseCodecs.putIfAbsent(typeref, value);
                 continue;
             }
-
-            pathToType.put(caseNode.getKey(), caseNode.getValue());
             @SuppressWarnings("rawtypes")
             ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
-            typeToCaseNodes.putIfAbsent(typeref, value);
+            typeToCaseCodecs.putIfAbsent(typeref, value);
         }
     }
 
@@ -352,18 +359,24 @@ public class LazyGeneratedCodecRegistry implements //
         choiceCodecs.put(choiceClass, newCodec);
         CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class<?>, BindingCodec<?, ?>>) classToCaseRawCodec);
         CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
-        
+
         tryToCreateCasesCodecs(schema);
 
     }
 
     private void tryToCreateCasesCodecs(ChoiceNode schema) {
-        for(ChoiceCaseNode caseNode : schema.getCases()) {
+        for (ChoiceCaseNode caseNode : schema.getCases()) {
             SchemaPath path = caseNode.getPath();
             GeneratedTypeBuilder type;
-            if(path != null && (type = pathToType.get(path)) != null) {
+            if (path != null && (type = pathToType.get(path)) != null) {
+                ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+                ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref);
+                if(partialCodec.getSchema() == null ) {
+                    partialCodec.setSchema(caseNode);
+                }
+                
                 Class<?> caseClass = ClassLoaderUtils.tryToLoadClassWithTCCL(type.getFullyQualifiedName());
-                if(caseClass != null) {
+                if (caseClass != null) {
                     getCaseCodecFor(caseClass);
                 }
             }
@@ -381,8 +394,7 @@ public class LazyGeneratedCodecRegistry implements //
     }
 
     @Override
-    public void onDataContainerCodecCreated(Class<?> dataClass,
-            Class<? extends BindingCodec<?,?>> dataCodec) {
+    public void onDataContainerCodecCreated(Class<?> dataClass, Class<? extends BindingCodec<?, ?>> dataCodec) {
         if (Augmentable.class.isAssignableFrom(dataClass)) {
             AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
             CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
@@ -471,15 +483,15 @@ public class LazyGeneratedCodecRegistry implements //
     @SuppressWarnings("rawtypes")
     private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
             Delegator<BindingCodec> {
-        private final boolean augmenting;
+        private boolean augmenting;
         private BindingCodec delegate;
 
-        private final Set<String> validNames;
-        private final Set<QName> validQNames;
+        private Set<String> validNames;
+        private Set<QName> validQNames;
         private ChoiceCaseNode schema;
 
-        public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
-            this.delegate = NOT_READY_CODEC;
+        public void setSchema(ChoiceCaseNode caseNode) {
+            this.schema = schema;
             this.schema = caseNode;
             validNames = new HashSet<>();
             validQNames = new HashSet<>();
@@ -491,6 +503,15 @@ public class LazyGeneratedCodecRegistry implements //
             augmenting = caseNode.isAugmenting();
         }
 
+        public ChoiceCaseCodecImpl() {
+            this.delegate = NOT_READY_CODEC;
+        }
+
+        public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
+            this.delegate = NOT_READY_CODEC;
+            setSchema(caseNode);
+        }
+
         @Override
         public ValueWithQName<T> deserialize(Node<?> input) {
             throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
index 7eb473ce3401a6774ed31f9690db658f24e4a576..cb25f4da8bb9247845c251ed95b67ee6ffeca4d5 100644 (file)
@@ -78,7 +78,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         for (entry : newBinding.moduleContexts.entrySet) {
 
             registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
-
+            binding.pathToType.putAll(entry.value.childNodes)
             //val module = entry.key;
             val context = entry.value;
             updateBindingFor(context.childNodes, schemaContext);
@@ -174,16 +174,18 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
     }
 
     private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+        
         for (entry : map.entrySet) {
             val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
 
             //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
+            val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
+            typeToDefinition.put(typeRef, entry.value);
             if (schemaNode != null) {
-                val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
                 typeToSchemaNode.put(typeRef, schemaNode);
-                typeToDefinition.put(typeRef, entry.value);
                 updatePromisedSchemas(typeRef, schemaNode);
             }
+            
         }
     }
 
index a732f152b25675612a21a3a6aad503c5971dbdaa..0316614aa1269a93eb8d6aa3f7d2e3fd2a4438a7 100644 (file)
@@ -49,6 +49,8 @@ import static extension org.opendaylight.controller.sal.binding.impl.util.YangSc
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
 import org.opendaylight.yangtools.yang.model.util.ExtendedType
 import org.opendaylight.yangtools.yang.model.util.EnumerationType
+import static com.google.common.base.Preconditions.*
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
 
 class TransformerGenerator {
 
@@ -78,6 +80,9 @@ class TransformerGenerator {
     @Property
     var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
 
+    @Property
+    var Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap();
+
     @Property
     var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
 
@@ -105,6 +110,27 @@ class TransformerGenerator {
             val ref = Types.typeForClass(inputType)
             val node = typeToSchemaNode.get(ref)
             val typeSpecBuilder = typeToDefinition.get(ref)
+            checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
+            val typeSpec = typeSpecBuilder.toInstance();
+            val newret = generateTransformerFor(inputType, typeSpec, node);
+            listener.onClassProcessed(inputType);
+            return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        ]
+    }
+
+    def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
+        return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+            val ret = getGeneratedClass(inputType)
+            if (ret !== null) {
+                listener.onClassProcessed(inputType);
+                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+            }
+            val ref = Types.typeForClass(inputType)
+            var typeSpecBuilder = typeToDefinition.get(ref)
+            if (typeSpecBuilder == null) {
+                typeSpecBuilder = pathToType.get(node.path);
+            }
+            checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
             val typeSpec = typeSpecBuilder.toInstance();
             val newret = generateTransformerFor(inputType, typeSpec, node);
             listener.onClassProcessed(inputType);
@@ -205,11 +231,9 @@ class TransformerGenerator {
         keyTransformerFor(cls, type, node);
     }
 
-    private def serializer(Type type) {
+    private def serializer(Type type, DataSchemaNode node) {
         val cls = loadClassWithTCCL(type.resolvedName);
-
-        transformerFor(cls);
-
+        transformerFor(cls, node);
     }
 
     private def Class<?> getValueSerializer(GeneratedTransferObject type) {
@@ -367,7 +391,7 @@ class TransformerGenerator {
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)  as Class<? extends BindingCodec<Object, Object>>
-            listener?.onDataContainerCodecCreated(inputType,ret);
+            listener?.onDataContainerCodecCreated(inputType, ret);
             log.info("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
@@ -710,7 +734,7 @@ class TransformerGenerator {
                 Object _listItem = _iterator.next();
                 _is_empty = false;
                 //System.out.println("  item" + _listItem);
-                Object _value = Â«type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
+                Object _value = Â«type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
                 //System.out.println("  value" + _value);
                 Â«propertyName».add(_value);
                 _hasNext = _iterator.hasNext();
@@ -762,12 +786,12 @@ class TransformerGenerator {
         if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
             _is_empty = false;
             java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
-            Â«propertyName» =  Â«type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
+            Â«propertyName» =  Â«type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
         }
     '''
 
     private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
-        Â«type.resolvedName» Â«propertyName» = Â«type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
+        Â«type.resolvedName» Â«propertyName» = Â«type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
         if(«propertyName» != null) {
             _is_empty = false;
         }
@@ -1140,7 +1164,7 @@ class TransformerGenerator {
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
-                Object _domValue = Â«type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
+                Object _domValue = Â«type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem);
                 _childNodes.add(_domValue);
                 _hasNext = _iterator.hasNext();
             }
@@ -1193,7 +1217,7 @@ class TransformerGenerator {
         String propertyName) '''
         Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
         if(«propertyName» != null) {
-            java.util.List domValue = Â«type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+            java.util.List domValue = Â«type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
             _childNodes.addAll(domValue);
         }
     '''
@@ -1219,7 +1243,7 @@ class TransformerGenerator {
         String propertyName) '''
         Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
         if(«propertyName» != null) {
-            Object domValue = Â«type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+            Object domValue = Â«type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
             _childNodes.add(domValue);
         }
     '''
index 596329e07b1cdb23b2642d3f97e943aebcbf579a..d230fd17f9475c24bd920094a233734291593901 100644 (file)
@@ -7,9 +7,10 @@ import static com.google.common.base.Preconditions.*;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import com.google.common.base.Joiner;
 import com.google.common.base.Optional;
 
 public final class ClassLoaderUtils {
@@ -56,15 +57,28 @@ public final class ClassLoaderUtils {
         if ("byte[]".equals(name)) {
             return byte[].class;
         }
-
-        return Thread.currentThread().getContextClassLoader().loadClass(name);
+        try {
+            return Thread.currentThread().getContextClassLoader().loadClass(name);
+        } catch (ClassNotFoundException e) {
+            String[] components = name.split("\\.");
+            String potentialOuter;
+            int length = components.length;
+            if (length > 2 && (potentialOuter = components[length - 2]) != null && Character.isUpperCase(potentialOuter.charAt(0))) {
+                
+                    String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1));
+                    String innerName = outerName + "$" + components[length-1];
+                    return Thread.currentThread().getContextClassLoader().loadClass(innerName);
+            } else {
+                throw e;
+            }
+        }
     }
 
     public static Class<?> tryToLoadClassWithTCCL(String fullyQualifiedName) {
         try {
             return loadClassWithTCCL(fullyQualifiedName);
         } catch (ClassNotFoundException e) {
-            
+
         }
         return null;
     }
index c67a0176d2de550ed6287607b14b546df64d71f7..a7a70c2839ca848bae7a0e45adc702c620ec4bcb 100644 (file)
@@ -14,6 +14,8 @@ import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
+import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
 import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.api.data.DataStore;
@@ -37,117 +39,34 @@ public abstract class AbstractDataServiceTest {
 
     protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
     protected DataProviderService baDataService;
-
-    /**
-     * Workaround for JUNIT sharing classloaders
-     * 
-     */
-    protected static final ClassPool POOL = new ClassPool();
-
-    protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
     protected BindingIndependentMappingService mappingService;
-    protected DataBrokerImpl baDataImpl;
-    protected org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
-    protected ListeningExecutorService executor;
-    protected BindingIndependentDataServiceConnector connectorServiceImpl;
-    protected HashMapDataStore rawDataStore;
-    protected SchemaAwareDataStoreAdapter schemaAwareDataStore;
     private DataStoreStatsWrapper dataStoreStats;
-
     protected DataStore dataStore;
+    protected BindingTestContext testContext;
 
     @Before
     public void setUp() {
-        executor = MoreExecutors.sameThreadExecutor();
-        baDataImpl = new DataBrokerImpl();
-        baDataService = baDataImpl;
-        baDataImpl.setExecutor(executor);
-
-        biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
-        biDataService = biDataImpl;
-        biDataImpl.setExecutor(executor);
-
-        rawDataStore = new HashMapDataStore();
-        schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
-        schemaAwareDataStore.changeDelegate(rawDataStore);
-        dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
-        dataStore = dataStoreStats;
-
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-                .builder().toInstance();
-        biDataImpl.registerConfigurationReader(treeRoot, dataStore);
-        biDataImpl.registerOperationalReader(treeRoot, dataStore);
-        biDataImpl.registerCommitHandler(treeRoot, dataStore);
-
-        mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
-        mappingServiceImpl.setPool(POOL);
-        mappingService = mappingServiceImpl;
-        File pathname = new File("target/gen-classes-debug");
-        // System.out.println("Generated classes are captured in " +
-        // pathname.getAbsolutePath());
-        mappingServiceImpl.start(null);
-        // mappingServiceImpl.getBinding().setClassFileCapturePath(pathname);
-
-        connectorServiceImpl = new BindingIndependentDataServiceConnector();
-        connectorServiceImpl.setBaDataService(baDataService);
-        connectorServiceImpl.setBiDataService(biDataService);
-        connectorServiceImpl.setMappingService(mappingServiceImpl);
-        connectorServiceImpl.start();
-
-        String[] yangFiles = getModelFilenames();
-        if (yangFiles != null && yangFiles.length > 0) {
-            SchemaContext context = getContext(yangFiles);
-            mappingServiceImpl.onGlobalContextUpdated(context);
-            schemaAwareDataStore.onGlobalContextUpdated(context);
-        }
+        ListeningExecutorService executor = MoreExecutors.sameThreadExecutor();
+        BindingBrokerTestFactory factory = new BindingBrokerTestFactory();
+        factory.setExecutor(executor);
+        factory.setStartWithParsedSchema(getStartWithSchema());
+        testContext = factory.getTestContext();
+        testContext.start();
+        
+        baDataService = testContext.getBindingDataBroker();
+        biDataService = testContext.getDomDataBroker();
+        dataStore = testContext.getDomDataStore();
+        mappingService = testContext.getBindingToDomMappingService();
     }
 
-    protected String[] getModelFilenames() {
-        return getAllModelFilenames();
-    }
-
-    public static String[] getAllModelFilenames() {
-        Predicate<String> predicate = new Predicate<String>() {
-            @Override
-            public boolean apply(String input) {
-                return input.endsWith(".yang");
-            }
-        };
-        Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
-        Set<String> result = reflection.getResources(predicate);
-        return (String[]) result.toArray(new String[result.size()]);
-    }
-
-    public static SchemaContext getContext(String[] yangFiles) {
-
-        ClassLoader loader = AbstractDataServiceTest.class.getClassLoader();
-
-        List<InputStream> streams = new ArrayList<>();
-        for (String string : yangFiles) {
-            InputStream stream = loader.getResourceAsStream(string);
-            streams.add(stream);
-
-        }
-        YangParserImpl parser = new YangParserImpl();
-
-        Set<Module> modules = parser.parseYangModelsFromStreams(streams);
-        return parser.resolveSchemaContext(modules);
+    protected boolean getStartWithSchema() {
+        return true;
     }
 
     @After
     public void afterTest() {
 
-        log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
-                dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
-                dataStoreStats.getConfigurationReadAverageTime());
-
-        log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
-                dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
-                dataStoreStats.getOperationalReadAverageTime());
-
-        log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
-                dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
-                dataStoreStats.getRequestCommitAverageTime());
+        testContext.logDataStoreStatistics();
 
     }
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingBrokerTestFactory.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingBrokerTestFactory.java
new file mode 100644 (file)
index 0000000..bad485e
--- /dev/null
@@ -0,0 +1,59 @@
+package org.opendaylight.controller.sal.binding.test.util;
+
+import java.util.concurrent.ExecutorService;
+
+import javassist.ClassPool;
+
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class BindingBrokerTestFactory {
+
+    private static final ClassPool CLASS_POOL = new ClassPool();
+    private boolean startWithParsedSchema = true;
+    private ExecutorService executor;
+    private ClassPool classPool;
+
+    
+    public boolean isStartWithParsedSchema() {
+        return startWithParsedSchema;
+    }
+
+    public void setStartWithParsedSchema(boolean startWithParsedSchema) {
+        this.startWithParsedSchema = startWithParsedSchema;
+    }
+
+    public ExecutorService getExecutor() {
+        return executor;
+    }
+
+    public void setExecutor(ExecutorService executor) {
+        this.executor = executor;
+    }
+
+
+    public BindingTestContext getTestContext() {
+        Preconditions.checkState(executor != null, "Executor is not set.");
+        ListeningExecutorService listenableExecutor = MoreExecutors.listeningDecorator(executor);
+        return new BindingTestContext(listenableExecutor, getClassPool(),startWithParsedSchema);
+    }
+
+    public ClassPool getClassPool() {
+        if(classPool == null) {
+            return CLASS_POOL;
+        }
+        
+        return classPool;
+    }
+
+    public void setClassPool(ClassPool classPool) {
+        this.classPool = classPool;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
new file mode 100644 (file)
index 0000000..4e611c5
--- /dev/null
@@ -0,0 +1,199 @@
+package org.opendaylight.controller.sal.binding.test.util;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javassist.ClassPool;
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicate;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import static com.google.common.base.Preconditions.*;
+
+public class BindingTestContext {
+    
+    
+    public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+            .builder().toInstance();
+
+    private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
+    
+    private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
+    private DataBrokerImpl baDataImpl;
+    private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
+    
+    private BindingIndependentDataServiceConnector connectorServiceImpl;
+    private HashMapDataStore rawDataStore;
+    private SchemaAwareDataStoreAdapter schemaAwareDataStore;
+    private DataStoreStatsWrapper dataStoreStats;
+    private DataStore dataStore;
+
+    
+    private boolean dataStoreStatisticsEnabled = false;
+    
+    private final ListeningExecutorService executor;
+    private final ClassPool classPool;
+
+    private final boolean startWithSchema;
+    
+    protected BindingTestContext(ListeningExecutorService executor, ClassPool classPool, boolean startWithSchema) {
+        this.executor = executor;
+        this.classPool = classPool;
+        this.startWithSchema = startWithSchema;
+    }
+
+    public void startDomDataStore() {
+        checkState(dataStore == null, "DataStore already started.");
+        checkState(biDataImpl != null, "Dom Data Broker not present");
+        rawDataStore = new HashMapDataStore();
+        schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
+        schemaAwareDataStore.changeDelegate(rawDataStore);
+        if(dataStoreStatisticsEnabled) {
+        dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
+        dataStore = dataStoreStats;
+        } else {
+            dataStore = schemaAwareDataStore;
+        }
+        
+        biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
+        biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
+        biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
+    }
+    
+    public void startDomDataBroker() {
+        checkState(executor != null,"Executor needs to be set");
+        biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
+        biDataImpl.setExecutor(executor);
+    }
+    
+    public void startBindingDataBroker() {
+        checkState(executor != null,"Executor needs to be set");
+        baDataImpl = new DataBrokerImpl();
+        baDataImpl.setExecutor(executor);
+    }
+    
+    public void startBindingToDomDataConnector() {
+        checkState(baDataImpl != null,"Binding Data Broker needs to be started");
+        checkState(biDataImpl != null,"DOM Data Broker needs to be started.");
+        checkState(mappingServiceImpl != null,"DOM Mapping Service needs to be started.");
+        connectorServiceImpl = new BindingIndependentDataServiceConnector();
+        connectorServiceImpl.setBaDataService(baDataImpl);
+        connectorServiceImpl.setBiDataService(biDataImpl);
+        connectorServiceImpl.setMappingService(mappingServiceImpl);
+        connectorServiceImpl.start();
+    }
+    
+    public void startBindingToDomMappingService() {
+        checkState(classPool != null,"ClassPool needs to be present");
+        mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
+        mappingServiceImpl.setPool(classPool);
+        mappingServiceImpl.start(null);
+    }
+    
+    
+    public void updateYangSchema(String[] files) {
+        SchemaContext context = getContext(files);
+        if(schemaAwareDataStore != null) {
+            schemaAwareDataStore.onGlobalContextUpdated(context);
+        }
+        if(mappingServiceImpl != null) {
+            mappingServiceImpl.onGlobalContextUpdated(context);
+        }
+    }
+    
+    
+    public static String[] getAllYangFilesOnClasspath() {
+        Predicate<String> predicate = new Predicate<String>() {
+            @Override
+            public boolean apply(String input) {
+                return input.endsWith(".yang");
+            }
+        };
+        Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
+        Set<String> result = reflection.getResources(predicate);
+        return (String[]) result.toArray(new String[result.size()]);
+    }
+    
+    private static SchemaContext getContext(String[] yangFiles) {
+        ClassLoader loader = BindingTestContext.class.getClassLoader();
+        List<InputStream> streams = new ArrayList<>();
+        for (String string : yangFiles) {
+            InputStream stream = loader.getResourceAsStream(string);
+            streams.add(stream);
+        }
+        YangParserImpl parser = new YangParserImpl();
+        Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+        return parser.resolveSchemaContext(modules);
+    }
+    
+    public void start() {
+        startBindingDataBroker();
+        startDomDataBroker();
+        startDomDataStore();
+        startBindingToDomMappingService();
+        startBindingToDomDataConnector();
+        if(startWithSchema) {
+            loadYangSchemaFromClasspath();
+        }
+    }
+
+    public void loadYangSchemaFromClasspath() {
+        String[] files = getAllYangFilesOnClasspath();
+        updateYangSchema(files);
+    }
+
+    public DataProviderService getBindingDataBroker() {
+        return baDataImpl;
+    }
+
+    public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
+        return biDataImpl;
+    }
+
+    public DataStore getDomDataStore() {
+        return dataStore;
+    }
+
+    public BindingIndependentMappingService getBindingToDomMappingService() {
+        return mappingServiceImpl;
+    }
+
+    public void logDataStoreStatistics() {
+        if(dataStoreStats == null) {
+            return;
+        }
+        
+        LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+                dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
+                dataStoreStats.getConfigurationReadAverageTime());
+
+        LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+                dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
+                dataStoreStats.getOperationalReadAverageTime());
+
+        LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+                dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
+                dataStoreStats.getRequestCommitAverageTime());
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-dom-it/pom.xml b/opendaylight/md-sal/sal-binding-dom-it/pom.xml
new file mode 100644 (file)
index 0000000..9a143d3
--- /dev/null
@@ -0,0 +1,82 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>sal-binding-dom-it</artifactId>
+    <packaging>bundle</packaging>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <configuration>
+                    <includes>org.opendaylight.controller.*</includes>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>pre-test</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>post-test</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+    <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-management</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+</project>
@@ -53,11 +53,6 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
             .toInstance();
     private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
 
-    @Override
-    protected String[] getModelFilenames() {
-        return null;
-    }
-
     /**
      * 
      * 
@@ -79,9 +74,7 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
             }
         });
         
-        SchemaContext ctx = getContext(getAllModelFilenames());
-        schemaAwareDataStore.onGlobalContextUpdated(ctx);
-        mappingServiceImpl.onGlobalContextUpdated(ctx);
+        testContext.loadYangSchemaFromClasspath();
         RpcResult<TransactionStatus> result = future.get().get();
         assertEquals(TransactionStatus.COMMITED, result.getResult());
         
@@ -95,5 +88,10 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
         return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
 
     }
+    
+    @Override
+    protected boolean getStartWithSchema() {
+        return false;
+    }
 
 }
index 27d426791f5c65f6fe01aac0a5e51fb2228b1032..6a994dbd07c6295d9284bfae5bf270523c4e8785 100644 (file)
         </pluginManagement>
     </build>
 
+
     <dependencies>
         <dependency>
             <groupId>org.opendaylight.yangtools.thirdparty</groupId>
index 4ef9d80b02c2f34a34de5f7e6360857565bb71fe..49781ce11630a7f589dda76922e1107025b9abba 100644 (file)
@@ -111,6 +111,8 @@ public class TestHelper {
 
                 systemProperty("netconf.tcp.address").value("0.0.0.0"), //
                 systemProperty("netconf.tcp.port").value("18383"), //
+                systemProperty("netconf.tcp.client.address").value("127.0.0.1"), //
+                systemProperty("netconf.tcp.client.port").value("18383"), //
                 systemProperty("netconf.config.persister.active").value("1"), //
                 systemProperty("netconf.config.persister.1.storageAdapterClass").value(
                         "org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter"), //
index da47438a6bb4a282045bb3fe44cd15863b9c3b03..32e59b869e20de484e4f1c27028698e1d8b05a49 100644 (file)
@@ -345,10 +345,19 @@ public abstract class AbstractDataTransaction<P extends Path<P>, D> extends Abst
     }\r
 \r
     override readConfigurationData(P path) {\r
+        val local = this.updatedConfigurationData.get(path);\r
+        if(local != null) {\r
+            return local;\r
+        }\r
+        \r
         return broker.readConfigurationData(path);\r
     }\r
 \r
     override readOperationalData(P path) {\r
+        val local = this.updatedOperationalData.get(path);\r
+        if(local != null) {\r
+            return local;\r
+        }\r
         return broker.readOperationalData(path);\r
     }\r
 \r
index 3e13a584d4b602a8f1a725ad06f491fb08c5897e..5e798b6720d23d73dc7da83ba5f12c491e6648ae 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-impl</artifactId>
       <version>${yang.version}</version>
+    </dependency>
+        <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-model-util</artifactId>
+      <version>${yang.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.code.gson</groupId>
index a2ae1c9f7f248e81218f9862e4247376ae47dc75..83e2d20d0e74334a8b138846e7fcd3396902c23f 100644 (file)
@@ -7,6 +7,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
 
 import com.google.common.collect.Lists;
@@ -69,7 +70,7 @@ class JsonReader {
             }
         } else if (childType.isJsonArray()) {
             if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) {
-                parent.addValue(new SimpleNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName), null));
+                parent.addValue(new EmptyNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName)));
 
             } else {
                 for (JsonElement childOfChildType : childType.getAsJsonArray()) {
index d0c007795263be5d8777ebd9af29774a8b47d0d9..fbddd05cafbaa6f5dd7808f31794cfb213a8deea 100644 (file)
@@ -25,7 +25,7 @@ import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.ResponseException;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -56,8 +56,9 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
         if (data == null) {
             throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
         }
-
-        Document domTree = NodeUtils.buildShadowDomTree(data);
+        
+        XmlMapper xmlMapper = new XmlMapper();
+        Document domTree = xmlMapper.write(data, (DataNodeContainer) t.getSchema());
         try {
             TransformerFactory tf = TransformerFactory.newInstance();
             Transformer transformer = tf.newTransformer();
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlMapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlMapper.java
new file mode 100644 (file)
index 0000000..39525f8
--- /dev/null
@@ -0,0 +1,119 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import java.util.Set;
+
+import javax.activation.UnsupportedDataTypeException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.YangNode;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class XmlMapper {
+
+    public Document write(CompositeNode data, DataNodeContainer schema) throws UnsupportedDataTypeException {
+        Preconditions.checkNotNull(data);
+        Preconditions.checkNotNull(schema);
+
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        Document doc = null;
+        try {
+            DocumentBuilder bob = dbf.newDocumentBuilder();
+            doc = bob.newDocument();
+        } catch (ParserConfigurationException e) {
+            return null;
+        }
+
+        if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
+            doc.appendChild(translateToXmlAndReturnRootElement(doc, data, schema));
+            return doc;
+        } else {
+            throw new UnsupportedDataTypeException(
+                    "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+        }
+    }
+
+    private Element translateToXmlAndReturnRootElement(Document doc, Node<?> data, YangNode schema)
+            throws UnsupportedDataTypeException {
+        QName dataType = data.getNodeType();
+        Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
+
+        if (data instanceof SimpleNode<?>) {
+            if (schema instanceof LeafListSchemaNode) {
+                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType());
+            } else if (schema instanceof LeafSchemaNode) {
+                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType());
+            } else {
+                Object value = data.getValue();
+                if (value != null) {
+                    itemEl.setTextContent(String.valueOf(value));
+                }
+            }
+        } else { // CompositeNode
+            for (Node<?> child : ((CompositeNode) data).getChildren()) {
+                DataSchemaNode childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
+                if (childSchema == null) {
+                    throw new UnsupportedDataTypeException("Probably the data node \""
+                            + child.getNodeType().getLocalName() + "\" is not conform to schema");
+                }
+                itemEl.appendChild(translateToXmlAndReturnRootElement(doc, child, childSchema));
+            }
+        }
+        return itemEl;
+    }
+
+    private void writeValueOfNodeByType(Element element, SimpleNode<?> node, TypeDefinition<?> type) {
+
+        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+
+        if (baseType instanceof IdentityrefTypeDefinition && node.getValue() instanceof QName) {
+            QName value = (QName) node.getValue();
+            element.setAttribute("xmlns:x", value.getNamespace().toString());
+            element.setTextContent("x:" + value.getLocalName());
+        } else {
+            Object value = node.getValue();
+            if (value != null) {
+                element.setTextContent(String.valueOf(value));
+            }
+        }
+    }
+
+    private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
+        for (DataSchemaNode dsn : dataSchemaNode) {
+            if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
+                return dsn;
+            } else if (dsn instanceof ChoiceNode) {
+                for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
+                    DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
+                    if (foundDsn != null) {
+                        return foundDsn;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
+        return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
+    }
+
+}
index bf7ff7d43524732f067982042fb46e19f3d35134..a53281492f23f28bd3e912c51cb8ae1ba1a752fa 100644 (file)
@@ -14,8 +14,10 @@ import javax.xml.stream.events.StartElement;
 import javax.xml.stream.events.XMLEvent;
 
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.yangtools.yang.data.api.Node;
 
 public class XmlReader {
 
@@ -121,7 +123,7 @@ public class XmlReader {
         return false;
     }
 
-    private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement)
+    private NodeWrapper<? extends Node<?>> resolveSimpleNodeFromStartElement(final StartElement startElement)
             throws XMLStreamException {
         checkArgument(startElement != null, "Start Element cannot be NULL!");
         String data = null;
@@ -141,7 +143,9 @@ public class XmlReader {
                 }
             }
         }
-
+        if(data == null) {
+            return new EmptyNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
+        }
         return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
     }
 
index fc146256e8ed7d2a0168944f3d16170fbd85bd07..0ded60dae4fc0131ad6eb9da0cef06aee6f2cdff 100644 (file)
@@ -230,5 +230,4 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
     public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
         return unwrap().entrySet();
     }
-
 }
index 470b4735a441ad7b5f3e8f421c53fea904d033d3..602e8b92425ea9d1ab26bd784893f7ff3a3a9ba1 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
 
 import static com.google.common.base.Preconditions.*
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
 
 class ControllerContext implements SchemaServiceListener {
 
@@ -288,9 +289,10 @@ class ControllerContext implements SchemaServiceListener {
     private def void addKeyValue(HashMap<QName, Object> map, DataSchemaNode node, String uriValue) {
         checkNotNull(uriValue);
         checkArgument(node instanceof LeafSchemaNode);
-        val decoded = URLDecoder.decode(uriValue);
+        val urlDecoded = URLDecoder.decode(uriValue);
+        val typedef = (node as LeafSchemaNode).type;
+        val decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded)
         map.put(node.QName, decoded);
-
     }
 
     private def String toModuleName(String str) {
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java
new file mode 100644 (file)
index 0000000..c146954
--- /dev/null
@@ -0,0 +1,111 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+
+import com.google.common.base.Preconditions;
+
+public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void> {
+    
+    private Node<?> unwrapped;
+    
+    private String localName;
+    private URI namespace;
+    private QName name;
+
+    private boolean composite;
+
+    public boolean isComposite() {
+        return composite;
+    }
+    
+    public void setComposite(boolean composite) {
+        this.composite = composite;
+    }
+    
+    public EmptyNodeWrapper(URI namespace, String localName) {
+        this.localName = Preconditions.checkNotNull(localName);
+        this.namespace = namespace;
+    }
+    
+    @Override
+    public void setQname(QName name) {
+        Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
+        this.name = name;
+    }
+    
+    @Override
+    public String getLocalName() {
+        if (unwrapped != null) {
+            return unwrapped.getNodeType().getLocalName();
+        }
+        return localName;
+    }
+    
+    @Override
+    public URI getNamespace() {
+        if (unwrapped != null) {
+            return unwrapped.getNodeType().getNamespace();
+        }
+        return namespace;
+    }
+
+    @Override
+    public void setNamespace(URI namespace) {
+        Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
+        this.namespace = namespace;
+    }
+
+    @Override
+    public Node<?> unwrap() {
+        if (unwrapped == null) {
+            if (name == null) {
+                Preconditions.checkNotNull(namespace);
+                name = new QName(namespace, localName);
+            }
+            if(composite) {
+                unwrapped = NodeFactory.createImmutableCompositeNode(name, null, Collections.<Node<?>>emptyList(),null);
+            } else {
+                unwrapped = NodeFactory.createImmutableSimpleNode(name, null, null);
+            }
+            namespace = null;
+            localName = null;
+            name = null;
+        }
+        return unwrapped;
+    }
+
+    @Override
+    public QName getNodeType() {
+        return unwrap().getNodeType();
+    }
+
+    @Override
+    public CompositeNode getParent() {
+        return unwrap().getParent();
+    }
+
+    @Override
+    public Void getValue() {
+        return null;
+    }
+
+    @Override
+    public QName getKey() {
+        return unwrap().getKey();
+    }
+
+    @Override
+    public Void setValue(Void value) {
+        return null;
+    }
+
+}
index a6a71fef55e6d3055901406734be06e05aca6c6d..35352e0819c9720d4bc23e80f30437b542351633 100644 (file)
@@ -12,6 +12,12 @@ import org.opendaylight.yangtools.yang.data.impl.NodeFactory
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
 
 class RestconfImpl implements RestconfService {
     
@@ -54,7 +60,7 @@ class RestconfImpl implements RestconfService {
 
     override createConfigurationData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
-        val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+        val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
         switch status.result {
             case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
@@ -64,7 +70,7 @@ class RestconfImpl implements RestconfService {
 
     override updateConfigurationData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
-        val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+        val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
         switch status.result {
             case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
@@ -77,7 +83,7 @@ class RestconfImpl implements RestconfService {
         if (rpc === null) {
             throw new ResponseException(Response.Status.NOT_FOUND, "RPC does not exist.");
         }
-        val value = resolveNodeNamespaceBySchema(payload, rpc.input)
+        val value = normalizeNode(payload, rpc.input)
         val List<Node<?>> input = new ArrayList
         input.add(value)
         val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
@@ -113,38 +119,69 @@ class RestconfImpl implements RestconfService {
         return identifierWithSchemaNode
     }
     
-    private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) {
+    private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) {
         if (node instanceof CompositeNodeWrapper) {
-            addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema)
+            normalizeNode(node as CompositeNodeWrapper, schema,null)
             return (node as CompositeNodeWrapper).unwrap()
         }
         return node
     }
 
-    private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
+    private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema,QName previousAugment) {
         if (schema === null) {
             throw new ResponseException(Response.Status.BAD_REQUEST,
                 "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
         }
-        val moduleName = controllerContext.findModuleByNamespace(schema.QName.namespace);
-        if (nodeBuilder.namespace === null || nodeBuilder.namespace == schema.QName.namespace ||
+        var validQName = schema.QName
+        var currentAugment = previousAugment;
+        if(schema.augmenting) {
+            currentAugment = schema.QName
+        } else if(previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
+            validQName = QName.create(currentAugment,schema.QName.localName);
+        }
+        val moduleName = controllerContext.findModuleByNamespace(validQName.namespace);
+        if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
             nodeBuilder.namespace.path == moduleName) {
-            nodeBuilder.qname = schema.QName
+            nodeBuilder.qname = validQName
         } else {
             throw new ResponseException(Response.Status.BAD_REQUEST,
                 "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
                     " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
                     nodeBuilder.localName + " should be " + moduleName + ".");
         }
+        
         if (nodeBuilder instanceof CompositeNodeWrapper) {
             val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
             for (child : children) {
-                addNamespaceToNodeFromSchemaRecursively(child,
-                    findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes))
+                normalizeNode(child,
+                    findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),currentAugment)
+            }
+        } else if (nodeBuilder instanceof SimpleNodeWrapper) {
+            val simpleNode = (nodeBuilder as SimpleNodeWrapper)
+            val stringValue = simpleNode.value as String;
+            
+            val objectValue = TypeDefinitionAwareCodec.from(schema.typeDefinition)?.deserialize(stringValue);
+            simpleNode.setValue(objectValue)
+        } else if (nodeBuilder instanceof EmptyNodeWrapper) {
+            val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
+            if(schema instanceof LeafSchemaNode) {
+                emptyNodeBuilder.setComposite(false);
+            } else if(schema instanceof ContainerSchemaNode) {
+                // FIXME: Add presence check
+                emptyNodeBuilder.setComposite(true);
             }
         }
     }
     
+    private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
+        node.type
+    }
+    
+    private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
+        node.type
+    }
+    
+    
     private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
         for (schema : schemas) {
             if (schema instanceof ChoiceNode) {
@@ -155,7 +192,11 @@ class RestconfImpl implements RestconfService {
                     }
                 }
             } else {
-                return schemas.findFirst[n|n.QName.localName.equals(localName)]
+                val result = schemas.findFirst[n|n.QName.localName.equals(localName)]
+                if(result !== null) {
+                    return result;
+                
+                }
             }
         }
         return null
index c1576895fd70bc8fc5c23a706c1fe26501af4b03..9f3c6e51e95b1c9d53a231b62b63d4072c6374cc 100644 (file)
@@ -11,16 +11,16 @@ import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
 import com.google.common.base.Preconditions;
 
-public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<String> {
+public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<Object> {
     
-    private SimpleNode<String> simpleNode;
+    private SimpleNode<?> simpleNode;
     
     private String localName;
-    private String value;
+    private Object value;
     private URI namespace;
     private QName name;
 
-    public SimpleNodeWrapper(String localName, String value) {
+    public SimpleNodeWrapper(String localName, Object value) {
         this.localName = Preconditions.checkNotNull(localName);
         this.value = value;
     }
@@ -59,7 +59,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
-    public SimpleNode<String> unwrap() {
+    public SimpleNode<Object> unwrap() {
         if (simpleNode == null) {
             if (name == null) {
                 Preconditions.checkNotNull(namespace);
@@ -72,7 +72,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
             localName = null;
             name = null;
         }
-        return simpleNode;
+        return (SimpleNode<Object>) simpleNode;
     }
 
     @Override
@@ -86,7 +86,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
-    public String getValue() {
+    public Object getValue() {
         return unwrap().getValue();
     }
 
@@ -96,7 +96,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
-    public MutableSimpleNode<String> asMutable() {
+    public MutableSimpleNode<Object> asMutable() {
         return unwrap().asMutable();
     }
 
@@ -106,9 +106,10 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
-    public String setValue(String value) {
+    public Object setValue(Object value) {
         return unwrap().setValue(value);
     }
+    
 
 
 }
index 5aa6d0339db6264e8e1c38157d118fd7dc2e8121..a72bd60d30eff23139841513505e02b5801d2ac5 100644 (file)
@@ -138,7 +138,7 @@ public class FromXmlToCompositeNodeTest {
         SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getChildren().get(0);
         assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString());
         assertEquals("lf111", cont11_lf111.getNodeType().getLocalName());
-        assertEquals("100", cont11_lf111.getValue());
+        assertEquals((short) 100, cont11_lf111.getValue());
         // :lst1_2
 
     }
@@ -251,7 +251,7 @@ public class FromXmlToCompositeNodeTest {
         SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getChildren().get(0);
         assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString());
         assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName());
-        assertEquals("100", cont1_lf11.getValue());
+        assertEquals((short) 100, cont1_lf11.getValue());
     }
 
     private CompositeNode compositeContainerFromXml(String xmlPath, boolean dummyNamespaces) {
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
new file mode 100644 (file)
index 0000000..104e52f
--- /dev/null
@@ -0,0 +1,123 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.*;
+import java.util.*;
+
+import org.junit.*;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.sal.restconf.impl.*;
+import org.opendaylight.yangtools.yang.common.*;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+public class InvokeRpcMethodTest {
+
+    private static Set<Module> modules;
+
+    private class RpcResultImpl<T> implements RpcResult<T> {
+
+        final T result;
+
+        public RpcResultImpl(T compNode) {
+            this.result = compNode;
+        }
+
+        @Override
+        public boolean isSuccessful() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        @Override
+        public T getResult() {
+            return result;
+        }
+
+        @Override
+        public Collection<RpcError> getErrors() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+    }
+
+    private class AnswerImpl implements Answer<RpcResult<CompositeNode>> {
+        @Override
+        public RpcResult<CompositeNode> answer(InvocationOnMock invocation) throws Throwable {
+            CompositeNode compNode = (CompositeNode) invocation.getArguments()[1];
+            return new RpcResultImpl<CompositeNode>(compNode);
+        }
+    }
+
+    @BeforeClass
+    public static void initialization() {
+        modules = TestUtils.resolveModules("/invoke-rpc");
+        assertEquals(1, modules.size());
+        Module module = TestUtils.resolveModule("invoke-rpc-module", modules);
+        assertNotNull(module);
+    }
+
+    /**
+     * Test method invokeRpc in RestconfImpl class tests if composite node as
+     * input parameter of method invokeRpc (second argument) is wrapped to
+     * parent composite node which has QName equals to QName of rpc (resolved
+     * from string - first argument).
+     */
+    @Test
+    public void invokeRpcMethodTest() {
+        ControllerContext contContext = ControllerContext.getInstance();
+        contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules));
+        try {
+            contContext.findModuleByNamespace(new URI("invoke:rpc:module"));
+        } catch (URISyntaxException e) {
+            assertTrue("Uri wasn't created sucessfuly", false);
+        }
+
+        BrokerFacade mockedBrokerFacade = mock(BrokerFacade.class);
+
+        RestconfImpl restconf = RestconfImpl.getInstance();
+        restconf.setBroker(mockedBrokerFacade);
+        restconf.setControllerContext(contContext);
+
+        when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenAnswer(new AnswerImpl());
+
+        StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", preparePayload());
+
+        CompositeNode rpcCompNode = structData.getData();
+        CompositeNode cont = null;
+        assertEquals("invoke:rpc:module", rpcCompNode.getNodeType().getNamespace().toString());
+        assertEquals("rpc-test", rpcCompNode.getNodeType().getLocalName());
+
+        for (Node<?> node : rpcCompNode.getChildren()) {
+            if (node.getNodeType().getLocalName().equals("cont")
+                    && node.getNodeType().getNamespace().toString().equals("nmspc")) {
+                if (node instanceof CompositeNode) {
+                    cont = (CompositeNode) node;
+                }
+            }
+        }
+        assertNotNull(cont);
+
+    }
+
+    private CompositeNode preparePayload() {
+        MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
+                TestUtils.buildQName("cont", "nmspc", "2013-12-04"), null, null, ModifyAction.CREATE, null);
+        MutableSimpleNode<?> lf = NodeFactory.createMutableSimpleNode(
+                TestUtils.buildQName("lf", "nmspc", "2013-12-04"), cont, "any value", ModifyAction.CREATE, null);
+        cont.getChildren().add(lf);
+        cont.init();
+
+        return cont;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang
new file mode 100644 (file)
index 0000000..ba06645
--- /dev/null
@@ -0,0 +1,20 @@
+module invoke-rpc-module {
+  namespace "invoke:rpc:module";  
+
+  prefix "inrpcmod";
+         
+  revision 2013-12-3 {
+  
+  }
+
+  rpc rpc-test {
+    input {
+        container cont {
+            leaf lf {
+                type string;
+            }
+        }
+    }
+  }  
+  
+}
\ No newline at end of file
index 7dda447e6ae524c60f7075cb2c470ad2155ee5b9..af56a84db5611974d0537d65b914df6acbf4adc0 100644 (file)
@@ -130,11 +130,12 @@ public class StatisticsProvider implements AutoCloseable {
             return;
 
         for (Node targetNode : targetNodes){
-            spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
+            
             
             //We need to add check, so see if groups/meters are supported
             //by the target node. Below check doesn't look good.
             if(targetNode.getId().getValue().contains("openflow:")){
+                spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
                 InstanceIdentifier<Node> targetInstanceId = InstanceIdentifier.builder(Nodes.class).child(Node.class,targetNode.getKey()).toInstance();
                 NodeRef targetNodeRef = new NodeRef(targetInstanceId);
                 
index 41ae52b3bf0ff5da3cfb3adcffb6ccfbeb4ac491..fda1e264e6babd472799340faeda579174c497b8 100644 (file)
@@ -151,6 +151,9 @@ public class ServiceProviderController {
                 systemProperty("netconf.tcp.address").value("127.0.0.1"),
                 systemProperty("netconf.tcp.port").value("8383"),
 
+                systemProperty("netconf.tcp.client.address").value("127.0.0.1"),
+                systemProperty("netconf.tcp.client.port").value("8383"),
+
                 // Set the systemPackages (used by clustering)
                 systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
 
index 5fa0b49d7b954434e88220f5378ccc89d0f51f8d..e7916c2d5f3d041ee315e03335586d533c76206e 100644 (file)
@@ -53,7 +53,7 @@ public class ConfigPersisterActivator implements BundleActivator {
         PersisterAggregator persister = PersisterAggregator.createFromProperties(propertiesProvider);
 
         InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
-                "Netconf is not configured, persister is not operational");
+                "Netconf is not configured, persister is not operational",true);
         configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(persister, address,
                 platformMBeanServer, ignoredMissingCapabilityRegex);
 
index 1d18f063bcc062ed64fb077d7cc34d07369a8d2e..b30c80b43d964426839306477a3c84a4d28084fd 100644 (file)
@@ -34,7 +34,8 @@ public class NetconfImplActivator implements BundleActivator {
 
     @Override
     public void start(final BundleContext context) throws Exception {
-        InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, "TCP is not configured, netconf not available.");
+        InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
+                "TCP is not configured, netconf not available.", false);
 
         NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
         factoriesTracker = new NetconfOperationServiceFactoryTracker(context, factoriesListener);
index 6f164f93d9c9482613a286352a6868e41cf649c3..b91824866a107ffef75290f3a52af53318dca7a5 100644 (file)
@@ -38,7 +38,8 @@ public class NetconfSSHActivator implements BundleActivator{
         logger.trace("Starting netconf SSH  bridge.");
 
         Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context,EXCEPTION_MESSAGE);
-        InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,EXCEPTION_MESSAGE);
+        InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
+                EXCEPTION_MESSAGE, true);
 
         if (sshSocketAddressOptional.isPresent()){
             server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress);
index 33ed88edf839a0d4c6a3f47793acf9baa15f4545..b9c9c174dcb3fd10a626c080cca5d75479c3bd62 100644 (file)
@@ -26,6 +26,7 @@ public class IOThread extends Thread {
     private String id;
     private ServerSession servSession;
     private ServerConnection servconnection;
+    private String customHeader;
 
 
     public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn){
@@ -36,11 +37,24 @@ public class IOThread extends Thread {
         super.setName(id);
         logger.trace("IOThread {} created", super.getName());
     }
+    public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn,String header){
+        this.inputStream = is;
+        this.outputStream = os;
+        this.servSession = ss;
+        this.servconnection = conn;
+        this.customHeader = header;
+        super.setName(id);
+        logger.trace("IOThread {} created", super.getName());
+    }
 
     @Override
     public void run() {
         logger.trace("thread {} started", super.getName());
         try {
+            if (this.customHeader!=null && !this.customHeader.equals("")){
+                this.outputStream.write(this.customHeader.getBytes());
+                logger.trace("adding  {} header", this.customHeader);
+            }
             IOUtils.copy(this.inputStream, this.outputStream);
         } catch (Exception e) {
             logger.error("inputstream -> outputstream copy error ",e);
index 95fdd48bfe31d6e83b1082eefedbfe7da06842a5..15d99a44ee4db4a7b31bd0ee2fd6abd25476079c 100644 (file)
@@ -28,6 +28,8 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
     private static final Logger logger =  LoggerFactory.getLogger(SocketThread.class);
     private ServerConnection conn = null;
     private long sessionId;
+    private String currentUser;
+    private final String remoteAddressWithPort;
 
 
     public static void start(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException{
@@ -40,6 +42,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
         this.socket = socket;
         this.clientAddress = clientAddress;
         this.sessionId = sessionId;
+        this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/","");
 
     }
 
@@ -81,7 +84,8 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
                                 netconf_ssh_input.start();
 
                                 logger.trace("starting netconf_ssh_output thread");
-                                netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn);
+                                final String customHeader = "["+currentUser+";"+remoteAddressWithPort+";ssh;;;;;;]\n";
+                                netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn,customHeader);
                                 netconf_ssh_output.setDaemon(false);
                                 netconf_ssh_output.start();
 
@@ -146,7 +150,8 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
 
     public String initAuthentication(ServerConnection sc)
     {
-        return "";
+        logger.trace("Established connection with host {}",remoteAddressWithPort);
+        return "Established connection with host "+remoteAddressWithPort+"\r\n";
     }
 
     public String[] getRemainingAuthMethods(ServerConnection sc)
@@ -161,8 +166,12 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
 
     public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
     {
-        if (USER.equals(username) && PASSWORD.equals(password))
+        if (USER.equals(username) && PASSWORD.equals(password)){
+            currentUser = username;
+            logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
             return AuthenticationResult.SUCCESS;
+        }
+
 
         return AuthenticationResult.FAILURE;
     }
index b1d902d6341f83415b8be25509bc6e1dc27000c2..987708d67ed03db1276a6459ad47c75f7eabf0bf 100644 (file)
@@ -8,12 +8,12 @@
 
 package org.opendaylight.controller.netconf.util.osgi;
 
-import com.google.common.base.Optional;
-import java.net.InetSocketAddress;
-import org.osgi.framework.BundleContext;
-import static com.google.common.base.Preconditions.checkNotNull;
+        import com.google.common.base.Optional;
+        import java.net.InetSocketAddress;
+        import org.osgi.framework.BundleContext;
+        import static com.google.common.base.Preconditions.checkNotNull;
 
-    public class NetconfConfigUtil {
+public class NetconfConfigUtil {
     private static final String PREFIX_PROP = "netconf.";
 
     private enum InfixProp {
@@ -22,10 +22,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
     private static final String PORT_SUFFIX_PROP = ".port";
     private static final String ADDRESS_SUFFIX_PROP = ".address";
+    private static final String CLIENT_PROP = ".client";
 
-    public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound) {
+    public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound, boolean forClient) {
 
-        Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound);
+        Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient);
 
         if (inetSocketAddressOptional.isPresent() == false) {
             throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
@@ -34,7 +35,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
     }
 
     public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context, String exceptionMessage) {
-        return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage);
+        return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage, false);
     }
 
     /**
@@ -47,14 +48,28 @@ import static com.google.common.base.Preconditions.checkNotNull;
      *             if address or port are invalid, or configuration is missing
      */
     private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
-            InfixProp infixProp, String exceptionMessage) {
-        String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
-        if (address == null) {
+                                                                         InfixProp infixProp,
+                                                                         String exceptionMessage,
+                                                                         boolean client) {
+        String address = "";
+        if (client) {
+            address = context.getProperty(PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP);
+        }
+        if (address == null || address.equals("")){
+            address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
+        }
+        if (address == null || address.equals("")) {
             throw new IllegalStateException("Cannot find initial netconf configuration for parameter    "
                     +PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP
                     +" in config.ini. "+exceptionMessage);
         }
-        String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
+        String portKey = "";
+        if (client) {
+            portKey = PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP;
+        }
+        if (portKey == null || portKey.equals("")){
+            portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
+        }
         String portString = context.getProperty(portKey);
         checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
         try {
index af2c18a217a676c142c73040e29fe52aab80b586..1b81ccb450f71a9050739830c3e57758e0a43fc4 100644 (file)
@@ -88,7 +88,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.enunciate</groupId>
index 4e1de914f7677e649f291a86d1dea69b368bddba..793af2f5d779379f1f92227c80d584b231a6b361 100644 (file)
@@ -49,7 +49,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>switchmanager</artifactId>
-      <version>0.6.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 05cb500273c2bca5c2012b251ebea9db02344ebe..5338849a62626ed740c6d930d72064efa1dca4d2 100644 (file)
@@ -844,7 +844,8 @@ public class StatisticsNorthbound {
      *                     },
      *                     "activeCount": "11",
      *                     "lookupCount": "816",
-     *                     "matchedCount": "220"
+     *                     "matchedCount": "220",
+     *                     "maximumEntries": "1000"
      *                 },
      *                 {
      *                     ...another table
@@ -876,6 +877,7 @@ public class StatisticsNorthbound {
      *          &lt;activeCount&gt;12&lt;/activeCount&gt;
      *          &lt;lookupCount&gt;10935&lt;/lookupCount&gt;
      *          &lt;matchedCount&gt;10084&lt;/matchedCount&gt;
+     *          &lt;maximumEntries&gt;1000&lt;/maximumEntries&gt;
      *      &lt;/tableStatistic&gt;
      *      &lt;tableStatistic&gt;
      *          &lt;nodeTable&gt;
@@ -888,6 +890,7 @@ public class StatisticsNorthbound {
      *          &lt;activeCount&gt;0&lt;/activeCount&gt;
      *          &lt;lookupCount&gt;0&lt;/lookupCount&gt;
      *          &lt;matchedCount&gt;0&lt;/matchedCount&gt;
+     *          &lt;maximumEntries&gt;0&lt;/maximumEntries&gt;
      *      &lt;/tableStatistic&gt;
      *      &lt;tableStatistic&gt;
      *          &lt;nodeTable&gt;
@@ -900,6 +903,7 @@ public class StatisticsNorthbound {
      *          &lt;activeCount&gt;0&lt;/activeCount&gt;
      *          &lt;lookupCount&gt;0&lt;/lookupCount&gt;
      *          &lt;matchedCount&gt;0&lt;/matchedCount&gt;
+     *          &lt;maximumEntries&gt;0&lt;/maximumEntries&gt;
      *      &lt;/tableStatistic&gt;
      *  &lt;/tableStatistics&gt;
      *  &lt;tableStatistics&gt;
@@ -987,7 +991,8 @@ public class StatisticsNorthbound {
      *             },
      *             "activeCount": "12",
      *             "lookupCount": "11382",
-     *             "matchedCount": "10524"
+     *             "matchedCount": "10524",
+     *             "maximumEntries": "1000"
      *         },
      *         {
      *             "nodeTable": {
@@ -999,7 +1004,8 @@ public class StatisticsNorthbound {
      *             },
      *             "activeCount": "0",
      *             "lookupCount": "0",
-     *             "matchedCount": "0"
+     *             "matchedCount": "0",
+     *             "maximumEntries": "0"
      *         }
      *    ]
      * }
@@ -1022,6 +1028,7 @@ public class StatisticsNorthbound {
      *         &lt;activeCount&gt;12&lt;/activeCount&gt;
      *         &lt;lookupCount&gt;10935&lt;/lookupCount&gt;
      *         &lt;matchedCount&gt;10084&lt;/matchedCount&gt;
+     *         &lt;maximumEntries&gt;1000&lt;/maximumEntries&gt;
      *     &lt;/tableStatistic&gt;
      *     &lt;tableStatistic&gt;
      *         &lt;nodeTable&gt;
@@ -1034,6 +1041,7 @@ public class StatisticsNorthbound {
      *         &lt;activeCount&gt;0&lt;/activeCount&gt;
      *         &lt;lookupCount&gt;0&lt;/lookupCount&gt;
      *         &lt;matchedCount&gt;0&lt;/matchedCount&gt;
+     *         &lt;maximumEntries&gt;0&lt;/maximumEntries&gt;
      *     &lt;/tableStatistic&gt;
      *     &lt;tableStatistic&gt;
      *         &lt;nodeTable&gt;
@@ -1046,6 +1054,7 @@ public class StatisticsNorthbound {
      *         &lt;activeCount&gt;0&lt;/activeCount&gt;
      *         &lt;lookupCount&gt;0&lt;/lookupCount&gt;
      *         &lt;matchedCount&gt;0&lt;/matchedCount&gt;
+     *         &lt;maximumEntries&gt;0&lt;/maximumEntries&gt;
      *     &lt;/tableStatistic&gt;
      * &lt;/nodeTableStatistics&gt;
      *
index ca0ff45d61e4977ed677f761d93c73c86262482e..ceeb29a1fcffa095f7b4ae089660176665a29ebd 100644 (file)
@@ -70,7 +70,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.6.0-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 8fa4941b88771c94dbf3b578a3f89717339f899e..361f977b2c2c547697b46c6cf8b76d18dbd1bafd 100644 (file)
@@ -57,6 +57,7 @@ import org.openflow.protocol.action.OFAction;
 import org.openflow.protocol.action.OFActionDataLayer;
 import org.openflow.protocol.action.OFActionDataLayerDestination;
 import org.openflow.protocol.action.OFActionDataLayerSource;
+import org.openflow.protocol.action.OFActionEnqueue;
 import org.openflow.protocol.action.OFActionNetworkLayerAddress;
 import org.openflow.protocol.action.OFActionNetworkLayerDestination;
 import org.openflow.protocol.action.OFActionNetworkLayerSource;
@@ -280,6 +281,15 @@ public class FlowConverter {
                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
                     continue;
                 }
+                if (action.getType() == ActionType.ENQUEUE) {
+                    Enqueue a = (Enqueue) action;
+                    OFActionEnqueue ofAction = new OFActionEnqueue();
+                    ofAction.setPort(PortConverter.toOFPort(a.getPort()));
+                    ofAction.setQueueId(a.getQueue());
+                    actionsList.add(ofAction);
+                    actionsLength += OFActionEnqueue.MINIMUM_LENGTH;
+                    continue;
+                }
                 if (action.getType() == ActionType.DROP) {
                     continue;
                 }
@@ -683,6 +693,10 @@ public class FlowConverter {
                                     NodeConnectorCreator.createOFNodeConnector(
                                             ofPort, node));
                         }
+                    } else if (ofAction instanceof OFActionEnqueue) {
+                        salAction = new Enqueue(NodeConnectorCreator.createOFNodeConnector(
+                                ((OFActionEnqueue) ofAction).getPort(), node),
+                                ((OFActionEnqueue) ofAction).getQueueId());
                     } else if (ofAction instanceof OFActionVirtualLanIdentifier) {
                         salAction = new SetVlanId(
                                 ((OFActionVirtualLanIdentifier) ofAction)
index f983e1244dba519f7a2afc0c6d13f8937f1178bc..39bbecf0214f5443e1991ba359a679bbc6cba183 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.protocol_plugin.openflow.internal;
 
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -138,6 +139,12 @@ public class InventoryService implements IInventoryShimInternalListener,
         return nodeProps;
     }
 
+    // nothing to return
+    @Override
+    public Set<Node> getConfiguredNotConnectedNodes() {
+        return Collections.emptySet();
+    }
+
     @Override
     public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps(
             Boolean refresh) {
index bcc2445808a677573892b299b16a3a2d6a5beed8..35a763869b20f2e73c2c773d748930970212820c 100644 (file)
@@ -54,6 +54,7 @@ public class TableStatisticsConverter {
                 ntStat.setActiveCount(ofTableStat.getActiveCount());
                 ntStat.setLookupCount(ofTableStat.getLookupCount());
                 ntStat.setMatchedCount(ofTableStat.getMatchedCount());
+                ntStat.setMaximumEntries(ofTableStat.getMaximumEntries());
                 this.ntStatsList.add(ntStat);
             }
         }
index 60e17e264e4d47b1c6505ef5b5aecdf7bee67ffa..405f92455410a982008af2c9c4c1ff66e7549210 100644 (file)
@@ -16,7 +16,7 @@
   </scm>
 
   <artifactId>sal</artifactId>
-  <version>0.6.0-SNAPSHOT</version>
+  <version>0.7.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
   <build>
index b3891c8337b1f2bba4012f378a65f6d3e5e5c7ca..c711e67f9ee33d91831194f05837094c8552de4e 100644 (file)
@@ -21,6 +21,8 @@ public class Enqueue extends Action {
     private static final long serialVersionUID = 1L;
     @XmlElement
     private NodeConnector port;
+    @XmlElement
+    private int queue;
 
     /* Dummy constructor for JAXB */
     @SuppressWarnings("unused")
@@ -30,9 +32,25 @@ public class Enqueue extends Action {
     public Enqueue(NodeConnector port) {
         type = ActionType.ENQUEUE;
         this.port = port;
+        this.queue = 0;
+    }
+
+    public Enqueue(NodeConnector port, int queue) {
+        type = ActionType.ENQUEUE;
+        this.port = port;
+        this.queue = queue;
     }
 
     public NodeConnector getPort() {
         return port;
     }
+
+    public int getQueue() {
+        return queue;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s[%s:%s]", type, port, queue);
+    }
 }
index 3c58ecbfcdc04ee4e7bca4b6a375fd956b3d45a4..fa3afd817301e46a2c5753cfcb8afb3d74c8036b 100644 (file)
@@ -10,6 +10,7 @@
 package org.opendaylight.controller.sal.inventory;
 
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.sal.core.Node;
@@ -28,6 +29,13 @@ public interface IInventoryService {
      */
     public ConcurrentMap<Node, Map<String, Property>> getNodeProps();
 
+    /**
+     * The method retrieves all the configured nodes that are not connected to
+     * the controller
+     *
+     * @return Set of {@link org.opendaylight.controller.sal.core.Node}
+     */
+    public Set<Node> getConfiguredNotConnectedNodes();
     /**
      * The method retrieve all the existing nodeConnectors and their properties
      *
index 5822731f26babd33bea1ea18d108fcf5be0a6f4c..4007dc86e78974d7d36dc7540b4a3fc044d48fdc 100644 (file)
@@ -10,6 +10,7 @@
 package org.opendaylight.controller.sal.inventory;
 
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.sal.core.Node;
@@ -36,4 +37,12 @@ public interface IPluginInInventoryService {
      */
     public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps(
             Boolean refresh);
+
+    /**
+     * The method retrieves all the configured nodes that are not connected to
+     * the controller
+     *
+     * @return Set of {@link org.opendaylight.controller.sal.core.Node}
+     */
+    public Set<Node> getConfiguredNotConnectedNodes();
 }
index 7c404178cfc195edd206500c90ba4155c7e02f73..eb33ad67995f2621fd95024c0736e897fb6f18ee 100644 (file)
@@ -37,6 +37,8 @@ public class NodeTableStatistics implements Serializable {
     private long lookupCount;
     @XmlElement
     private long matchedCount;
+    @XmlElement
+    private int maximumEntries;
 
 
     @Override
@@ -164,6 +166,20 @@ public class NodeTableStatistics implements Serializable {
         this.matchedCount = matchedCount;
     }
 
+    /**
+     * @return the maximumEntries
+     */
+    public long getMaximumEntries() {
+        return maximumEntries;
+    }
+
+    /**
+     * @param maximumEntries the maximumEntries to set
+     */
+    public void setMaximumEntries(int maximumEntries) {
+        this.maximumEntries = maximumEntries;
+    }
+
     @Override
     public String toString() {
         return "NodeTableStats[tableId = " + nodeTable
index cbf3f95b2a776dc616ebd8606697b7b46aa06f2d..da4cd5388380f81f69fd9dc9a431da61093a67a6 100644 (file)
@@ -40,7 +40,7 @@ public abstract class NodeConnectorCreator {
         if (node.getType().equals(NodeIDType.OPENFLOW)) {
             try {
                 return new NodeConnector(NodeConnectorIDType.OPENFLOW,
-                        (Short) portId, node);
+                        portId, node);
             } catch (ConstructionException e1) {
                 logger.error("",e1);
                 return null;
@@ -49,6 +49,18 @@ public abstract class NodeConnectorCreator {
         return null;
     }
 
+    /**
+     * Generic NodeConnector creator
+     * The nodeConnector type is inferred from the node type
+     *
+     * @param portId The string representing the port id
+     * @param node The network node as {@link org.opendaylight.controller.sal.core.Node Node} object
+     * @return The corresponding {@link org.opendaylight.controller.sal.core.NodeConnector NodeConnector} object
+     */
+    public static NodeConnector createNodeConnector(String portId, Node node) {
+        return NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), portId, node.toString()));
+    }
+
     /**
      * NodeConnector creator where NodeConnector type can be specified
      * Needed to create special internal node connectors (like software stack)
index 00ac84fcc1ef54ee515ac4421bba972e13c0ea56..0387f72f382da08bc1ec395e73158d11545e253c 100644 (file)
@@ -101,7 +101,7 @@ public class Status implements Serializable {
      * @return true if the Status code is {@code StatusCode.SUCCESS}
      */
     public boolean isSuccess() {
-        return code == StatusCode.SUCCESS;
+        return code == StatusCode.SUCCESS || code == StatusCode.CREATED;
     }
 
     /**
@@ -130,15 +130,19 @@ public class Status implements Serializable {
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
+        if (this == obj) {
             return true;
-        if (obj == null)
+        }
+        if (obj == null) {
             return false;
-        if (getClass() != obj.getClass())
+        }
+        if (getClass() != obj.getClass()) {
             return false;
+        }
         Status other = (Status) obj;
-        if (code != other.code)
+        if (code != other.code) {
             return false;
+        }
         return true;
     }
 }
index 86b0d53fba70a797dac4059102f007a1d4805137..f8882bbd2f81663023c95dd2b8b980d2e9754687 100644 (file)
@@ -15,6 +15,7 @@ package org.opendaylight.controller.sal.utils;
  */
 public enum StatusCode {
         SUCCESS("Success"),
+        CREATED("Created"),
 
         BADREQUEST("Bad Request"),
         UNAUTHORIZED("UnAuthorized"),
index c0d6bb698a7b0cf9112bcfa51b8e95ce2e20cf5b..a29d4268dab2c02f55006ff948a1735ee65125ea 100644 (file)
@@ -24,12 +24,14 @@ public class NodeTableStatisticsTest {
         ntStats.setActiveCount(100);
         ntStats.setLookupCount(200);
         ntStats.setMatchedCount(500);
+        ntStats.setMaximumEntries(1000);
         ntStats.setName("Test");
 
         Assert.assertTrue(ntStats.getNodeTable().equals(nt));
         Assert.assertTrue(ntStats.getActiveCount() == 100);
         Assert.assertTrue(ntStats.getLookupCount() == 200);
         Assert.assertTrue(ntStats.getMatchedCount() == 500);
+        Assert.assertTrue(ntStats.getMaximumEntries() == 1000);
         Assert.assertTrue(ntStats.getName().equals("Test"));
     }
 }
index f260f315e082368066413f35a1704db205ad889e..7c92a6b52b3151d528d8b6d39a407ff8bad19098 100644 (file)
@@ -59,7 +59,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
index 1cc57bac66e797cead08f0e2300b325f3622afe1..fbb9fbc518f74c64611a39e536157b30b4dab789 100644 (file)
@@ -9,6 +9,7 @@
 
 package org.opendaylight.controller.sal.implementation.internal;
 
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -145,6 +146,18 @@ public class Inventory implements IPluginOutInventoryService, IInventoryService
         return nodeProps;
     }
 
+    @Override
+    public Set<Node> getConfiguredNotConnectedNodes() {
+        Set<Node> configuredNotConnected = new HashSet<Node>(), rv;
+        for (IPluginInInventoryService s : this.pluginService) {
+            rv = s.getConfiguredNotConnectedNodes();
+            if (rv != null) {
+                configuredNotConnected.addAll(rv);
+            }
+        }
+        return configuredNotConnected;
+    }
+
     @Override
     public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps() {
         ConcurrentMap<NodeConnector, Map<String, Property>> ncProps =
index 043fdc08c1858153a16fbd0bfe49f9337888ac98..a34cbb5db80f8f7232bf8dac7c2c41e7aba42c01 100644 (file)
@@ -634,7 +634,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify,
                 po = e.getValue();
                 if (po != null) {
                     // Populate the Policy field now
-                    Status poStatus = this.frm.installFlowEntry(po);
+                    Status poStatus = this.frm.modifyOrAddFlowEntry(po);
                     if (!poStatus.isSuccess()) {
                         log.error("Failed to install policy: "
                                 + po.getGroupName() + " ("
@@ -842,8 +842,9 @@ public class SimpleForwardingImpl implements IfNewHostNotify,
     @Override
     public void notifyNode(Node node, UpdateType type,
             Map<String, Property> propMap) {
-        if (node == null)
+        if (node == null) {
             return;
+        }
 
         switch (type) {
         case REMOVED:
@@ -858,8 +859,9 @@ public class SimpleForwardingImpl implements IfNewHostNotify,
     @Override
     public void notifyNodeConnector(NodeConnector nodeConnector,
             UpdateType type, Map<String, Property> propMap) {
-        if (nodeConnector == null)
+        if (nodeConnector == null) {
             return;
+        }
 
         boolean up = false;
         switch (type) {
index a3ecf526c0748bfd274f39ff9161089d1ba3389b..d04371461f371e1e11ba0254a57fb92763f793c3 100644 (file)
@@ -25,7 +25,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
      <dependency>
       <groupId>org.opendaylight.controller</groupId>
@@ -75,7 +75,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>switchmanager</artifactId>
-      <version>0.6.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
 
       <dependency>
index cf4c5149657d453bcff2a72c06cdf383f1841e0f..b9cac8f2f86ac286f07bebeea3982e3aa75c5ec4 100644 (file)
@@ -16,7 +16,7 @@
   </scm>
 
   <artifactId>switchmanager</artifactId>
-  <version>0.6.1-SNAPSHOT</version>
+  <version>0.7.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
   <properties>
index 8815e5e8c08a1b2f52ddabdcf9c6a28363b79419..072544c2146f9edd31a7b3bdf9458378290064d9 100644 (file)
@@ -66,6 +66,13 @@ public interface ISwitchManager {
      */
     public List<Switch> getNetworkDevices();
 
+    /**
+     * Return a Set of all configured devices that are not connected to the controller
+     *
+     * @return Set of {@link org.opendaylight.controller.switchmanager.Switch}
+     */
+    public Set<Switch> getConfiguredNotConnectedSwitches();
+
     /**
      * Return a list of subnet that were previously configured
      *
index 1e78ec7a3df60a545b6ff6c89d0e15567d44f359..76bfd56c2913cf9f89625e3db71fcf2cc9cc9e48 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>switchmanager</artifactId>
-      <version>0.6.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 4d2aea203601dafe6e19fcacc208ae4760819b0f..4950cae33a9fc37813afb963250e31a5ff71e824 100644 (file)
@@ -2155,4 +2155,25 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
         return (desc == null /* || desc.getValue().equalsIgnoreCase("none") */) ? ""
                 : desc.getValue();
     }
+
+    @Override
+    public Set<Switch> getConfiguredNotConnectedSwitches() {
+        Set<Switch> configuredNotConnectedSwitches = new HashSet<Switch>();
+        if (this.inventoryService == null) {
+            log.trace("inventory service not avaiable");
+            return configuredNotConnectedSwitches;
+        }
+
+        Set<Node> configuredNotConnectedNodes = this.inventoryService.getConfiguredNotConnectedNodes();
+        if (configuredNotConnectedNodes != null) {
+            for (Node node : configuredNotConnectedNodes) {
+                Switch sw = getSwitchByNode(node);
+                if (sw != null) {
+                    configuredNotConnectedSwitches.add(sw);
+                }
+            }
+        }
+        return configuredNotConnectedSwitches;
+    }
+
 }
index c06efb91b88f4b730fb86e7e256fe3e0fac7f688..24788771bf58d34aea44bb6fe3b577eec00b6d85 100644 (file)
@@ -21,7 +21,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>switchmanager</artifactId>
-      <version>0.6.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
       <dependency>
       <groupId>org.opendaylight.controller</groupId>
@@ -31,7 +31,7 @@
      <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.7.0-SNAPSHOT</version>
     </dependency>
      <dependency>
       <groupId>org.opendaylight.controller</groupId>