Merge "Bug 1367 - Fix NPE in cors filter"
authorTony Tkacik <ttkacik@cisco.com>
Thu, 17 Jul 2014 08:30:08 +0000 (08:30 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 17 Jul 2014 08:30:08 +0000 (08:30 +0000)
69 files changed:
features/base/src/main/resources/features.xml
features/config/pom.xml [moved from opendaylight/config/feature/pom.xml with 97% similarity]
features/config/src/main/resources/features.xml [new file with mode: 0644]
features/mdsal/pom.xml [moved from opendaylight/md-sal/feature/pom.xml with 97% similarity]
features/mdsal/src/main/resources/features.xml [moved from opendaylight/md-sal/feature/src/main/resources/features.xml with 56% similarity]
features/netconf/pom.xml [new file with mode: 0644]
features/netconf/src/main/resources/features.xml [new file with mode: 0644]
features/pom.xml [new file with mode: 0644]
features/protocol-framework/pom.xml [new file with mode: 0644]
features/protocol-framework/src/main/resources/features.xml [new file with mode: 0644]
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/feature/src/main/resources/features.xml [deleted file]
opendaylight/config/pom.xml
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java
opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory.yang
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingToDomCommitHandler.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingToDomTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingCommitHandler.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingNotificationForwarder.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingRpcForwarder.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingRpcForwardingManager.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategy.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java [deleted file]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategyTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/TwoPhaseCommit.java
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/CommitHandlerTransactions.java
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/RpcErrors.java
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMDataCommitCoordinatorImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/GlobalRpcRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcRegImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/broker/spi/rpc/RpcRoutingStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicator.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceCommitHandler.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceRpc.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceSalProvider.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceTwoPhaseCommitTransaction.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/util/FailedRpcResult.java [deleted file]
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToRpcRequestTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/rpc-notification-subscription.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfErrorTest.java
opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-routed-rpc.yang [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/sample/toaster/provider/OpendaylightToaster.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/AbstractNetconfSessionNegotiator.java
pom.xml

index 60286175c18e0a6455dedcc19f23018216b406dd..b9107b9f62881d1fc2799ddbecc238559add943a 100644 (file)
@@ -79,6 +79,8 @@
    <feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
       <bundle start="true" start-level="35">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
       <bundle start="true" start-level="35">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
+      <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0</bundle>
+      <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
    </feature>
    <feature name="base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
       <feature>http</feature>
similarity index 97%
rename from opendaylight/config/feature/pom.xml
rename to features/config/pom.xml
index aaf33ccc0fdfb64639ef6feb2c15256443dbca56..01a4ea74a264afcf722d10b6515b5b26313e869c 100644 (file)
@@ -5,6 +5,7 @@
     <groupId>org.opendaylight.controller</groupId>
     <artifactId>config-subsystem</artifactId>
     <version>0.2.5-SNAPSHOT</version>
+    <relativePath>../../opendaylight/config/</relativePath>
   </parent>
   <artifactId>config-features</artifactId>
 
diff --git a/features/config/src/main/resources/features.xml b/features/config/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..7c11b5b
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-config-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/netconf-features/${netconf.version}/xml/features</repository>
+
+  <feature name='odl-config-startup' version='${project.version}'>
+    <feature version='${project.version}'>odl-config-netconf-connector</feature>
+    <feature version='${project.version}'>odl-config-persister</feature>
+    <feature version='${project.version}'>odl-netconf-impl</feature>
+  </feature>
+
+  <feature name='odl-config-core' version='${project.version}'>
+    <feature version='${yangtools.version}'>yangtools-concepts</feature>
+    <feature version='${yangtools.version}'>yangtools-binding</feature>
+    <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
+    <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
+    <feature version='${project.version}'>odl-config-api</feature>
+    <bundle>mvn:org.opendaylight.controller/config-util/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/yang-jmx-generator/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/shutdown-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/shutdown-impl/${project.version}</bundle>
+    <bundle>mvn:org.osgi/org.osgi.core/${osgi.core.version}</bundle>
+    <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
+    <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
+  </feature>
+  <feature name='odl-config-manager' version='${project.version}'>
+    <feature version='${project.version}'>odl-config-core</feature>
+    <bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
+  </feature>
+  <feature name='odl-config-persister' version='${project.version}'>
+    <feature version='${netconf.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-config-api</feature>
+    <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
+    <bundle>mvn:org.opendaylight.controller/config-persister-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/config-persister-impl/${project.version}</bundle>
+
+    <bundle>mvn:org.opendaylight.controller/netconf-util/${netconf.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${netconf.version}</bundle>
+
+    <bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
+    <bundle>mvn:commons-io/commons-io/${commons.io.version}</bundle>
+    <bundle>mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
+    <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version}</bundle>
+    <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version}</bundle>
+  </feature>
+  <feature name='odl-config-api' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
+
+    <!-- yangtools features -->
+    <feature version='${yangtools.version}'>yangtools-concepts</feature>
+    <feature version='${yangtools.version}'>yangtools-binding</feature>
+  </feature>
+
+  <feature name='odl-config-netty-config-api' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netty-config-api/${project.version}</bundle>
+
+    <!-- netty bundles -->
+    <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-common/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
+
+    <feature version='${project.version}'>odl-config-api</feature>
+  </feature>
+  <feature name='odl-config-netty' version='${project.version}'>
+    <feature version='${project.version}'>odl-config-netty-config-api</feature>
+    <bundle>mvn:org.opendaylight.controller/netty-event-executor-config/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netty-threadgroup-config/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netty-timer-config/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/threadpool-config-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/threadpool-config-impl/${project.version}</bundle>
+    <feature version='${project.version}'>odl-config-startup</feature>
+  </feature>
+  <feature name='odl-config-dispatcher' version='${project.version}'>
+      <bundle>mvn:org.opendaylight.controller/netconf-config-dispatcher/${project.version}</bundle>
+  </feature>
+
+</features>
\ No newline at end of file
similarity index 97%
rename from opendaylight/md-sal/feature/pom.xml
rename to features/mdsal/pom.xml
index c08c3e5606023bcc9cbd4c6780287135a7dd32ab..2983c5efab8fb21031991fe6af248032eb842365 100644 (file)
@@ -5,6 +5,7 @@
     <groupId>org.opendaylight.controller</groupId>
     <artifactId>sal-parent</artifactId>
     <version>1.1-SNAPSHOT</version>
+    <relativePath>../../opendaylight/md-sal</relativePath>
   </parent>
   <artifactId>mdsal-features</artifactId>
 
similarity index 56%
rename from opendaylight/md-sal/feature/src/main/resources/features.xml
rename to features/mdsal/src/main/resources/features.xml
index 16b457403740b7cac4f3fc137e1a1a9d00db4521..7d393bc64cdc7aab9056043d8b1f852260dcfe27 100644 (file)
@@ -9,20 +9,20 @@
         <feature version='${project.version}'>odl-mdsal-restconf</feature>
     </feature>
     <feature name='odl-mdsal-commons' version='${project.version}'>
-        <feature version='${yangtools.version}'>yangtools-concepts</feature>
-        <feature version='${yangtools.version}'>yangtools-binding</feature>
+        <feature version='${yangtools.version}'>yangtools-data-binding</feature>
         <bundle>mvn:org.opendaylight.controller/sal-common/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-common-api/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-common-impl/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-common-util/${project.version}</bundle>
-        <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
-        <bundle>wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version}</bundle>
     </feature>
     <feature name='odl-mdsal-broker' version='${project.version}'>
         <feature version='${yangtools.version}'>yangtools-concepts</feature>
         <feature version='${yangtools.version}'>yangtools-binding</feature>
         <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
-        <feature version='${config.version}'>odl-config-subsystem</feature>
+        <feature version='${config.version}'>odl-config-core</feature>
+        <feature version='${config.version}'>odl-config-manager</feature>
+        <feature version='${config.version}'>odl-config-api</feature>
+        <feature version='${config.version}'>odl-config-persister</feature>
         <bundle>mvn:org.opendaylight.controller/sal-core-api/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-core-spi/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-broker-impl/${project.version}</bundle>
@@ -31,6 +31,7 @@
         <bundle>mvn:org.opendaylight.controller/sal-binding-broker-impl/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-binding-util/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-connector-api/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/sal-inmemory-datastore/${project.version}</bundle>
     </feature>
     <feature name='odl-mdsal-restconf' version='${project.version}'>
         <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
         <bundle>wrap:mvn:io.netty/netty-handler/${netty.version}</bundle>
         <bundle>wrap:mvn:io.netty/netty-transport/${netty.version}</bundle>
     </feature>
+    <feature name='odl-mdsal-model' version='${project.version}'>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-base/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-management/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-service/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-statistics/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-inventory/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-topology/${project.version}</bundle>
+    </feature>
+    <feature name='odl-mdsal-toaster' version='${project.version}'>
+        <feature version='${yangtools.version}'>yangtools-concepts</feature>
+        <feature version='${yangtools.version}'>yangtools-binding</feature>
+        <feature version='${project.version}'>odl-mdsal-broker</feature>
+        <feature version='${project.version}'>odl-mdsal-all</feature>
+        <bundle>mvn:org.opendaylight.controller.samples/sample-toaster/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.samples/sample-toaster-consumer/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.samples/sample-toaster-provider/${project.version}</bundle>
+    </feature>
+    <feature name='odl-mdsal-misc' version='${project.version}'>
+        <bundle>mvn:org.opendaylight.controller/sal-netconf-connector/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/sal-restconf-broker/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/sal-remote/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/topology-manager/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/topology-lldp-discovery/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/statistics-manager/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/inventory-manager/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/forwardingrules-manager/${project.version}</bundle>
+    </feature>
+
 </features>
diff --git a/features/netconf/pom.xml b/features/netconf/pom.xml
new file mode 100644 (file)
index 0000000..457fc64
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>netconf-subsystem</artifactId>
+    <version>0.2.5-SNAPSHOT</version>
+    <relativePath>../../opendaylight/netconf</relativePath>
+  </parent>
+  <artifactId>netconf-features</artifactId>
+
+  <packaging>pom</packaging>
+
+  <properties>
+    <features.file>features.xml</features.file>
+  </properties>
+
+  <dependencies></dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>filter</id>
+            <goals>
+              <goal>resources</goal>
+            </goals>
+            <phase>generate-resources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/${features.file}</file>
+                  <type>xml</type>
+                  <classifier>features</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+  </scm>
+</project>
diff --git a/features/netconf/src/main/resources/features.xml b/features/netconf/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..50a537b
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-netconf-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.controller/features-odl-protocol-framework/${protocol-framework.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/config-features/${config.version}/xml/features</repository>
+
+  <feature name='odl-netconf-api' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring-extension/${project.version}</bundle>
+    <feature version='${protocol-framework.version}'>odl-protocol-framework</feature>
+    <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version}</bundle>
+    <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version}</bundle>
+  </feature>
+  <feature name='odl-netconf-mapping-api' version='${project.version}'>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${project.version}</bundle>
+  </feature>
+  <feature name='odl-netconf-util' version='${project.version}'>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <bundle>mvn:org.opendaylight.controller/netconf-util/${project.version}</bundle>
+  </feature>
+  <feature name='odl-config-netconf-connector' version='${project.version}'>
+    <feature version='${config.version}'>odl-config-manager</feature>
+    <bundle>mvn:org.opendaylight.controller/config-netconf-connector/${project.version}</bundle>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <feature version='${project.version}'>odl-netconf-util</feature>
+  </feature>
+
+  <feature name='odl-netconf-impl' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-impl/${project.version}</bundle>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <feature version='${project.version}'>odl-netconf-util</feature>
+    <feature version='${project.version}'>odl-netconf-netty-util</feature>
+  </feature>
+  <feature name='odl-netconf-netty-util' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-netty-util/${project.version}</bundle>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <feature version='${project.version}'>odl-netconf-util</feature>
+    <bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/${ganymed.version}</bundle>
+    <bundle>mvn:org.openexi/nagasena/${exi.nagasena.version}</bundle>
+    <bundle>mvn:io.netty/netty-codec/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-handler/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-common/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
+  </feature>
+  <feature name='odl-netconf-misc' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-client/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netconf-monitoring/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netconf-tcp/${project.version}</bundle>
+  </feature>
+
+</features>
\ No newline at end of file
diff --git a/features/pom.xml b/features/pom.xml
new file mode 100644 (file)
index 0000000..dce47fa
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../opendaylight/commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>features-controller</artifactId>
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <modules>
+    <module>config</module>
+    <module>mdsal</module>
+    <module>netconf</module>
+    <module>protocol-framework</module>
+  </modules>
+</project>
diff --git a/features/protocol-framework/pom.xml b/features/protocol-framework/pom.xml
new file mode 100644 (file)
index 0000000..f0208d6
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../../opendaylight/commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>features-odl-protocol-framework</artifactId>
+  <version>${protocol-framework.version}</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <features.file>features.xml</features.file>
+  </properties>
+
+  <dependencies></dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>filter</id>
+            <goals>
+              <goal>resources</goal>
+            </goals>
+            <phase>generate-resources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/${features.file}</file>
+                  <type>xml</type>
+                  <classifier>features</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+  </scm>
+</project>
diff --git a/features/protocol-framework/src/main/resources/features.xml b/features/protocol-framework/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..d2560f5
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-protocol-framework-${protocol-framework.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.controller/config-features/${config.version}/xml/features</repository>
+  <feature name='odl-protocol-framework' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/protocol-framework/${protocol-framework.version}</bundle>
+    <feature version='${config.version}'>odl-config-api</feature> <!-- needed by netty-config-api -->
+    <feature version='${config.version}'>odl-config-netty-config-api</feature> <!-- needed by netty-config-api -->
+  </feature>
+</features>
\ No newline at end of file
index 28c23c8259cd9ca76492fb154b52e0767b67d98f..163c64ed520bb1782bf0d1778f087913f0a4b86a 100644 (file)
@@ -91,6 +91,7 @@
     <forwarding.staticrouting.northbound.version>0.4.2-SNAPSHOT</forwarding.staticrouting.northbound.version>
     <forwardingrulesmanager.implementation.version>0.4.2-SNAPSHOT</forwardingrulesmanager.implementation.version>
     <forwardingrulesmanager.version>0.6.0-SNAPSHOT</forwardingrulesmanager.version>
+    <ganymed.version>1.1-SNAPSHOT</ganymed.version>
     <hosttracker.api.version>0.5.2-SNAPSHOT</hosttracker.api.version>
     <hosttracker.implementation.version>0.5.2-SNAPSHOT</hosttracker.implementation.version>
     <hosttracker.northbound.version>0.4.2-SNAPSHOT</hosttracker.northbound.version>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>ganymed</artifactId>
-        <version>1.1-SNAPSHOT</version>
+        <version>${ganymed.version}</version>
       </dependency>
       <!-- Third parties from opendaylight released -->
       <dependency>
diff --git a/opendaylight/config/feature/src/main/resources/features.xml b/opendaylight/config/feature/src/main/resources/features.xml
deleted file mode 100644 (file)
index a84a743..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<features name="config-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
-  <feature name='config-all' version='${project.version}'>
-    <feature version='${project.version}'>odl-config-subsystem</feature>
-  </feature>
-
-  <feature name='odl-config-subsystem' version='${project.version}'>
-    <feature version='${yangtools.version}'>yangtools-concepts</feature>
-    <feature version='${yangtools.version}'>yangtools-binding</feature>
-    <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
-    <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
-    <bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-util/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/yang-jmx-generator/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-persister-api/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/shutdown-api/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/shutdown-impl/${project.version}</bundle>
-    <bundle>mvn:org.osgi/org.osgi.core/${osgi.core.version}</bundle>
-    <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
-    <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
-  </feature>
-</features>
\ No newline at end of file
index a8a4c87a4eaa9f28a3e6656390bb27accbdd1f67..66bb01f051fa1042e9fc08d4019a236f1e07bb04 100644 (file)
@@ -39,7 +39,6 @@
     <module>shutdown-impl</module>
     <module>netconf-config-dispatcher</module>
     <module>config-module-archetype</module>
-    <module>feature</module>
   </modules>
 
   <dependencies>
index 221bfa78e8972822b43894cd039b306456839e3b..4ef0b8e86bf926062ff0e7071775efd79d0f531a 100644 (file)
       <type>kar</type>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-odl-protocol-framework</artifactId>
+      <version>${protocol-framework.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>netconf-features</artifactId>
+      <version>${netconf.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>features-yangtools</artifactId>
-      <version>${yangtools.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
   </dependencies>
 
   <build>
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml
deleted file mode 100644 (file)
index 7853b86..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<snapshot>
-    <configuration>
-        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                <module>
-                   <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">prefix:remote-zeromq-rpc-server</type>
-                   <name>remoter</name>
-                   <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
-                   <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
-                       <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
-                       <name>dom-broker</name>
-                   </dom-broker>
-               </module>
-            </modules>
-            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-            </services>
-        </data>
-    </configuration>
-
-    <required-capabilities>
-       <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&amp;revision=2013-10-28</capability>
-    </required-capabilities>
-</snapshot>
-
index be3add104289951ef29a9564d03f7a197fcf73c7..ff68176f1fed36f3b8c606421cee8790a73ec582 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.controller.md.frm.compatibility;
 
-import java.util.Collections;
-
 import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
 import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
@@ -17,7 +15,6 @@ import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
 import org.opendaylight.controller.sal.common.util.Arguments;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
 import org.opendaylight.yangtools.concepts.Registration;
@@ -26,8 +23,8 @@ import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
@@ -89,7 +86,7 @@ public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHa
             this.manager.removeStaticFlow(flow.getName(), flow.getNode());
             this.manager.addStaticFlow(flow);
         }
-        return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+        return RpcResultBuilder.<Void> success().build();
     }
 
     public RpcResult<Void> rollback(final FlowCommitTransaction transaction) {
index 01d75acfe6332b3e6574683ad49736efdf58655f..56c7afb253a5224547f848b40b1b125bd376b553 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.controller.sal.compatibility.adsal;
 import java.math.BigInteger;
 
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.compatibility.InventoryMapping;
 import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
@@ -32,6 +31,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -70,7 +70,8 @@ public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListen
         AddFlowOutputBuilder builder = new AddFlowOutputBuilder();
         builder.setTransactionId(new TransactionId(BigInteger.valueOf(status.getRequestId())));
         AddFlowOutput rpcResultType = builder.build();
-        return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
+        return Futures.immediateFuture(RpcResultBuilder.<AddFlowOutput>status(status.isSuccess())
+                .withResult(rpcResultType).build());
     }
 
     @Override
@@ -84,7 +85,8 @@ public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListen
         RemoveFlowOutputBuilder builder = new RemoveFlowOutputBuilder();
         builder.setTransactionId(new TransactionId(BigInteger.valueOf(status.getRequestId())));
         RemoveFlowOutput rpcResultType = builder.build();
-        return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
+        return Futures.immediateFuture(RpcResultBuilder.<RemoveFlowOutput>status(status.isSuccess())
+                                                         .withResult(rpcResultType).build());
 
     }
 
index c5cbecabedae35c96eb1fd0cad2ae5059253d074..e63cb54b8685174fafc7367bbe76bc130104a107 100644 (file)
@@ -13,7 +13,6 @@ import java.util.List;
 import java.util.concurrent.Future;
 
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.compatibility.FromSalConversionsUtils;
 import org.opendaylight.controller.sal.compatibility.InventoryMapping;
 import org.opendaylight.controller.sal.compatibility.NodeMapping;
@@ -60,6 +59,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.n
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -107,7 +107,8 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
             LOG.error(e.getMessage());
         }
 
-        return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
+        return Futures.immediateFuture(RpcResultBuilder.<GetAllFlowStatisticsFromFlowTableOutput>
+                                                status(rpcResultBool).withResult(rpcResultType).build());
     }
 
     /**
@@ -133,7 +134,8 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
             LOG.error(e.getMessage());
         }
 
-        return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
+        return Futures.immediateFuture(RpcResultBuilder.<GetAllFlowsStatisticsFromAllFlowTablesOutput>
+                                               status(rpcResultBool).withResult(rpcResultType).build());
     }
 
     @Override
@@ -154,7 +156,8 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
             LOG.error(e.getMessage());
         }
 
-        return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
+        return Futures.immediateFuture(RpcResultBuilder.<GetFlowStatisticsFromFlowTableOutput>
+                                              status(rpcResultBool).withResult(rpcResultType).build());
     }
 
     @Override
index 396206e28ed30f1a03c8b28f72fec645911fa86f..64d212e9bc57e514f4616d4fb5078d636315003a 100644 (file)
@@ -9,8 +9,8 @@ module opendaylight-inventory {
     revision "2013-08-19" {
         description "Initial revision of Inventory model";
     }
-    
-    
+
+
     typedef support-type {
         type enumeration {
             enum native;
@@ -21,43 +21,79 @@ module opendaylight-inventory {
 
     typedef node-id {
         type inet:uri;
+        description "Identifier for a particular node. For example:
+
+                        myprotocol:<unique_node_id>
+
+                        myprotocol:12
+
+                    It is a good practice to always lead with a scoping identifier.
+                    In the example above the scoping was 'myprotocol'. In your app you
+                    could use 'myapp' etc.";
     }
 
     typedef node-connector-id {
         type inet:uri;
+        description "Identifier for a particular node-connector. For example:
+
+                        myprotocol:<unique_node_connector_id>
+                        myprotocol:3
+
+                    It is a good practice to always lead with a scoping identifier.
+                    In the example above the scoping was 'myprotocol'. In your app you
+                    could use 'myapp' etc.";
+
     }
 
+    //YANG does not have a statement which limits the scope of an instance-identifier to a particular subtree,
+    //which is why we are using a type capture and not an instance-identifier to define a node-ref and a node-connector-ref.
     typedef node-ref {
         type instance-identifier;
+        description "A reference that points to an opendaylight-light:nodes/node in the data tree.";
     }
 
     typedef node-connector-ref {
         type instance-identifier;
+        description "A reference that points to an opendaylight-list:nodes/node/{node-id}/node-connector in the data tree.";
     }
 
     identity node-context {
-        description "Identity used to mark node context";
+        description "A node-context is a classifier for node elements which allows an RPC to provide a service on behalf of a particular element in the data tree.";
     }
 
     identity node-connector-context {
-        description "Identity used to mark node connector context";
+        description "A node-connector-context is a classifier for node-connector elements which allows an RPC to provide a service on behalf of a particular element in the data tree.";
     }
 
+    //We are defining a base identity here because there are limitations with yang enums. Yang doesn't allow you to extend enumeratations.
+    //Therefore by defining a base identity we allow other yang files to extend this identity to define additional "enumerations". By
+    //using node-type as their base they are able to pass their object to fields that accept "node-types" while uniquely describing their
+    //type of node, such as "router-node" or "switch-node" etc.
+    //See https://wiki.opendaylight.org/view/YANG_Tools:YANG_to_Java_Mapping#Identity for more information.
     identity node-type {
-        description "Base identity for node types";
+        description "A base identity definition which represents a generic node type and can be extended in other yang files.";
     }
 
     identity node-connector-type {
-        description "Base identity for node connectors type";
+        description "A base identity definition which represents a generic node connector type and can be extended in other yang files.";
     }
 
     grouping node {
+
+        description "Describes the contents of a generic node -
+                     essentially an ID and a list of node-connectors.
+                     Acts as an augmentation point where other yang files
+                      can add additional information.";
+
         leaf id {
             type node-id;
+            description "The unique identifier for the node.";
         }
 
         list "node-connector" {
             key "id";
+
+            description "A list of node connectors that belong this node.";
             ext:context-instance "node-connector-context";
 
             uses node-connector;
@@ -65,55 +101,117 @@ module opendaylight-inventory {
     }
 
     grouping node-connector {
+
+        description "Describes a generic node connector which consists of an ID.
+                     Acts as an augmentation point where other yang files can
+                      add additional information.";
+
         leaf id {
             type node-connector-id;
+            description "The unique identifier for the node-connector.";
         }
     }
 
     grouping node-context-ref {
-        description 
-        "Helper grouping which contains a reference to node context.";
+        description
+        "A helper grouping which contains a reference to a node classified with a node-context. This allows RPCs in other yang files to refine their input to a particular node instance.";
+
         leaf node {
             ext:context-reference "node-context";
             type node-ref;
+            description "A reference to a particular node.";
         }
     }
 
     /** Base structure **/
     container nodes {
+
+        description "The root container of all nodes.";
+
         list node {
             key "id";
             ext:context-instance "node-context";
-
-            uses node;
+            description "A list of nodes (as defined by the 'grouping node').";
+            uses node; //this refers to the 'grouping node' defined above.
         }
     }
 
+    //The following notifications should really be replaced by direct writes to the data tree with data change listeners listening to those changes.
+    //Notifications should be reserved for one time events which do not require persistence to the data tree.
     notification node-updated {
+
+        status deprecated;
+
+        description "A notification sent by someone who realized there was a modification to a node, but did not modify the data tree.
+                    Describes that something on the node has been updated (including addition of a new node), but is for
+                    whatever reason is not modifying the data tree.
+
+                    Deprecated: If a process determines that a node was updated, then that
+                    logic should update the node using the DataBroker directly. Listeners interested
+                    update changes should register a data change listener for notifications on removals.";
+
         leaf node-ref {
             ext:context-reference "node-context";
+            description "A reference to the node which changed.";
+
             type node-ref;
         }
         uses node;
     }
 
     notification node-connector-updated {
+
+        status deprecated;
+
+        description "A notification sent by someone who realized there was a modification to a node-connector, but did not modify the data tree.
+                    Describes that something on the node-connector has been updated (including addition of a new node-connector), but is for
+                    whatever reason is not modifying the data tree.
+
+                    Deprecated: If a process determines that a node-connector was updated, then that
+                    logic should update the node-connector using the DataBroker directly. Listeners interested
+                    update changes should register a data change listener for notifications on removals.";
+
         leaf node-connector-ref {
             ext:context-reference "node-connector-context";
             type node-connector-ref;
+            description "A reference to the node-connector which changed.";
         }
         uses node-connector;
     }
 
     notification node-removed {
+
+        status deprecated;
+
+        description "A notification sent by someone who realized there was a node was removed, but did not modify the data tree.
+                    Describes that a node has been removed but is for
+                    whatever reason is not modifying the data tree.
+
+                    Deprecated: If a process determines that a node was removed, then that
+                    logic should remove the node from the DataBroker directly. Listeners interested
+                    in changes should register a data change listener for notifications on removals.";
+
         leaf node-ref {
+            description "A reference to the node that was removed.";
             ext:context-reference "node-context";
             type node-ref;
         }
     }
 
     notification node-connector-removed {
+
+        status deprecated;
+
+        description "A notification sent by someone who realized there was a node-connector was removed, but did not modify the data tree.
+                    Describes that a node-connector has been removed but is for
+                    whatever reason is not modifying the data tree.
+
+                    Deprecated: If a process determines that a node-connector was removed, then that
+                    logic should remove the node-connector from the DataBroker directly. Listeners interested
+                    in changes should register a data change listener for notifications on removals.";
+
         leaf node-connector-ref {
+            description "A reference to the node-connector that was removed.";
             ext:context-reference "node-connector-context";
             type node-connector-ref;
         }
index d3f6d2d005a93ce5ffa0c30cddd8190976bc6309..1cfd5a66399eb4991fedb3cb59098aa62e1d8249 100644 (file)
@@ -63,9 +63,6 @@
     <!--sal-protocolbuffer-encoding-->
     <module>sal-protocolbuffer-encoding</module>
 
-    <!--  Karaf feature -->
-    <module>feature</module>
-
     <!-- Yang Test Models for MD-SAL -->
     <module>sal-test-model</module>
   </modules>
index 1c6447a4e741615b714657c9356dc6b756fe44c0..b45450ae3a54554243fe6a3c5097f362fb82779b 100644 (file)
@@ -33,7 +33,6 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.Delegator;
@@ -42,8 +41,8 @@ import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -163,7 +162,7 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
                 if(requestCommitSuccess) {
                     return tx.getDelegate().commit();
                 }
-                return Futures.immediateFuture(Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError>emptySet()));
+                return Futures.immediateFuture(RpcResultBuilder.<TransactionStatus>failed().withResult(TransactionStatus.FAILED).build());
             }
         });
 
index 052fd2169a523b955a427f036e2a0ab6b7a03bc4..709b62fee25247c09ec980c188acd504693d4e3e 100644 (file)
@@ -37,8 +37,6 @@ RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentif
 
     private static final Logger LOG = LoggerFactory.getLogger(RpcRouterCodegenInstance.class);
 
-    private T defaultService;
-
     private final Class<T> serviceType;
 
     private final T invocationProxy;
@@ -49,11 +47,8 @@ RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentif
 
     private final Map<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, T>> routingTables;
 
-    private final String name;
-
     @SuppressWarnings("unchecked")
     public RpcRouterCodegenInstance(final String name,final Class<T> type, final T routerImpl, final Iterable<Class<? extends BaseIdentity>> contexts) {
-        this.name = name;
         this.listeners = ListenerRegistry.create();
         this.serviceType = type;
         this.invocationProxy = routerImpl;
@@ -90,7 +85,7 @@ RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentif
 
     @Override
     public T getDefaultService() {
-        return defaultService;
+        return RuntimeCodeHelper.getDelegate(invocationProxy);
     }
 
     @Override
@@ -125,11 +120,17 @@ RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentif
         return new RoutedRpcRegistrationImpl(service);
     }
 
+    public void removeDefaultImplementation(final T instance) {
+        RpcService current = RuntimeCodeHelper.getDelegate(invocationProxy);
+        if(instance == current) {
+            RuntimeCodeHelper.setDelegate(invocationProxy, null);
+        }
+    }
+
     @Override
     public RpcRegistration<T> registerDefaultService(final T service) {
-        // TODO Auto-generated method stub
         RuntimeCodeHelper.setDelegate(invocationProxy, service);
-        return null;
+        return new DefaultRpcImplementationRegistration(service);
     }
 
     private class RoutedRpcRegistrationImpl extends AbstractObjectRegistration<T> implements RoutedRpcRegistration<T> {
@@ -168,4 +169,24 @@ RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentif
 
         }
     }
+
+    private class DefaultRpcImplementationRegistration extends AbstractObjectRegistration<T> implements RpcRegistration<T> {
+
+
+        protected DefaultRpcImplementationRegistration(final T instance) {
+            super(instance);
+        }
+
+        @Override
+        protected void removeRegistration() {
+            removeDefaultImplementation(this.getInstance());
+        }
+
+        @Override
+        public Class<T> getServiceType() {
+            return serviceType;
+        }
+    }
+
+
 }
index 542dfa7e7bca61a0fc4ff33e31239c3c3872e73b..952d84d885c41e73fe2312bf22c723f62cc44b35 100644 (file)
@@ -7,6 +7,15 @@
  */
 package org.opendaylight.controller.sal.binding.impl;
 
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
@@ -28,15 +37,6 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.EventListener;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-import static com.google.common.base.Preconditions.checkState;
-
 public class RpcProviderRegistryImpl implements //
         RpcProviderRegistry, //
         RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
@@ -60,19 +60,19 @@ public class RpcProviderRegistryImpl implements //
         return name;
     }
 
-    public RpcProviderRegistryImpl(String name) {
+    public RpcProviderRegistryImpl(final String name) {
         super();
         this.name = name;
     }
 
     @Override
-    public final <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type,
-            T implementation) throws IllegalStateException {
+    public final <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(final Class<T> type,
+            final T implementation) throws IllegalStateException {
         return getRpcRouter(type).addRoutedRpcImplementation(implementation);
     }
 
     @Override
-    public final <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
+    public final <T extends RpcService> RpcRegistration<T> addRpcImplementation(final Class<T> type, final T implementation)
             throws IllegalStateException {
         @SuppressWarnings("unchecked")
         RpcRouter<T> potentialRouter = (RpcRouter<T>) rpcRouters.get(type);
@@ -92,7 +92,7 @@ public class RpcProviderRegistryImpl implements //
 
     @SuppressWarnings("unchecked")
     @Override
-    public final <T extends RpcService> T getRpcService(Class<T> type) {
+    public final <T extends RpcService> T getRpcService(final Class<T> type) {
 
         T potentialProxy = (T) publicProxies.get(type);
         if (potentialProxy != null) {
@@ -115,8 +115,8 @@ public class RpcProviderRegistryImpl implements //
         }
     }
 
-    @SuppressWarnings("unchecked")
-    public <T extends RpcService> RpcRouter<T> getRpcRouter(Class<T> type) {
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public <T extends RpcService> RpcRouter<T> getRpcRouter(final Class<T> type) {
         RpcRouter<?> potentialRouter = rpcRouters.get(type);
         if (potentialRouter != null) {
             return (RpcRouter<T>) potentialRouter;
@@ -140,7 +140,7 @@ public class RpcProviderRegistryImpl implements //
         }
     }
 
-    private void notifyGlobalRpcAdded(Class<? extends RpcService> type) {
+    private void notifyGlobalRpcAdded(final Class<? extends RpcService> type) {
         for(ListenerRegistration<GlobalRpcRegistrationListener> listener : globalRpcListeners) {
             try {
                 listener.getInstance().onGlobalRpcRegistered(type);
@@ -151,7 +151,7 @@ public class RpcProviderRegistryImpl implements //
 
     }
 
-    private void notifyListenersRoutedCreated(RpcRouter<?> router) {
+    private void notifyListenersRoutedCreated(final RpcRouter<?> router) {
 
         for (ListenerRegistration<RouterInstantiationListener> listener : routerInstantiationListener) {
             try {
@@ -164,7 +164,7 @@ public class RpcProviderRegistryImpl implements //
     }
 
     public ListenerRegistration<RouterInstantiationListener> registerRouterInstantiationListener(
-            RouterInstantiationListener listener) {
+            final RouterInstantiationListener listener) {
         ListenerRegistration<RouterInstantiationListener> reg = routerInstantiationListener.register(listener);
         try {
             for (RpcRouter<?> router : rpcRouters.values()) {
@@ -176,9 +176,10 @@ public class RpcProviderRegistryImpl implements //
         return reg;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
-            L listener) {
+            final L listener) {
         return (ListenerRegistration<L>) routeChangeListeners.register(listener);
     }
 
@@ -186,7 +187,7 @@ public class RpcProviderRegistryImpl implements //
         return rpcFactory;
     }
 
-    public void setRpcFactory(RuntimeCodeGenerator rpcFactory) {
+    public void setRpcFactory(final RuntimeCodeGenerator rpcFactory) {
         this.rpcFactory = rpcFactory;
     }
 
@@ -194,7 +195,7 @@ public class RpcProviderRegistryImpl implements //
         void onRpcRouterCreated(RpcRouter<?> router);
     }
 
-    public ListenerRegistration<GlobalRpcRegistrationListener> registerGlobalRpcRegistrationListener(GlobalRpcRegistrationListener listener) {
+    public ListenerRegistration<GlobalRpcRegistrationListener> registerGlobalRpcRegistrationListener(final GlobalRpcRegistrationListener listener) {
         return globalRpcListeners.register(listener);
     }
 
@@ -209,12 +210,12 @@ public class RpcProviderRegistryImpl implements //
 
         private final Class<T> type;
 
-        public RouteChangeForwarder(Class<T> type) {
+        public RouteChangeForwarder(final Class<T> type) {
             this.type = type;
         }
 
         @Override
-        public void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
+        public void onRouteChange(final RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
             Map<RpcContextIdentifier, Set<InstanceIdentifier<?>>> announcements = new HashMap<>();
             for (Entry<Class<? extends BaseIdentity>, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements()
                     .entrySet()) {
@@ -245,7 +246,7 @@ public class RpcProviderRegistryImpl implements //
         private final Class<T> serviceType;
         private RpcProviderRegistryImpl registry;
 
-        public RpcProxyRegistration(Class<T> type, T service, RpcProviderRegistryImpl registry) {
+        public RpcProxyRegistration(final Class<T> type, final T service, final RpcProviderRegistryImpl registry) {
             super(service);
             this.serviceType = type;
             this.registry =  registry;
index 6e4b2d8d99b69c2f417fd96a6532c404e37b8b0d..71253d02d66ff0230ad483dea2297afee072c8ba 100644 (file)
  */
 package org.opendaylight.controller.sal.binding.impl.connect.dom;
 
-import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
-import java.lang.ref.WeakReference;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.concurrent.Callable;
+
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
 import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
-import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService.NotificationInterestListener;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
-import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
 import org.opendaylight.controller.sal.binding.impl.MountPointManagerImpl.BindingMountPointImpl;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
-import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.GlobalRpcRegistrationListener;
-import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.RouterInstantiationListener;
-import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
 import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.ObjectRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.BaseIdentity;
-import org.opendaylight.yangtools.yang.binding.BindingMapping;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.Notification;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
-import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
 public class BindingIndependentConnector implements //
         RuntimeDataProvider, //
         Provider, //
         AutoCloseable {
 
-    private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
-
+    private static final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
             .builder().toInstance();
 
-    private final static Method EQUALS_METHOD;
-
     private BindingIndependentMappingService mappingService;
-
     private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
-
     private DataProviderService baDataService;
 
-    private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
-    private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
-
-    private final BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
-    private final DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
-
-    private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
+    private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+    private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+    private final BindingToDomCommitHandler bindingToDomCommitHandler;
+    private final DomToBindingCommitHandler domToBindingCommitHandler;
 
     private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
-
     private RpcProvisionRegistry biRpcRegistry;
     private RpcProviderRegistry baRpcRegistry;
 
     private ListenerRegistration<DomToBindingRpcForwardingManager> domToBindingRpcManager;
-    // private ListenerRegistration<BindingToDomRpcForwardingManager>
-    // bindingToDomRpcManager;
-
-    private final Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
 
-        @Override
-        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier<?> input) {
-            return mappingService.toDataDom(input);
-        }
-
-    };
-
-    private boolean rpcForwarding = false;
-
-    private boolean dataForwarding = false;
-
-    private boolean notificationForwarding = false;
+    private boolean rpcForwarding;
+    private boolean dataForwarding;
+    private boolean notificationForwarding;
 
     private RpcProviderRegistryImpl baRpcRegistryImpl;
 
@@ -150,12 +75,15 @@ public class BindingIndependentConnector implements //
 
     private NotificationPublishService domNotificationService;
 
-    static {
-        try {
-            EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+    public BindingIndependentConnector() {
+        domOpenedTransactions = new ConcurrentHashMap<>();
+        bindingOpenedTransactions = new ConcurrentHashMap<>();
+
+        bindingToDomCommitHandler = new BindingToDomCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
+        domToBindingCommitHandler = new DomToBindingCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
+        rpcForwarding = false;
+        dataForwarding = false;
+        notificationForwarding = false;
     }
 
     @Override
@@ -195,84 +123,6 @@ public class BindingIndependentConnector implements //
         }
     }
 
-    private DataModificationTransaction createBindingToDomTransaction(
-            final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
-        DataModificationTransaction target = biDataService.beginTransaction();
-        LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier());
-        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
-            target.removeConfigurationData(biEntry);
-            LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry);
-        }
-        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
-            target.removeOperationalData(biEntry);
-            LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry);
-        }
-        for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
-                .entrySet()) {
-            Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
-                    .toDataDom(entry);
-            target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
-            LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry);
-        }
-        for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
-                .entrySet()) {
-            Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
-                    .toDataDom(entry);
-            target.putOperationalData(biEntry.getKey(), biEntry.getValue());
-            LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry);
-        }
-
-        return target;
-    }
-
-    private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
-            final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
-        org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
-                .beginTransaction();
-        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
-            try {
-
-                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
-                target.removeConfigurationData(baEntry);
-            } catch (DeserializationException e) {
-                LOG.error("Ommiting from BA transaction: {}.", entry, e);
-            }
-        }
-        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
-            try {
-
-                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
-                target.removeOperationalData(baEntry);
-            } catch (DeserializationException e) {
-                LOG.error("Ommiting from BA transaction: {}.", entry, e);
-            }
-        }
-        for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
-                .getUpdatedConfigurationData().entrySet()) {
-            try {
-                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
-                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
-                target.putConfigurationData(baKey, baData);
-            } catch (DeserializationException e) {
-                LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
-            }
-        }
-        for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
-                .getUpdatedOperationalData().entrySet()) {
-            try {
-
-                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
-                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
-                target.putOperationalData(baKey, baData);
-            } catch (DeserializationException e) {
-                LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
-            }
-        }
-        return target;
-    }
-
     public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
         return biDataService;
     }
@@ -280,6 +130,7 @@ public class BindingIndependentConnector implements //
     protected void setDomDataService(
             final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
         this.biDataService = biDataService;
+        bindingToDomCommitHandler.setBindingIndependentDataService(this.biDataService);
     }
 
     public DataProviderService getBaDataService() {
@@ -288,6 +139,7 @@ public class BindingIndependentConnector implements //
 
     protected void setBindingDataService(final DataProviderService baDataService) {
         this.baDataService = baDataService;
+        domToBindingCommitHandler.setBindingAwareDataService(this.baDataService);
     }
 
     public RpcProviderRegistry getRpcRegistry() {
@@ -323,10 +175,12 @@ public class BindingIndependentConnector implements //
         dataForwarding = true;
     }
 
+    //WTF? - cycle references to biFwdManager - need to solve :-/
     public void startRpcForwarding() {
+        checkNotNull(mappingService, "Unable to start Rpc forwarding. Reason: Mapping Service is not initialized properly!");
         if (biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
             checkState(!rpcForwarding, "Connector is already forwarding RPCs");
-            final DomToBindingRpcForwardingManager biFwdManager = new DomToBindingRpcForwardingManager();
+            final DomToBindingRpcForwardingManager biFwdManager = new DomToBindingRpcForwardingManager(mappingService, biRpcRegistry, baRpcRegistry);
 
             domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(biFwdManager);
             biRpcRegistry.addRpcRegistrationListener(biFwdManager);
@@ -334,6 +188,7 @@ public class BindingIndependentConnector implements //
                 baRpcRegistryImpl = (RpcProviderRegistryImpl) baRpcRegistry;
                 baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance());
                 baRpcRegistryImpl.registerGlobalRpcRegistrationListener(domToBindingRpcManager.getInstance());
+                biFwdManager.setRegistryImpl(baRpcRegistryImpl);
             }
             rpcForwarding = true;
         }
@@ -341,15 +196,23 @@ public class BindingIndependentConnector implements //
 
     public void startNotificationForwarding() {
         checkState(!notificationForwarding, "Connector is already forwarding notifications.");
-        if (baNotifyService != null && domNotificationService != null) {
-            baNotifyService.registerInterestListener(new DomToBindingNotificationForwarder());
-
+        if (mappingService == null) {
+            LOG.warn("Unable to start Notification forwarding. Reason: Mapping Service is not initialized properly!");
+        } else if (baNotifyService == null) {
+            LOG.warn("Unable to start Notification forwarding. Reason: Binding Aware Notify Service is not initialized properly!");
+        } else if (domNotificationService == null) {
+            LOG.warn("Unable to start Notification forwarding. Reason: DOM Notification Service is not initialized properly!");
+        } else {
+            baNotifyService.registerInterestListener(
+                new DomToBindingNotificationForwarder(mappingService, baNotifyService, domNotificationService));
             notificationForwarding = true;
         }
     }
 
     protected void setMappingService(final BindingIndependentMappingService mappingService) {
         this.mappingService = mappingService;
+        bindingToDomCommitHandler.setMappingService(this.mappingService);
+        domToBindingCommitHandler.setMappingService(this.mappingService);
     }
 
     @Override
@@ -364,458 +227,15 @@ public class BindingIndependentConnector implements //
 
     }
 
-    public <T extends RpcService> void onRpcRouterCreated(final Class<T> serviceType, final RpcRouter<T> router) {
-
-    }
-
     public void setDomRpcRegistry(final RpcProvisionRegistry registry) {
         biRpcRegistry = registry;
     }
 
     @Override
     public void close() throws Exception {
-        if (baCommitHandlerRegistration != null) {
-            baCommitHandlerRegistration.close();
-        }
         if (biCommitHandlerRegistration != null) {
             biCommitHandlerRegistration.close();
         }
-
-    }
-
-    private class DomToBindingTransaction implements
-            DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
-
-        private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
-        private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
-
-        public DomToBindingTransaction(
-                final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
-                final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
-            super();
-            this.backing = backing;
-            this.modification = modification;
-            bindingOpenedTransactions.put(backing.getIdentifier(), this);
-        }
-
-        @Override
-        public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
-            return modification;
-        }
-
-        @Override
-        public RpcResult<Void> rollback() throws IllegalStateException {
-            // backing.cancel();
-            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
-        }
-
-        @Override
-        public RpcResult<Void> finish() throws IllegalStateException {
-            Future<RpcResult<TransactionStatus>> result = backing.commit();
-            try {
-                RpcResult<TransactionStatus> baResult = result.get();
-                return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
-            } catch (InterruptedException e) {
-                throw new IllegalStateException("", e);
-            } catch (ExecutionException e) {
-                throw new IllegalStateException("", e);
-            }
-        }
-    }
-
-    private class BindingToDomTransaction implements
-            DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
-
-        private final DataModificationTransaction backing;
-        private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-
-        public BindingToDomTransaction(final DataModificationTransaction backing,
-                final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-            this.backing = backing;
-            this.modification = modification;
-            domOpenedTransactions.put(backing.getIdentifier(), this);
-        }
-
-        @Override
-        public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
-            return modification;
-        }
-
-        @Override
-        public RpcResult<Void> finish() throws IllegalStateException {
-            Future<RpcResult<TransactionStatus>> result = backing.commit();
-            try {
-                RpcResult<TransactionStatus> biResult = result.get();
-                return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
-            } catch (InterruptedException e) {
-                throw new IllegalStateException("", e);
-            } catch (ExecutionException e) {
-                throw new IllegalStateException("", e);
-            } finally {
-                domOpenedTransactions.remove(backing.getIdentifier());
-            }
-        }
-
-        @Override
-        public RpcResult<Void> rollback() throws IllegalStateException {
-            domOpenedTransactions.remove(backing.getIdentifier());
-            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
-        }
-    }
-
-    private class BindingToDomCommitHandler implements
-            DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
-        @Override
-        public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
-                final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
-
-            /**
-             * Transaction was created as DOM transaction, in that case we do
-             * not need to forward it back.
-             */
-            if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
-
-                return CommitHandlerTransactions.allwaysSuccessfulTransaction(bindingTransaction);
-            }
-            DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
-            BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
-            LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .",
-                    bindingTransaction.getIdentifier(), domTransaction.getIdentifier());
-            return wrapped;
-        }
-    }
-
-    private class DomToBindingCommitHandler implements //
-            RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>>, //
-            DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
-
-        @Override
-        public void onRegister(
-                final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
-
-            mappingService.toDataDom(registration
-                    .getPath());
-
-        }
-
-        @Override
-        public void onUnregister(
-                final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
-            // NOOP for now
-            // FIXME: do registration based on only active commit handlers.
-        }
-
-        @Override
-        public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
-                final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
-            Object identifier = domTransaction.getIdentifier();
-
-            /**
-             * We checks if the transcation was originated in this mapper. If it
-             * was originated in this mapper we are returing allways success
-             * commit hanlder to prevent creating loop in two-phase commit and
-             * duplicating data.
-             */
-            if (domOpenedTransactions.containsKey(identifier)) {
-                return CommitHandlerTransactions.allwaysSuccessfulTransaction(domTransaction);
-            }
-
-            org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
-            DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
-            LOG.trace("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
-                    baTransaction.getIdentifier());
-            return forwardedTransaction;
-        }
-    }
-
-    /**
-     * Manager responsible for instantiating forwarders responsible for
-     * forwarding of RPC invocations from DOM Broker to Binding Aware Broker
-     *
-     */
-    private class DomToBindingRpcForwardingManager implements
-            RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>, RouterInstantiationListener,
-            GlobalRpcRegistrationListener, RpcRegistrationListener {
-
-        private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
-        private RpcProviderRegistryImpl registryImpl;
-
-        public RpcProviderRegistryImpl getRegistryImpl() {
-            return registryImpl;
-        }
-
-        public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) {
-            this.registryImpl = registryImpl;
-        }
-
-        @Override
-        public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
-            getRpcForwarder(cls, null).registerToDOMBroker();
-        }
-
-        @Override
-        public void onGlobalRpcUnregistered(final Class<? extends RpcService> cls) {
-            // NOOP
-        }
-
-        @Override
-        public void onRpcRouterCreated(final RpcRouter<?> router) {
-            Class<? extends BaseIdentity> ctx = router.getContexts().iterator().next();
-            getRpcForwarder(router.getServiceType(), ctx);
-        }
-
-        @Override
-        public void onRouteChange(final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
-            for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
-                bindingRoutesAdded(entry);
-            }
-        }
-
-        private void bindingRoutesAdded(final Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
-            Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
-            Class<? extends RpcService> service = entry.getKey().getRpcService();
-            if (context != null) {
-                getRpcForwarder(service, context).registerPaths(context, service, entry.getValue());
-            }
-        }
-
-        private DomToBindingRpcForwarder getRpcForwarder(final Class<? extends RpcService> service,
-                final Class<? extends BaseIdentity> context) {
-            DomToBindingRpcForwarder potential = forwarders.get(service);
-            if (potential != null) {
-                return potential;
-            }
-            if (context == null) {
-                potential = new DomToBindingRpcForwarder(service);
-            } else {
-                potential = new DomToBindingRpcForwarder(service, context);
-            }
-
-            forwarders.put(service, potential);
-            return potential;
-        }
-
-        @Override
-        public void onRpcImplementationAdded(final QName name) {
-
-            final Optional<Class<? extends RpcService>> rpcInterface = mappingService.getRpcServiceClassFor(
-                    name.getNamespace().toString(), name.getFormattedRevision());
-            if (rpcInterface.isPresent()) {
-                getRpcForwarder(rpcInterface.get(), null).registerToBindingBroker();
-            }
-        }
-
-        @Override
-        public void onRpcImplementationRemoved(final QName name) {
-
-        }
-    }
-
-    private class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
-
-        private final Set<QName> supportedRpcs;
-        private final WeakReference<Class<? extends RpcService>> rpcServiceType;
-        private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
-        private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
-        private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
-        private final RpcService proxy;
-        private ObjectRegistration<?> forwarderRegistration;
-        private boolean registrationInProgress = false;
-
-        public DomToBindingRpcForwarder(final Class<? extends RpcService> service) {
-            this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
-            this.supportedRpcs = mappingService.getRpcQNamesFor(service);
-
-            Class<?> cls = rpcServiceType.get();
-            ClassLoader clsLoader = cls.getClassLoader();
-            proxy =(RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
-            createStrategies();
-        }
-
-        /**
-         * Constructor for Routed RPC Forwareder.
-         *
-         * @param service
-         * @param context
-         */
-        public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
-                                        final Class<? extends BaseIdentity> context) {
-            this(service);
-            Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
-                    .<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> builder();
-            try {
-                for (QName rpc : supportedRpcs) {
-                    registrationsBuilder.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
-                }
-                createDefaultDomForwarder();
-            } catch (Exception e) {
-                LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
-            }
-            registrations = registrationsBuilder.build();
-        }
-
-
-
-        private void createStrategies() {
-            try {
-                for (QName rpc : supportedRpcs) {
-                    RpcInvocationStrategy strategy = createInvocationStrategy(rpc, rpcServiceType.get());
-                    strategiesByMethod.put(strategy.targetMethod, strategy);
-                    strategiesByQName.put(rpc, strategy);
-                }
-            } catch (Exception e) {
-                LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
-            }
-
-        }
-
-        /**
-         * Registers RPC Forwarder to DOM Broker,
-         * this means Binding Aware Broker has implementation of RPC
-         * which is registered to it.
-         *
-         * If RPC Forwarder was previously registered to DOM Broker
-         * or to Bidning Broker this method is noop to prevent
-         * creating forwarding loop.
-         *
-         */
-        public void registerToDOMBroker() {
-            if(!registrationInProgress && forwarderRegistration == null) {
-                registrationInProgress = true;
-                CompositeObjectRegistrationBuilder<DomToBindingRpcForwarder> builder = CompositeObjectRegistration.builderFor(this);
-                try {
-                    for (QName rpc : supportedRpcs) {
-                        builder.add(biRpcRegistry.addRpcImplementation(rpc, this));
-                    }
-                } catch (Exception e) {
-                    LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
-                }
-                this.forwarderRegistration = builder.toInstance();
-                registrationInProgress = false;
-            }
-        }
-
-
-        public void registerPaths(final Class<? extends BaseIdentity> context,
-                final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
-            QName ctx = BindingReflections.findQName(context);
-            for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
-                    toDOMInstanceIdentifier)) {
-                for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
-                    reg.registerPath(ctx, path);
-                }
-            }
-        }
-
-        @Override
-        public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
-            if (EQUALS_METHOD.equals(method)) {
-                return false;
-            }
-            RpcInvocationStrategy strategy = strategiesByMethod.get(method);
-            checkState(strategy != null);
-            checkArgument(args.length <= 2);
-            if (args.length == 1) {
-                checkArgument(args[0] instanceof DataObject);
-                return strategy.forwardToDomBroker((DataObject) args[0]);
-            }
-            return strategy.forwardToDomBroker(null);
-        }
-
-        public void removePaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
-                final Set<InstanceIdentifier<?>> set) {
-            QName ctx = BindingReflections.findQName(context);
-            for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
-                    toDOMInstanceIdentifier)) {
-                for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
-                    reg.unregisterPath(ctx, path);
-                }
-            }
-        }
-
-        @Override
-        public Set<QName> getSupportedRpcs() {
-            return supportedRpcs;
-        }
-
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        public void createDefaultDomForwarder() {
-            if (baRpcRegistryImpl != null) {
-                Class<?> cls = rpcServiceType.get();
-                ClassLoader clsLoader = cls.getClassLoader();
-                RpcService proxy = (RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
-
-                RpcRouter rpcRouter = baRpcRegistryImpl.getRpcRouter(rpcServiceType.get());
-                rpcRouter.registerDefaultService(proxy);
-            }
-        }
-
-        @Override
-        public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
-            checkArgument(rpc != null);
-            checkArgument(domInput != null);
-
-            Class<? extends RpcService> rpcType = rpcServiceType.get();
-            checkState(rpcType != null);
-            RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
-            checkState(rpcService != null);
-            CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
-
-            try {
-                return Futures.immediateFuture(resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput));
-            } catch (Exception e) {
-                return Futures.immediateFailedFuture(e);
-            }
-        }
-
-        private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
-            return strategiesByQName.get(rpc);
-        }
-
-        private RpcInvocationStrategy createInvocationStrategy(final QName rpc,
-                final Class<? extends RpcService> rpcType) throws Exception {
-            return ClassLoaderUtils.withClassLoader(rpcType.getClassLoader(), new Callable<RpcInvocationStrategy>() {
-                @Override
-                public RpcInvocationStrategy call() throws Exception {
-                    String methodName = BindingMapping.getMethodName(rpc);
-                    Method targetMethod = null;
-                    for (Method possibleMethod : rpcType.getMethods()) {
-                        if (possibleMethod.getName().equals(methodName)
-                                && BindingReflections.isRpcMethod(possibleMethod)) {
-                            targetMethod = possibleMethod;
-                            break;
-                        }
-                    }
-                    checkState(targetMethod != null, "Rpc method not found");
-                    return  new RpcInvocationStrategy(rpc,targetMethod, mappingService, biRpcRegistry);
-                }
-
-            });
-        }
-
-        /**
-         * Registers RPC Forwarder to Binding Broker,
-         * this means DOM Broekr has implementation of RPC
-         * which is registered to it.
-         *
-         * If RPC Forwarder was previously registered to DOM Broker
-         * or to Bidning Broker this method is noop to prevent
-         * creating forwarding loop.
-         *
-         */
-        public void registerToBindingBroker() {
-            if(!registrationInProgress && forwarderRegistration == null) {
-               try {
-                   registrationInProgress = true;
-                   this.forwarderRegistration = baRpcRegistry.addRpcImplementation((Class)rpcServiceType.get(), proxy);
-               } catch (Exception e) {
-                   LOG.error("Unable to forward RPCs for {}",rpcServiceType.get(),e);
-               } finally {
-                   registrationInProgress = false;
-               }
-            }
-        }
     }
 
     public boolean isRpcForwarding() {
@@ -842,45 +262,4 @@ public class BindingIndependentConnector implements //
     public void setDomNotificationService(final NotificationPublishService domService) {
         this.domNotificationService = domService;
     }
-
-    private class DomToBindingNotificationForwarder implements NotificationInterestListener, NotificationListener {
-
-        private final ConcurrentMap<QName, WeakReference<Class<? extends Notification>>> notifications = new ConcurrentHashMap<>();
-        private final Set<QName> supportedNotifications = new HashSet<>();
-
-        @Override
-        public Set<QName> getSupportedNotifications() {
-            return Collections.unmodifiableSet(supportedNotifications);
-        }
-
-        @Override
-        public void onNotification(final CompositeNode notification) {
-            QName qname = notification.getNodeType();
-            WeakReference<Class<? extends Notification>> potential = notifications.get(qname);
-            if (potential != null) {
-                Class<? extends Notification> potentialClass = potential.get();
-                if (potentialClass != null) {
-                    final DataContainer baNotification = mappingService.dataObjectFromDataDom(potentialClass,
-                            notification);
-
-                    if (baNotification instanceof Notification) {
-                        baNotifyService.publish((Notification) baNotification);
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void onNotificationSubscribtion(final Class<? extends Notification> notificationType) {
-            QName qname = BindingReflections.findQName(notificationType);
-            if (qname != null) {
-                WeakReference<Class<? extends Notification>> already = notifications.putIfAbsent(qname,
-                        new WeakReference<Class<? extends Notification>>(notificationType));
-                if (already == null) {
-                    domNotificationService.addNotificationListener(qname, this);
-                    supportedNotifications.add(qname);
-                }
-            }
-        }
-    }
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingToDomCommitHandler.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingToDomCommitHandler.java
new file mode 100644 (file)
index 0000000..ee06283
--- /dev/null
@@ -0,0 +1,99 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class BindingToDomCommitHandler implements
+    DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+    private final Logger LOG = LoggerFactory.getLogger(BindingToDomCommitHandler.class);
+
+    private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+    private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+    private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
+    private BindingIndependentMappingService mappingService;
+
+    BindingToDomCommitHandler(final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions,
+        final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions) {
+        this.bindingOpenedTransactions = bindingOpenedTransactions;
+        this.domOpenedTransactions = domOpenedTransactions;
+    }
+
+    public void setBindingIndependentDataService(final DataProviderService biDataService) {
+        this.biDataService = biDataService;
+    }
+
+    public void setMappingService(BindingIndependentMappingService mappingService) {
+        this.mappingService = mappingService;
+    }
+
+    @Override
+    public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
+        final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
+
+        /**
+         * Transaction was created as DOM transaction, in that case we do
+         * not need to forward it back.
+         */
+        if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
+            return CommitHandlerTransactions.allwaysSuccessfulTransaction(bindingTransaction);
+        }
+        DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
+        BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction, domOpenedTransactions);
+        LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .",
+            bindingTransaction.getIdentifier(), domTransaction.getIdentifier());
+        return wrapped;
+    }
+
+    private DataModificationTransaction createBindingToDomTransaction(
+        final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+        if (biDataService == null) {
+            final String msg = "Binding Independent Service is not initialized correctly! Binding to DOM Transaction cannot be created for ";
+            LOG.error(msg + "{}", source);
+            throw new IllegalStateException(msg + source);
+        }
+        if (mappingService == null) {
+            final String msg = "Mapping Service is not initialized correctly! Binding to DOM Transaction cannot be created for ";
+            LOG.error(msg + "{}", source);
+            throw new IllegalStateException(msg + source);
+        }
+        DataModificationTransaction target = biDataService.beginTransaction();
+        LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier());
+        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeConfigurationData(biEntry);
+            LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry);
+        }
+        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeOperationalData(biEntry);
+            LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry);
+        }
+        for (Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
+            .entrySet()) {
+            Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+                .toDataDom(entry);
+            target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
+            LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry);
+        }
+        for (Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
+            .entrySet()) {
+            Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+                .toDataDom(entry);
+            target.putOperationalData(biEntry.getKey(), biEntry.getValue());
+            LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry);
+        }
+        return target;
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingToDomTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingToDomTransaction.java
new file mode 100644 (file)
index 0000000..081adb4
--- /dev/null
@@ -0,0 +1,59 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+class BindingToDomTransaction implements
+    DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+    private final DataModificationTransaction backing;
+    private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+    private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+
+    public BindingToDomTransaction(final DataModificationTransaction backing,
+        final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,
+        ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions) {
+        this.backing = backing;
+        this.modification = modification;
+        this.domOpenedTransactions = domOpenedTransactions;
+        this.domOpenedTransactions.put(backing.getIdentifier(), this);
+    }
+
+    @Override
+    public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
+        return modification;
+    }
+
+    @Override
+    public RpcResult<Void> finish() throws IllegalStateException {
+        Future<RpcResult<TransactionStatus>> result = backing.commit();
+        try {
+            RpcResult<TransactionStatus> biResult = result.get();
+            domOpenedTransactions.remove(backing.getIdentifier());
+            return RpcResultBuilder.<Void> status(biResult.isSuccessful())
+                                             .withRpcErrors(biResult.getErrors()).build();
+        } catch (InterruptedException e) {
+            throw new IllegalStateException("", e);
+        } catch (ExecutionException e) {
+            throw new IllegalStateException("", e);
+        } finally {
+            domOpenedTransactions.remove(backing.getIdentifier());
+        }
+    }
+
+    @Override
+    public RpcResult<Void> rollback() throws IllegalStateException {
+        domOpenedTransactions.remove(backing.getIdentifier());
+        return RpcResultBuilder.<Void> success().build();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingCommitHandler.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingCommitHandler.java
new file mode 100644 (file)
index 0000000..395af8f
--- /dev/null
@@ -0,0 +1,135 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class DomToBindingCommitHandler implements //
+    RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>>, //
+    DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
+
+    private final Logger LOG = LoggerFactory.getLogger(DomToBindingCommitHandler.class);
+
+    private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+    private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+
+    DomToBindingCommitHandler(final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions,
+        final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions) {
+        this.bindingOpenedTransactions = bindingOpenedTransactions;
+        this.domOpenedTransactions = domOpenedTransactions;
+    }
+
+    private DataProviderService baDataService;
+    private BindingIndependentMappingService mappingService;
+
+    public void setBindingAwareDataService(DataProviderService baDataService) {
+        this.baDataService = baDataService;
+    }
+
+    public void setMappingService(BindingIndependentMappingService mappingService) {
+        this.mappingService = mappingService;
+    }
+
+    @Override
+    public void onRegister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        mappingService.toDataDom(registration.getPath());
+    }
+
+    @Override
+    public void onUnregister(
+        final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        // NOOP for now
+        // FIXME: do registration based on only active commit handlers.
+    }
+
+    @Override
+    public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
+        final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
+        Object identifier = domTransaction.getIdentifier();
+
+        /**
+         * We checks if the transcation was originated in this mapper. If it
+         * was originated in this mapper we are returing allways success
+         * commit hanlder to prevent creating loop in two-phase commit and
+         * duplicating data.
+         */
+        if (domOpenedTransactions.containsKey(identifier)) {
+            return CommitHandlerTransactions.allwaysSuccessfulTransaction(domTransaction);
+        }
+
+        org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
+        DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction, bindingOpenedTransactions);
+        LOG.trace("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
+            baTransaction.getIdentifier());
+        return forwardedTransaction;
+    }
+
+    private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
+        final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
+        if (baDataService == null) {
+            final String msg = "Binding Aware Service is not initialized correctly! DOM to Binding Transaction cannot be created for ";
+            LOG.error(msg + "{}", source);
+            throw new IllegalStateException(msg + source);
+        }
+        if (mappingService == null) {
+            final String msg = "Mapping Service is not initialized correctly! DOM to Binding Transaction cannot be created for ";
+            LOG.error(msg + "{}", source);
+            throw new IllegalStateException(msg + source);
+        }
+
+        org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
+            .beginTransaction();
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
+            try {
+
+                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+                target.removeConfigurationData(baEntry);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}.", entry, e);
+            }
+        }
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
+            try {
+
+                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+                target.removeOperationalData(baEntry);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}.", entry, e);
+            }
+        }
+        for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
+            .getUpdatedConfigurationData().entrySet()) {
+            try {
+                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+                target.putConfigurationData(baKey, baData);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
+            }
+        }
+        for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
+            .getUpdatedOperationalData().entrySet()) {
+            try {
+
+                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+                target.putOperationalData(baKey, baData);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
+            }
+        }
+        return target;
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingNotificationForwarder.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingNotificationForwarder.java
new file mode 100644 (file)
index 0000000..841ea55
--- /dev/null
@@ -0,0 +1,70 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+class DomToBindingNotificationForwarder implements NotificationProviderService.NotificationInterestListener,
+    NotificationListener {
+
+    private final ConcurrentMap<QName, WeakReference<Class<? extends Notification>>> notifications = new ConcurrentHashMap<>();
+    private final Set<QName> supportedNotifications = new HashSet<>();
+
+    private final BindingIndependentMappingService mappingService;
+    private final NotificationProviderService baNotifyService;
+    private final NotificationPublishService domNotificationService;
+
+    DomToBindingNotificationForwarder(final BindingIndependentMappingService mappingService, final NotificationProviderService baNotifyService,
+        final NotificationPublishService domNotificationService) {
+        this.mappingService = mappingService;
+        this.baNotifyService = baNotifyService;
+        this.domNotificationService = domNotificationService;
+    }
+
+    @Override
+    public Set<QName> getSupportedNotifications() {
+        return Collections.unmodifiableSet(supportedNotifications);
+    }
+
+    @Override
+    public void onNotification(final CompositeNode notification) {
+        QName qname = notification.getNodeType();
+        WeakReference<Class<? extends Notification>> potential = notifications.get(qname);
+        if (potential != null) {
+            Class<? extends Notification> potentialClass = potential.get();
+            if (potentialClass != null) {
+                final DataContainer baNotification = mappingService.dataObjectFromDataDom(potentialClass,
+                    notification);
+
+                if (baNotification instanceof Notification) {
+                    baNotifyService.publish((Notification) baNotification);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onNotificationSubscribtion(final Class<? extends Notification> notificationType) {
+        QName qname = BindingReflections.findQName(notificationType);
+        if (qname != null) {
+            WeakReference<Class<? extends Notification>> already = notifications.putIfAbsent(qname,
+                new WeakReference<Class<? extends Notification>>(notificationType));
+            if (already == null) {
+                domNotificationService.addNotificationListener(qname, this);
+                supportedNotifications.add(qname);
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingRpcForwarder.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingRpcForwarder.java
new file mode 100644 (file)
index 0000000..ffcab59
--- /dev/null
@@ -0,0 +1,281 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
+
+    private final Logger LOG = LoggerFactory.getLogger(DomToBindingRpcForwarder.class);
+
+    private final Set<QName> supportedRpcs;
+    private final WeakReference<Class<? extends RpcService>> rpcServiceType;
+    private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
+    private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
+    private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
+    private final RpcService proxy;
+    private ObjectRegistration<?> forwarderRegistration;
+    private boolean registrationInProgress = false;
+
+    private final RpcProvisionRegistry biRpcRegistry;
+    private final RpcProviderRegistry baRpcRegistry;
+    private final RpcProviderRegistryImpl baRpcRegistryImpl;
+
+    private final Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier;
+
+    private final static Method EQUALS_METHOD;
+
+    static {
+        try {
+            EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public DomToBindingRpcForwarder(final Class<? extends RpcService> service, final BindingIndependentMappingService mappingService,
+        final RpcProvisionRegistry biRpcRegistry, final RpcProviderRegistry baRpcRegistry, final RpcProviderRegistryImpl registryImpl) {
+        this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
+        this.supportedRpcs = mappingService.getRpcQNamesFor(service);
+
+        toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
+
+            @Override
+            public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier<?> input) {
+                return mappingService.toDataDom(input);
+            }
+        };
+
+        this.biRpcRegistry = biRpcRegistry;
+        this.baRpcRegistry = baRpcRegistry;
+        this.baRpcRegistryImpl = registryImpl;
+
+        Class<?> cls = rpcServiceType.get();
+        ClassLoader clsLoader = cls.getClassLoader();
+        proxy =(RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
+        createStrategies(mappingService);
+    }
+
+    /**
+     * Constructor for Routed RPC Forwareder.
+     *
+     * @param service
+     * @param context
+     * @param registryImpl
+     */
+    public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
+        final Class<? extends BaseIdentity> context, final BindingIndependentMappingService mappingService,
+        final RpcProvisionRegistry biRpcRegistry, final RpcProviderRegistry baRpcRegistry, final RpcProviderRegistryImpl registryImpl) {
+        this(service, mappingService, biRpcRegistry, baRpcRegistry,registryImpl);
+
+        final ImmutableSet.Builder<Broker.RoutedRpcRegistration> registrationsBuilder = ImmutableSet.builder();
+        try {
+            for (QName rpc : supportedRpcs) {
+                registrationsBuilder.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
+            }
+            createDefaultDomForwarder();
+        } catch (Exception e) {
+            LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
+        }
+        registrations = registrationsBuilder.build();
+    }
+
+
+
+    private void createStrategies(final BindingIndependentMappingService mappingService) {
+        try {
+            for (QName rpc : supportedRpcs) {
+                RpcInvocationStrategy strategy = createInvocationStrategy(rpc, rpcServiceType.get(), mappingService);
+                strategiesByMethod.put(strategy.targetMethod, strategy);
+                strategiesByQName.put(rpc, strategy);
+            }
+        } catch (Exception e) {
+            LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
+        }
+
+    }
+
+    /**
+     * Registers RPC Forwarder to DOM Broker,
+     * this means Binding Aware Broker has implementation of RPC
+     * which is registered to it.
+     *
+     * If RPC Forwarder was previously registered to DOM Broker
+     * or to Bidning Broker this method is noop to prevent
+     * creating forwarding loop.
+     *
+     */
+    public void registerToDOMBroker() {
+        if(!registrationInProgress && forwarderRegistration == null) {
+            registrationInProgress = true;
+            CompositeObjectRegistration.CompositeObjectRegistrationBuilder<DomToBindingRpcForwarder> builder = CompositeObjectRegistration.builderFor(this);
+            try {
+                for (QName rpc : supportedRpcs) {
+                    builder.add(biRpcRegistry.addRpcImplementation(rpc, this));
+                }
+            } catch (Exception e) {
+                LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
+            }
+            this.forwarderRegistration = builder.toInstance();
+            registrationInProgress = false;
+        }
+    }
+
+
+    public void registerPaths(final Class<? extends BaseIdentity> context,
+        final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
+        QName ctx = BindingReflections.findQName(context);
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
+            toDOMInstanceIdentifier)) {
+            for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
+                reg.registerPath(ctx, path);
+            }
+        }
+    }
+
+    @Override
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        if (EQUALS_METHOD.equals(method)) {
+            return false;
+        }
+        RpcInvocationStrategy strategy = strategiesByMethod.get(method);
+        checkState(strategy != null);
+        checkArgument(args.length <= 2);
+        if (args.length == 1) {
+            checkArgument(args[0] instanceof DataObject);
+            return strategy.forwardToDomBroker((DataObject) args[0]);
+        }
+        return strategy.forwardToDomBroker(null);
+    }
+
+    public void removePaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
+        final Set<InstanceIdentifier<?>> set) {
+        QName ctx = BindingReflections.findQName(context);
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
+            toDOMInstanceIdentifier)) {
+            for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
+                reg.unregisterPath(ctx, path);
+            }
+        }
+    }
+
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        return supportedRpcs;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void createDefaultDomForwarder() {
+        if (baRpcRegistryImpl != null) {
+            Class<?> cls = rpcServiceType.get();
+            ClassLoader clsLoader = cls.getClassLoader();
+            RpcService proxy = (RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
+
+            RpcRouter rpcRouter = baRpcRegistryImpl.getRpcRouter(rpcServiceType.get());
+            rpcRouter.registerDefaultService(proxy);
+        }
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
+        checkArgument(rpc != null);
+        checkArgument(domInput != null);
+
+        Class<? extends RpcService> rpcType = rpcServiceType.get();
+        checkState(rpcType != null);
+        RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
+        checkState(rpcService != null);
+        CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
+
+        try {
+            return Futures.immediateFuture(resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput));
+        } catch (Exception e) {
+            return Futures.immediateFailedFuture(e);
+        }
+    }
+
+    private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
+        return strategiesByQName.get(rpc);
+    }
+
+    private RpcInvocationStrategy createInvocationStrategy(final QName rpc,
+        final Class<? extends RpcService> rpcType, final BindingIndependentMappingService mappingService) throws Exception {
+        return ClassLoaderUtils.withClassLoader(rpcType.getClassLoader(), new Callable<RpcInvocationStrategy>() {
+            @Override
+            public RpcInvocationStrategy call() throws Exception {
+                String methodName = BindingMapping.getMethodName(rpc);
+                Method targetMethod = null;
+                for (Method possibleMethod : rpcType.getMethods()) {
+                    if (possibleMethod.getName().equals(methodName)
+                        && BindingReflections.isRpcMethod(possibleMethod)) {
+                        targetMethod = possibleMethod;
+                        break;
+                    }
+                }
+                checkState(targetMethod != null, "Rpc method not found");
+                return new RpcInvocationStrategy(rpc, targetMethod, mappingService, biRpcRegistry);
+            }
+
+        });
+    }
+
+    /**
+     * Registers RPC Forwarder to Binding Broker,
+     * this means DOM Broekr has implementation of RPC
+     * which is registered to it.
+     *
+     * If RPC Forwarder was previously registered to DOM Broker
+     * or to Bidning Broker this method is noop to prevent
+     * creating forwarding loop.
+     *
+     */
+    public void registerToBindingBroker() {
+        if(!registrationInProgress && forwarderRegistration == null) {
+            try {
+                registrationInProgress = true;
+                this.forwarderRegistration = baRpcRegistry.addRpcImplementation((Class)rpcServiceType.get(), proxy);
+            } catch (Exception e) {
+                LOG.error("Unable to forward RPCs for {}",rpcServiceType.get(),e);
+            } finally {
+                registrationInProgress = false;
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingRpcForwardingManager.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingRpcForwardingManager.java
new file mode 100644 (file)
index 0000000..63d4b71
--- /dev/null
@@ -0,0 +1,115 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.base.Optional;
+
+/**
+ * Manager responsible for instantiating forwarders responsible for
+ * forwarding of RPC invocations from DOM Broker to Binding Aware Broker
+ *
+ */
+class DomToBindingRpcForwardingManager implements
+    RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>,
+    RpcProviderRegistryImpl.RouterInstantiationListener,
+    RpcProviderRegistryImpl.GlobalRpcRegistrationListener, RpcRegistrationListener {
+
+    private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
+    private final BindingIndependentMappingService mappingService;
+    private final RpcProvisionRegistry biRpcRegistry;
+    private final RpcProviderRegistry baRpcRegistry;
+    private RpcProviderRegistryImpl registryImpl;
+
+    DomToBindingRpcForwardingManager(final BindingIndependentMappingService mappingService, final RpcProvisionRegistry biRpcRegistry,
+        final RpcProviderRegistry baRpcRegistry) {
+        this.mappingService = mappingService;
+        this.biRpcRegistry = biRpcRegistry;
+        this.baRpcRegistry = baRpcRegistry;
+    }
+
+    public RpcProviderRegistryImpl getRegistryImpl() {
+        return registryImpl;
+    }
+
+    public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) {
+        this.registryImpl = registryImpl;
+    }
+
+    @Override
+    public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
+        getRpcForwarder(cls, null).registerToDOMBroker();
+    }
+
+    @Override
+    public void onGlobalRpcUnregistered(final Class<? extends RpcService> cls) {
+        // NOOP
+    }
+
+    @Override
+    public void onRpcRouterCreated(final RpcRouter<?> router) {
+        Class<? extends BaseIdentity> ctx = router.getContexts().iterator().next();
+        getRpcForwarder(router.getServiceType(), ctx);
+    }
+
+    @Override
+    public void onRouteChange(final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+        for (Map.Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
+            bindingRoutesAdded(entry);
+        }
+    }
+
+    private void bindingRoutesAdded(final Map.Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
+        Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
+        Class<? extends RpcService> service = entry.getKey().getRpcService();
+        if (context != null) {
+            getRpcForwarder(service, context).registerPaths(context, service, entry.getValue());
+        }
+    }
+
+    private DomToBindingRpcForwarder getRpcForwarder(final Class<? extends RpcService> service,
+        final Class<? extends BaseIdentity> context) {
+        DomToBindingRpcForwarder potential = forwarders.get(service);
+        if (potential != null) {
+            return potential;
+        }
+        if (context == null) {
+            potential = new DomToBindingRpcForwarder(service, mappingService, biRpcRegistry, baRpcRegistry,registryImpl);
+        } else {
+            potential = new DomToBindingRpcForwarder(service, context, mappingService, biRpcRegistry, baRpcRegistry,registryImpl);
+        }
+
+        forwarders.put(service, potential);
+        return potential;
+    }
+
+    @Override
+    public void onRpcImplementationAdded(final QName name) {
+
+        final Optional<Class<? extends RpcService>> rpcInterface = mappingService.getRpcServiceClassFor(
+            name.getNamespace().toString(), name.getFormattedRevision());
+        if (rpcInterface.isPresent()) {
+            getRpcForwarder(rpcInterface.get(), null).registerToBindingBroker();
+        }
+    }
+
+    @Override
+    public void onRpcImplementationRemoved(final QName name) {
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DomToBindingTransaction.java
new file mode 100644 (file)
index 0000000..cb271a1
--- /dev/null
@@ -0,0 +1,60 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+class DomToBindingTransaction implements
+    DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> {
+
+    private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
+    private final DataModification<InstanceIdentifier, CompositeNode> modification;
+    private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+
+    public DomToBindingTransaction(
+    final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
+    final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification,
+        ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions) {
+        super();
+        this.backing = backing;
+        this.modification = modification;
+        this.bindingOpenedTransactions = bindingOpenedTransactions;
+        this.bindingOpenedTransactions.put(backing.getIdentifier(), this);
+    }
+
+    @Override
+    public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
+        return modification;
+    }
+
+    @Override
+    public RpcResult<Void> rollback() throws IllegalStateException {
+        bindingOpenedTransactions.remove(backing.getIdentifier());
+        return RpcResultBuilder.<Void> success().build();
+    }
+
+    @Override
+    public RpcResult<Void> finish() throws IllegalStateException {
+        Future<RpcResult<TransactionStatus>> result = backing.commit();
+        try {
+            RpcResult<TransactionStatus> baResult = result.get();
+            bindingOpenedTransactions.remove(backing.getIdentifier());
+            return RpcResultBuilder.<Void> status(baResult.isSuccessful())
+                                          .withRpcErrors(baResult.getErrors()).build();
+        } catch (InterruptedException e) {
+            throw new IllegalStateException("", e);
+        } catch (ExecutionException e) {
+            throw new IllegalStateException("", e);
+        } finally {
+            bindingOpenedTransactions.remove(backing.getIdentifier());
+        }
+    }
+}
index d08b217e71c547ea3cd2aa3dcb24a0b3374e9744..f03d07eb99c0fc2ae212cc358402ba67c17a4a74 100644 (file)
@@ -10,19 +10,17 @@ package org.opendaylight.controller.sal.binding.impl.connect.dom;
 
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.Future;
 
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
@@ -89,7 +87,7 @@ public class RpcInvocationStrategy {
     public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
 
         if(biRpcRegistry == null) {
-            return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
+            return Futures.<RpcResult<?>> immediateFuture(RpcResultBuilder.failed().build());
         }
 
         CompositeNode inputXml = null;
@@ -102,6 +100,7 @@ public class RpcInvocationStrategy {
 
         Function<RpcResult<CompositeNode>, RpcResult<?>> transformationFunction =
                                        new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
+            @SuppressWarnings("rawtypes")
             @Override
             public RpcResult<?> apply(RpcResult<CompositeNode> result) {
 
@@ -114,7 +113,7 @@ public class RpcInvocationStrategy {
                     }
                 }
 
-                return Rpcs.getRpcResult(result.isSuccessful(), output, result.getErrors());
+                return RpcResultBuilder.from( (RpcResult)result ).withResult( output ).build();
             }
         };
 
@@ -135,22 +134,18 @@ public class RpcInvocationStrategy {
         }
 
         if (futureResult == null) {
-            return Rpcs.getRpcResult(false);
+            return RpcResultBuilder.<CompositeNode>failed().build();
         }
 
-        RpcResult<?> bindingResult = futureResult.get();
-
-        Collection<RpcError> errors = bindingResult.getErrors();
-        if( errors == null ) {
-            errors = Collections.<RpcError>emptySet();
-        }
+        @SuppressWarnings("rawtypes")
+        RpcResult bindingResult = futureResult.get();
 
         final Object resultObj = bindingResult.getResult();
-        CompositeNode output = null;
+        Object output = null;
         if (resultObj instanceof DataObject) {
             output = mappingService.toDataDom((DataObject)resultObj);
         }
-        return Rpcs.getRpcResult( bindingResult.isSuccessful(), output, errors);
+        return RpcResultBuilder.from( bindingResult ).withResult( output ).build();
     }
 
     public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java
deleted file mode 100644 (file)
index aa6a9a2..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.sal.binding.impl.util;
-
-import com.google.common.collect.Multimap;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map.Entry;
-import org.opendaylight.yangtools.concepts.Path;
-
-@SuppressWarnings("all")
-public class MapUtils {
-  public static <P extends Path<P>, V extends Object> Collection<Entry<? extends P,? extends V>> getAllChildren(final Multimap<? extends P,? extends V> map, final P path) {
-    HashSet<Entry<? extends P,? extends V>> _hashSet = new HashSet<Entry<? extends P, ? extends V>>();
-    final HashSet<Entry<? extends P,? extends V>> ret = _hashSet;
-    final Collection<? extends Entry<? extends P,? extends V>> entries = map.entries();
-    for (final Entry<? extends P,? extends V> entry : entries) {
-      {
-        final P currentPath = entry.getKey();
-        if (path.contains(currentPath)) {
-          ret.add(entry);
-        } else if (currentPath.contains(path)){
-            ret.add(entry);
-        }
-      }
-    }
-    return ret;
-  }
-}
-
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java
new file mode 100644 (file)
index 0000000..9f1ae38
--- /dev/null
@@ -0,0 +1,99 @@
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Regression test suite for Bug 1125 - Can't detect switch disconnection
+ * https://bugs.opendaylight.org/show_bug.cgi?id=1125
+ */
+public class Bug1125RegressionTest extends AbstractDataChangeListenerTest {
+
+    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier
+            .create(Top.class);
+    private static final InstanceIdentifier<TopLevelList> TOP_FOO_PATH = TOP_PATH
+            .child(TopLevelList.class, TOP_FOO_KEY);
+
+    private static final InstanceIdentifier<TreeComplexUsesAugment> FOO_AUGMENT_PATH = TOP_FOO_PATH
+            .augmentation(TreeComplexUsesAugment.class);
+
+    private static final InstanceIdentifier<TreeComplexUsesAugment> WILDCARDED_AUGMENT_PATH = TOP_PATH
+            .child(TopLevelList.class).augmentation(
+                    TreeComplexUsesAugment.class);
+
+    private void writeInitialState() {
+        WriteTransaction initialTx = getDataBroker().newWriteOnlyTransaction();
+        initialTx.put(LogicalDatastoreType.OPERATIONAL, TOP_PATH,
+                new TopBuilder().build());
+        TreeComplexUsesAugment fooAugment = new TreeComplexUsesAugmentBuilder()
+                .setContainerWithUses(
+                        new ContainerWithUsesBuilder().setLeafFromGrouping(
+                                "foo").build()).build();
+        initialTx.put(LogicalDatastoreType.OPERATIONAL, path(TOP_FOO_KEY),
+                topLevelList(TOP_FOO_KEY, fooAugment));
+        assertCommit(initialTx.commit());
+    }
+
+    private void delete(final InstanceIdentifier<?> path) {
+        WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
+        tx.delete(LogicalDatastoreType.OPERATIONAL, path);
+        assertCommit(tx.commit());
+    }
+
+    private void verifyRemoved(
+            final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
+        assertEmpty(event.getCreatedData());
+        assertEmpty(event.getUpdatedData());
+        assertContains(event.getRemovedPaths(), FOO_AUGMENT_PATH);
+    }
+
+    private void deleteAndListenAugment(final DataChangeScope scope,
+            final InstanceIdentifier<?> path) {
+        writeInitialState();
+        TestListener listener = createListener(
+                LogicalDatastoreType.OPERATIONAL, WILDCARDED_AUGMENT_PATH,
+                scope);
+        delete(path);
+        verifyRemoved(listener.event());
+    }
+
+    @Test
+    public void deleteAndListenAugment() {
+
+        deleteAndListenAugment(DataChangeScope.ONE, TOP_PATH);
+
+        deleteAndListenAugment(DataChangeScope.BASE, TOP_PATH);
+
+        deleteAndListenAugment(DataChangeScope.SUBTREE, TOP_PATH);
+
+        deleteAndListenAugment(DataChangeScope.BASE, TOP_FOO_PATH);
+
+        deleteAndListenAugment(DataChangeScope.ONE, TOP_FOO_PATH);
+
+        deleteAndListenAugment(DataChangeScope.SUBTREE, TOP_FOO_PATH);
+
+        deleteAndListenAugment(DataChangeScope.BASE, FOO_AUGMENT_PATH);
+
+        deleteAndListenAugment(DataChangeScope.ONE, FOO_AUGMENT_PATH);
+
+        deleteAndListenAugment(DataChangeScope.SUBTREE, FOO_AUGMENT_PATH);
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java
new file mode 100644 (file)
index 0000000..110e5b4
--- /dev/null
@@ -0,0 +1,137 @@
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_BAR_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path;
+
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.test.AssertCollections;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.OpendaylightTestRpcServiceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.rpc.routing.rev140701.OpendaylightTestRoutedRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.rpc.routing.rev140701.TestContext;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+
+public class RpcProviderRegistryTest {
+
+    private static InstanceIdentifier<TopLevelList> FOO_PATH = path(TOP_FOO_KEY);
+    private static InstanceIdentifier<TopLevelList> BAR_PATH = path(TOP_BAR_KEY);
+    private static RpcContextIdentifier ROUTING_CONTEXT = RpcContextIdentifier.contextFor(OpendaylightTestRoutedRpcService.class, TestContext.class);
+
+    private RpcProviderRegistryImpl rpcRegistry;
+
+    @Before
+    public void setup() {
+        rpcRegistry = new RpcProviderRegistryImpl("test");
+    }
+
+    private static class TestListener implements RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>> {
+
+        final SettableFuture<RouteChange<RpcContextIdentifier, InstanceIdentifier<?>>> event = SettableFuture.create();
+        @Override
+        public void onRouteChange(
+                final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+            event.set(change);
+        }
+    }
+
+    @Test
+    public void testGlobalRpcRegistrations() throws Exception {
+        OpendaylightTestRpcServiceService one = Mockito.mock(OpendaylightTestRpcServiceService.class);
+        OpendaylightTestRpcServiceService two = Mockito.mock(OpendaylightTestRpcServiceService.class);
+
+        RpcRegistration<OpendaylightTestRpcServiceService> regOne = rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, one);
+        assertNotNull(regOne);
+
+        try {
+            rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, two);
+        fail("Second call for registration of same RPC must throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            assertNotNull(e.getMessage());
+        }
+
+        regOne.close();
+
+        RpcRegistration<OpendaylightTestRpcServiceService> regTwo = rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, two);
+        assertNotNull(regTwo);
+    }
+
+    @Test
+    public void testRpcRouterInstance() throws Exception  {
+        OpendaylightTestRoutedRpcService def = Mockito.mock(OpendaylightTestRoutedRpcService.class);
+
+        RpcRouter<OpendaylightTestRoutedRpcService> router = rpcRegistry.getRpcRouter(OpendaylightTestRoutedRpcService.class);
+
+        assertEquals(OpendaylightTestRoutedRpcService.class, router.getServiceType());
+        assertNotNull(router.getInvocationProxy());
+        assertNull(router.getDefaultService());
+
+        AssertCollections.assertContains(router.getContexts(), TestContext.class);
+
+        RpcRegistration<OpendaylightTestRoutedRpcService> regDef = router.registerDefaultService(def);
+        assertNotNull(regDef);
+        assertEquals(OpendaylightTestRoutedRpcService.class,regDef.getServiceType());
+        assertEquals(def,regDef.getInstance());
+        assertEquals(def, router.getDefaultService());
+
+        regDef.close();
+        assertNull("Default instance should be null after closing registration",  router.getDefaultService());
+    }
+
+    @Test
+    public void testRoutedRpcPathChangeEvents() throws InterruptedException, TimeoutException, ExecutionException {
+        OpendaylightTestRoutedRpcService one = Mockito.mock(OpendaylightTestRoutedRpcService.class);
+        OpendaylightTestRoutedRpcService two = Mockito.mock(OpendaylightTestRoutedRpcService.class);
+        RoutedRpcRegistration<OpendaylightTestRoutedRpcService> regOne = rpcRegistry.addRoutedRpcImplementation(OpendaylightTestRoutedRpcService.class, one);
+        RoutedRpcRegistration<OpendaylightTestRoutedRpcService> regTwo = rpcRegistry.addRoutedRpcImplementation(OpendaylightTestRoutedRpcService.class, two);
+        assertNotNull(regOne);
+        assertNotNull(regTwo);
+
+        final TestListener addListener = new TestListener();
+        rpcRegistry.registerRouteChangeListener(addListener);
+        regOne.registerPath(TestContext.class, FOO_PATH);
+
+        RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> fooAddEvent = addListener.event.get(500, TimeUnit.MILLISECONDS);
+        Set<InstanceIdentifier<?>> announce = fooAddEvent.getAnnouncements().get(ROUTING_CONTEXT);
+        assertNotNull(announce);
+        AssertCollections.assertContains(announce, FOO_PATH);
+        AssertCollections.assertNotContains(announce, BAR_PATH);
+
+
+
+        final TestListener removeListener = new TestListener();
+        rpcRegistry.registerRouteChangeListener(removeListener);
+
+        regOne.unregisterPath(TestContext.class, FOO_PATH);
+
+        RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> fooRemoveEvent = removeListener.event.get(500, TimeUnit.MILLISECONDS);
+        Set<InstanceIdentifier<?>> removal = fooRemoveEvent.getRemovals().get(ROUTING_CONTEXT);
+        assertNotNull(removal);
+        AssertCollections.assertContains(removal, FOO_PATH);
+        AssertCollections.assertNotContains(removal, BAR_PATH);
+
+
+    }
+
+}
index c5aea8f2ab666cb5e777e3f20d808910ab3308c6..6977588a017265f003de2e9ac0f3bba29383cc2f 100644 (file)
@@ -25,13 +25,13 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 
@@ -96,9 +96,11 @@ public class RpcInvocationStrategyTest {
 
     private void setupForForwardToDom(boolean hasOutput, boolean hasInput, int expectedErrorSize) {
 
-        if (expectedErrorSize > 0)
+        if (expectedErrorSize > 0) {
             errors.add(rpcError);
-        RpcResult<CompositeNode> result = Rpcs.getRpcResult(true, invokeRpcResult, errors);
+        }
+        RpcResult<CompositeNode> result = RpcResultBuilder.<CompositeNode>success(invokeRpcResult)
+                                                            .withRpcErrors( errors ).build();
         futureCompNode = Futures.immediateFuture(result);
         if( hasInput )
         {
@@ -191,22 +193,28 @@ public class RpcInvocationStrategyTest {
      * invokeOn Tests
      */
     private void setupRpcResultsWithOutput(int expectedErrorSize) {
-        if (expectedErrorSize > 0)
+        if (expectedErrorSize > 0) {
             errors.add(rpcError);
-        RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+        }
+        RpcResult<CompositeNode> resultCompNode = RpcResultBuilder.<CompositeNode>success(inputInvokeOn)
+                                                                        .withRpcErrors(errors).build();
         futureCompNode = Futures.immediateFuture(resultCompNode);
-        RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, toDataDomInput, errors);
+        RpcResult<DataObject> resultDataObj = RpcResultBuilder.<DataObject>success(toDataDomInput)
+                                                                           .withRpcErrors(errors).build();
         futureDataObj = Futures.immediateFuture(resultDataObj);
 
         when(mockMappingService.toDataDom(toDataDomInput)).thenReturn(outputInvokeOn);
     }
 
     private void setupRpcResultsNoOutput(int expectedErrorSize) {
-        if (expectedErrorSize > 0)
+        if (expectedErrorSize > 0) {
             errors.add(rpcError);
-        RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+        }
+        RpcResult<CompositeNode> resultCompNode = RpcResultBuilder.<CompositeNode>success(inputInvokeOn)
+                                                                          .withRpcErrors(errors).build();
         futureCompNode = Futures.immediateFuture(resultCompNode);
-        RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, null, errors);
+        RpcResult<DataObject> resultDataObj = RpcResultBuilder.<DataObject>success()
+                                                                          .withRpcErrors(errors).build();
         futureDataObj = Futures.immediateFuture(resultDataObj);
     }
 
index ca38ed0797e1f1d0433a2281a2763672d1d19300..48e1db0e631c3c02505913c02192866d35756ae7 100644 (file)
@@ -23,7 +23,6 @@ import org.junit.Test;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
 import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
@@ -42,12 +41,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -136,7 +134,7 @@ public class CrossBrokerRpcTest {
             @Override
             public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
                 CompositeNode result = testContext.getBindingToDomMappingService().toDataDom(output);
-                return Futures.immediateFuture(Rpcs.getRpcResult(true, result, ImmutableList.<RpcError>of()));
+                return Futures.immediateFuture(RpcResultBuilder.<CompositeNode>success(result).build());
             }
         });
         registration.registerPath(NodeContext.QNAME, BI_NODE_C_ID);
@@ -168,7 +166,7 @@ public class CrossBrokerRpcTest {
     private Future<RpcResult<AddFlowOutput>> addFlowResult(boolean success, long xid) {
         AddFlowOutput output = new AddFlowOutputBuilder() //
                 .setTransactionId(new TransactionId(BigInteger.valueOf(xid))).build();
-        RpcResult<AddFlowOutput> result = Rpcs.getRpcResult(success, output, ImmutableList.<RpcError> of());
+        RpcResult<AddFlowOutput> result = RpcResultBuilder.<AddFlowOutput>status(success).withResult(output).build();
         return Futures.immediateFuture(result);
     }
 
index c87b93625f4e4a0bc653b8e169eec56fe244f22f..0c123ebe66aac8a77de4bc62b17920d6d0003a93 100644 (file)
@@ -25,7 +25,6 @@ import org.opendaylight.controller.sal.binding.api.mount.MountProviderInstance;
 import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
 import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
 import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
@@ -39,6 +38,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -135,8 +135,8 @@ public class DOMRpcServiceTestBugfix560 {
             public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(
                     final QName rpc, final CompositeNode input) {
 
-                return Futures.immediateFuture(Rpcs
-                        .<CompositeNode> getRpcResult(true));
+                return Futures.immediateFuture(RpcResultBuilder
+                        .<CompositeNode> success().build());
             }
 
             @Override
index a51dc64816d0822778ff1b690bd10fdd19268afa..007122e41df26eaf6c3c9e803e2d3f75abcf8deb 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.controller.md.sal.common.impl.service;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -21,10 +20,9 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.yangtools.concepts.Path;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -68,8 +66,7 @@ public class TwoPhaseCommit<P extends Path<P>, D extends Object, DCL extends Dat
 
             log.trace("Transaction: {} Finished successfully (no effects).", transactionId);
 
-            return Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
-                    Collections.<RpcError> emptySet());
+            return RpcResultBuilder.<TransactionStatus> success( TransactionStatus.COMMITED ).build();
         }
 
         final ImmutableList.Builder<ListenerStateCapture<P, D, DCL>> listenersBuilder = ImmutableList.builder();
@@ -127,8 +124,7 @@ public class TwoPhaseCommit<P extends Path<P>, D extends Object, DCL extends Dat
         log.trace("Transaction: {} Notifying listeners.", transactionId);
 
         publishDataChangeEvent(listeners);
-        return Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
-                Collections.<RpcError> emptySet());
+        return RpcResultBuilder.<TransactionStatus> success(TransactionStatus.COMMITED).build();
     }
 
     private void captureInitialState(ImmutableList<ListenerStateCapture<P, D, DCL>> listeners) {
@@ -240,7 +236,6 @@ public class TwoPhaseCommit<P extends Path<P>, D extends Object, DCL extends Dat
         for (final DataCommitTransaction<P, D> transaction : transactions) {
             transaction.rollback();
         }
-        Set<RpcError> _emptySet = Collections.<RpcError> emptySet();
-        return Rpcs.<TransactionStatus> getRpcResult(false, TransactionStatus.FAILED, _emptySet);
+        return RpcResultBuilder.<TransactionStatus> failed().withResult(TransactionStatus.FAILED).build();
     }
 }
index 1af7ccc79ad2de55b1f26a3b53b11b6b44bfadea..9aacf1e0a8b8123d0c75360b7e9c9c88a73cb827 100644 (file)
@@ -7,13 +7,11 @@
  */
 package org.opendaylight.controller.sal.common.util;
 
-import java.util.Collections;
-
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
 import org.opendaylight.yangtools.concepts.Path;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 public class CommitHandlerTransactions {
 
@@ -26,11 +24,11 @@ public class CommitHandlerTransactions {
         }
         @Override
         public RpcResult<Void> rollback() throws IllegalStateException {
-            return Rpcs.<Void>getRpcResult(true, null, Collections.<RpcError>emptyList());
+            return RpcResultBuilder.<Void>success().build();
         }
         @Override
         public RpcResult<Void> finish() throws IllegalStateException {
-            return Rpcs.<Void>getRpcResult(true, null, Collections.<RpcError>emptyList());
+            return RpcResultBuilder.<Void>success().build();
         }
 
         @Override
index 4d41249b4d5600e7932d9b56dd34bbaaf80f8854..cacb167f6f54f962c4f7bb49b39452ed140186e1 100644 (file)
@@ -12,9 +12,9 @@ import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 
 /**
- * @author mirehak
- *
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.common.RpcResultBuilder}
  */
+@Deprecated
 public class RpcErrors {
 
     /**
index f30394187125153004e9b5c3a1b4d4cb2cc74886..69458b6a6d6e3492ed484c958bd3380e049bff0f 100644 (file)
@@ -16,6 +16,10 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 
 import com.google.common.collect.ImmutableList;
 
+/**
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.common.RpcResultBuilder}
+ */
+@Deprecated
 public class Rpcs {
 
     public static <T> RpcResult<T> getRpcResult(boolean successful) {
index 540e2fe20ce52208ffd4a659b5e21c70eafe4b10..13a0093d340b7ef3bc496cf6950d1118ad309ab5 100644 (file)
@@ -6,7 +6,6 @@
  */
 package org.opendaylight.controller.md.sal.dom.broker.impl;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -16,10 +15,9 @@ import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -221,7 +219,7 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
          */
         private RpcResult<TransactionStatus> commitBlocking() throws TransactionCommitFailedException {
             commitAll().checkedGet();
-            return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.<RpcError> emptySet());
+            return RpcResultBuilder.<TransactionStatus>success(TransactionStatus.COMMITED).build();
         }
 
         /**
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/GlobalRpcRegistration.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/GlobalRpcRegistration.java
new file mode 100644 (file)
index 0000000..f63e5ea
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+
+class GlobalRpcRegistration extends AbstractObjectRegistration<RpcImplementation> implements
+        RpcRegistration {
+    private final QName type;
+    private SchemaAwareRpcBroker router;
+
+    public GlobalRpcRegistration(final QName type, final RpcImplementation instance, final SchemaAwareRpcBroker router) {
+        super(instance);
+        this.type = type;
+        this.router = router;
+    }
+
+    @Override
+    public QName getType() {
+        return type;
+    }
+
+    @Override
+    protected void removeRegistration() {
+        if (router != null) {
+            router.remove(this);
+            router = null;
+        }
+    }
+}
\ No newline at end of file
index 50dfbe852b4d7241e08fba0686c6253068a59492..d7309b9ed31717ebe8641bdc4bee5f15ce8d948f 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.controller.sal.dom.broker.impl;
 
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -15,10 +14,9 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.data.DataStore;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -70,8 +68,7 @@ public final class HashMapDataStore implements DataStore, AutoCloseable {
     }
 
     public RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
-        return Rpcs.<Void> getRpcResult(true, null,
-                Collections.<RpcError> emptySet());
+        return RpcResultBuilder.<Void> success().build();
     }
 
     public RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
@@ -100,8 +97,7 @@ public final class HashMapDataStore implements DataStore, AutoCloseable {
         configuration.putAll(modification.getUpdatedConfigurationData());
         operational.putAll(modification.getUpdatedOperationalData());
 
-        return Rpcs.<Void> getRpcResult(true, null,
-                Collections.<RpcError> emptySet());
+        return RpcResultBuilder.<Void> success().build();
     }
 
     public void remove(final Map<InstanceIdentifier, CompositeNode> map,
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcRegImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcRegImpl.java
new file mode 100644 (file)
index 0000000..e4f19bb
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+class RoutedRpcRegImpl extends AbstractObjectRegistration<RpcImplementation> implements
+        RoutedRpcRegistration {
+
+    private final QName type;
+    private final RoutedRpcSelector router;
+
+    public RoutedRpcRegImpl(final QName rpcType, final RpcImplementation implementation, final RoutedRpcSelector routedRpcSelector) {
+        super(implementation);
+        this.type = rpcType;
+        router = routedRpcSelector;
+    }
+
+    @Override
+    public void registerPath(final QName context, final InstanceIdentifier path) {
+        router.addPath(context, path, this);
+    }
+
+    @Override
+    public void unregisterPath(final QName context, final InstanceIdentifier path) {
+        router.removePath(context, path, this);
+    }
+
+    @Override
+    protected void removeRegistration() {
+
+    }
+
+    @Override
+    public QName getType() {
+        return type;
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java
new file mode 100644 (file)
index 0000000..a22aed7
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
+
+class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable<RpcRoutingContext> {
+
+    private final RpcRoutingStrategy strategy;
+    private final Set<QName> supportedRpcs;
+    private final RpcRoutingContext identifier;
+    final ConcurrentMap<InstanceIdentifier, RoutedRpcRegImpl> implementations = new ConcurrentHashMap<>();
+    private final SchemaAwareRpcBroker router;
+
+    public RoutedRpcSelector(final RpcRoutingStrategy strategy, final SchemaAwareRpcBroker router) {
+        super();
+        this.strategy = strategy;
+        supportedRpcs = ImmutableSet.of(strategy.getIdentifier());
+        identifier = RpcRoutingContext.create(strategy.getContext(), strategy.getIdentifier());
+        this.router = router;
+    }
+
+    @Override
+    public RpcRoutingContext getIdentifier() {
+        return identifier;
+    }
+
+    @Override
+    public void close() throws Exception {
+
+    }
+
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        return supportedRpcs;
+    }
+
+    public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
+        return new RoutedRpcRegImpl(rpcType, implementation, this);
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
+        CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input"));
+        checkArgument(inputContainer != null, "Rpc payload must contain input element");
+        SimpleNode<?> routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf());
+        checkArgument(routeContainer != null, "Leaf %s must be set with value", strategy.getLeaf());
+        Object route = routeContainer.getValue();
+        checkArgument(route instanceof InstanceIdentifier,
+                      "The routed node %s is not an instance identifier", route);
+        RpcImplementation potential = null;
+        if (route != null) {
+            RoutedRpcRegImpl potentialReg = implementations.get(route);
+            if (potentialReg != null) {
+                potential = potentialReg.getInstance();
+            }
+        }
+        if (potential == null) {
+            return router.invokeRpc(rpc, (InstanceIdentifier) route, input);
+        }
+        checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route);
+        return potential.invokeRpc(rpc, input);
+    }
+
+    public void addPath(final QName context, final InstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
+        //checkArgument(strategy.getContext().equals(context),"Supplied context is not supported.");
+        RoutedRpcRegImpl previous = implementations.put(path, routedRpcRegImpl);
+        if (previous == null) {
+            router.notifyPathAnnouncement(context,strategy.getIdentifier(), path);
+        }
+
+    }
+
+    public void removePath(final QName context, final InstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
+        boolean removed = implementations.remove(path, routedRpcRegImpl);
+        if (removed) {
+            router.notifyPathWithdrawal(context, strategy.getIdentifier(), path);
+        }
+    }
+}
\ No newline at end of file
index 32139308b11230b806467f95d078c1608077a1f6..7bc827dcb0329d41825638efa9b5d1748ac0c83c 100644 (file)
@@ -14,10 +14,10 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import com.google.common.base.Preconditions;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
+import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
 import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
@@ -25,7 +25,6 @@ import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
 import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
 import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
@@ -33,17 +32,13 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -53,8 +48,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
 
     private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareRpcBroker.class);
 
-    private static final QName CONTEXT_REFERENCE = QName.create("urn:opendaylight:yang:extension:yang-ext",
-            "2013-07-09", "context-reference");
+
     private final ListenerRegistry<RpcRegistrationListener> rpcRegistrationListeners = new ListenerRegistry<>();
     private final ListenerRegistry<RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> routeChangeListeners = new ListenerRegistry<>();
 
@@ -65,7 +59,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
     private SchemaContextProvider schemaProvider;
     private RoutedRpcDefaultImplementation defaultDelegate;
 
-    public SchemaAwareRpcBroker(String identifier, SchemaContextProvider schemaProvider) {
+    public SchemaAwareRpcBroker(final String identifier, final SchemaContextProvider schemaProvider) {
         super();
         this.identifier = identifier;
         this.schemaProvider = schemaProvider;
@@ -75,7 +69,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         return defaultImplementation;
     }
 
-    public void setDefaultImplementation(RpcImplementation defaultImplementation) {
+    public void setDefaultImplementation(final RpcImplementation defaultImplementation) {
         this.defaultImplementation = defaultImplementation;
     }
 
@@ -83,7 +77,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         return schemaProvider;
     }
 
-    public void setSchemaProvider(SchemaContextProvider schemaProvider) {
+    public void setSchemaProvider(final SchemaContextProvider schemaProvider) {
         this.schemaProvider = schemaProvider;
     }
 
@@ -92,18 +86,18 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
     }
 
     @Override
-    public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultDelegate) {
+    public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultDelegate) {
         this.defaultDelegate = defaultDelegate;
     }
 
     @Override
-    public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
+    public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
         checkArgument(rpcType != null, "RPC Type should not be null");
         checkArgument(implementation != null, "RPC Implementatoin should not be null");
         return getOrCreateRoutedRpcRouter(rpcType).addRoutedRpcImplementation(rpcType, implementation);
     }
 
-    private RoutedRpcSelector getOrCreateRoutedRpcRouter(QName rpcType) {
+    private RoutedRpcSelector getOrCreateRoutedRpcRouter(final QName rpcType) {
         RoutedRpcSelector potential = getRoutedRpcRouter(rpcType);
         if (potential != null) {
             return potential;
@@ -114,15 +108,15 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
                 return potential;
             }
             RpcDefinition definition = findRpcDefinition(rpcType);
-            RoutingStrategy strategy = getRoutingStrategy(definition);
-            checkState(strategy instanceof RoutedRpcStrategy, "Rpc %s is not routed.", rpcType);
-            potential = new RoutedRpcSelector((RoutedRpcStrategy) strategy, this);
+            RpcRoutingStrategy strategy = RpcRoutingStrategy.from(definition);
+            checkState(strategy.isContextBasedRouted(), "Rpc %s is not routed.", rpcType);
+            potential = new RoutedRpcSelector( strategy, this);
             implementations.put(rpcType, potential);
             return potential;
         }
     }
 
-    private RoutedRpcSelector getRoutedRpcRouter(QName rpcType) {
+    private RoutedRpcSelector getRoutedRpcRouter(final QName rpcType) {
         RpcImplementation potential = implementations.get(rpcType);
         if (potential != null) {
             checkState(potential instanceof RoutedRpcSelector, "Rpc %s is not routed.", rpcType);
@@ -133,13 +127,13 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
     }
 
     @Override
-    public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
+    public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
             throws IllegalArgumentException {
         checkArgument(rpcType != null, "RPC Type should not be null");
         checkArgument(implementation != null, "RPC Implementatoin should not be null");
         checkState(!hasRpcImplementation(rpcType), "Implementation already registered");
         RpcDefinition definition = findRpcDefinition(rpcType);
-        checkArgument(!isRoutedRpc(definition), "RPC Type must not be routed.");
+        checkArgument(!RpcRoutingStrategy.from(definition).isContextBasedRouted(), "RPC Type must not be content routed.");
         GlobalRpcRegistration reg = new GlobalRpcRegistration(rpcType, implementation, this);
         final RpcImplementation previous = implementations.putIfAbsent(rpcType, implementation);
         Preconditions.checkState(previous == null, "Rpc %s is already registered.",rpcType);
@@ -147,7 +141,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         return reg;
     }
 
-    private void notifyRpcAdded(QName rpcType) {
+    private void notifyRpcAdded(final QName rpcType) {
         for (ListenerRegistration<RpcRegistrationListener> listener : rpcRegistrationListeners) {
             try {
                 listener.getInstance().onRpcImplementationAdded(rpcType);
@@ -158,12 +152,8 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         }
     }
 
-    private boolean isRoutedRpc(RpcDefinition definition) {
-        return getRoutingStrategy(definition) instanceof RoutedRpcStrategy;
-    }
-
     @Override
-    public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener) {
+    public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(final RpcRegistrationListener listener) {
         ListenerRegistration<RpcRegistrationListener> reg = rpcRegistrationListeners.register(listener);
         for (QName impl : implementations.keySet()) {
             listener.onRpcImplementationAdded(impl);
@@ -182,11 +172,11 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
     }
 
     @Override
-    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
         return findRpcImplemention(rpc).invokeRpc(rpc, input);
     }
 
-    private RpcImplementation findRpcImplemention(QName rpc) {
+    private RpcImplementation findRpcImplemention(final QName rpc) {
         checkArgument(rpc != null, "Rpc name should not be null");
         RpcImplementation potentialImpl = implementations.get(rpc);
         if (potentialImpl != null) {
@@ -201,11 +191,11 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         return potentialImpl;
     }
 
-    private boolean hasRpcImplementation(QName rpc) {
+    private boolean hasRpcImplementation(final QName rpc) {
         return implementations.containsKey(rpc);
     }
 
-    private RpcDefinition findRpcDefinition(QName rpcType) {
+    private RpcDefinition findRpcDefinition(final QName rpcType) {
         checkArgument(rpcType != null, "Rpc name must be supplied.");
         checkState(schemaProvider != null, "Schema Provider is not available.");
         SchemaContext ctx = schemaProvider.getSchemaContext();
@@ -215,7 +205,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         return findRpcDefinition(rpcType, module.getRpcs());
     }
 
-    static private RpcDefinition findRpcDefinition(QName rpcType, Set<RpcDefinition> rpcs) {
+    static private RpcDefinition findRpcDefinition(final QName rpcType, final Set<RpcDefinition> rpcs) {
         checkState(rpcs != null, "Rpc schema is not available.");
         for (RpcDefinition rpc : rpcs) {
             if (rpcType.equals(rpc.getQName())) {
@@ -225,225 +215,17 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         throw new IllegalArgumentException("Supplied Rpc Type is not defined.");
     }
 
-    private RoutingStrategy getRoutingStrategy(RpcDefinition rpc) {
-        ContainerSchemaNode input = rpc.getInput();
-        if (input != null) {
-            for (DataSchemaNode schemaNode : input.getChildNodes()) {
-                Optional<QName> context = getRoutingContext(schemaNode);
-                if (context.isPresent()) {
-                    return createRoutedStrategy(rpc, context.get(), schemaNode.getQName());
-                }
-            }
-        }
-        return createGlobalStrategy(rpc);
-    }
-
-    private static RoutingStrategy createRoutedStrategy(RpcDefinition rpc, QName context, QName leafNode) {
-        return new RoutedRpcStrategy(rpc.getQName(), context, leafNode);
-    }
-
-    private Optional<QName> getRoutingContext(DataSchemaNode schemaNode) {
-        for (UnknownSchemaNode extension : schemaNode.getUnknownSchemaNodes()) {
-            if (CONTEXT_REFERENCE.equals(extension.getNodeType())) {
-                return Optional.fromNullable(extension.getQName());
-            }
-        }
-        return Optional.absent();
-    }
-
-    private static RoutingStrategy createGlobalStrategy(RpcDefinition rpc) {
-        GlobalRpcStrategy ret = new GlobalRpcStrategy(rpc.getQName());
-        return ret;
-    }
-
     @Override
-    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
-      checkState(defaultDelegate != null);
-      return defaultDelegate.invokeRpc(rpc, identifier, input);
-    }
-
-    private static abstract class RoutingStrategy implements Identifiable<QName> {
-
-        private final QName identifier;
-
-        public RoutingStrategy(QName identifier) {
-            super();
-            this.identifier = identifier;
-        }
-
-        @Override
-        public QName getIdentifier() {
-            return identifier;
-        }
-    }
-
-    private static class GlobalRpcStrategy extends RoutingStrategy {
-
-        public GlobalRpcStrategy(QName identifier) {
-            super(identifier);
-        }
-    }
-
-    private static class RoutedRpcStrategy extends RoutingStrategy {
-
-        private final QName context;
-        private final QName leaf;
-
-        public RoutedRpcStrategy(QName identifier, QName ctx, QName leaf) {
-            super(identifier);
-            this.context = ctx;
-            this.leaf = leaf;
-        }
-
-        public QName getContext() {
-            return context;
-        }
-
-        public QName getLeaf() {
-            return leaf;
-        }
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final InstanceIdentifier route, final CompositeNode input) {
+      checkState(defaultDelegate != null, "No implementation is available for rpc:%s path:%s", rpc, route);
+      return defaultDelegate.invokeRpc(rpc, route, input);
     }
 
-    private static class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable<RpcRoutingContext> {
-
-        private final RoutedRpcStrategy strategy;
-        private final Set<QName> supportedRpcs;
-        private final RpcRoutingContext identifier;
-        private RpcImplementation defaultDelegate;
-        private final ConcurrentMap<InstanceIdentifier, RoutedRpcRegImpl> implementations = new ConcurrentHashMap<>();
-        private final SchemaAwareRpcBroker router;
-
-        public RoutedRpcSelector(RoutedRpcStrategy strategy, SchemaAwareRpcBroker router) {
-            super();
-            this.strategy = strategy;
-            supportedRpcs = ImmutableSet.of(strategy.getIdentifier());
-            identifier = RpcRoutingContext.create(strategy.context, strategy.getIdentifier());
-            this.router = router;
-        }
-
-        @Override
-        public RpcRoutingContext getIdentifier() {
-            return identifier;
-        }
-
-        @Override
-        public void close() throws Exception {
-
-        }
-
-        @Override
-        public Set<QName> getSupportedRpcs() {
-            return supportedRpcs;
-        }
-
-        public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
-            return new RoutedRpcRegImpl(rpcType, implementation, this);
-        }
-
-        @Override
-        public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
-            CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input"));
-            checkArgument(inputContainer != null, "Rpc payload must contain input element");
-            SimpleNode<?> routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf());
-            checkArgument(routeContainer != null, "Leaf %s must be set with value", strategy.getLeaf());
-            Object route = routeContainer.getValue();
-            checkArgument(route instanceof InstanceIdentifier,
-                          "The routed node %s is not an instance identifier", route);
-            RpcImplementation potential = null;
-            if (route != null) {
-                RoutedRpcRegImpl potentialReg = implementations.get(route);
-                if (potentialReg != null) {
-                    potential = potentialReg.getInstance();
-                }
-            }
-            if (potential == null) {
-                return router.invokeRpc(rpc, (InstanceIdentifier) route, input);
-            }
-            checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route);
-            return potential.invokeRpc(rpc, input);
-        }
-
-        public void addPath(QName context, InstanceIdentifier path, RoutedRpcRegImpl routedRpcRegImpl) {
-            //checkArgument(strategy.getContext().equals(context),"Supplied context is not supported.");
-            RoutedRpcRegImpl previous = implementations.put(path, routedRpcRegImpl);
-            if (previous == null) {
-                router.notifyPathAnnouncement(context,strategy.getIdentifier(), path);
-            }
-
-        }
-
-        public void removePath(QName context, InstanceIdentifier path, RoutedRpcRegImpl routedRpcRegImpl) {
-            boolean removed = implementations.remove(path, routedRpcRegImpl);
-            if (removed) {
-                router.notifyPathWithdrawal(context, strategy.getIdentifier(), path);
-            }
-        }
-    }
-
-    private static class GlobalRpcRegistration extends AbstractObjectRegistration<RpcImplementation> implements
-            RpcRegistration {
-        private final QName type;
-        private SchemaAwareRpcBroker router;
-
-        public GlobalRpcRegistration(QName type, RpcImplementation instance, SchemaAwareRpcBroker router) {
-            super(instance);
-            this.type = type;
-            this.router = router;
-        }
-
-        @Override
-        public QName getType() {
-            return type;
-        }
-
-        @Override
-        protected void removeRegistration() {
-            if (router != null) {
-                router.remove(this);
-                router = null;
-            }
-        }
-    }
-
-    private static class RoutedRpcRegImpl extends AbstractObjectRegistration<RpcImplementation> implements
-            RoutedRpcRegistration {
-
-        private final QName type;
-        private final RoutedRpcSelector router;
-
-        public RoutedRpcRegImpl(QName rpcType, RpcImplementation implementation, RoutedRpcSelector routedRpcSelector) {
-            super(implementation);
-            this.type = rpcType;
-            router = routedRpcSelector;
-        }
-
-        @Override
-        public void registerPath(QName context, InstanceIdentifier path) {
-            router.addPath(context, path, this);
-        }
-
-        @Override
-        public void unregisterPath(QName context, InstanceIdentifier path) {
-            router.removePath(context, path, this);
-        }
-
-        @Override
-        protected void removeRegistration() {
-
-        }
-
-        @Override
-        public QName getType() {
-            return type;
-        }
-
-    }
-
-    private void remove(GlobalRpcRegistration registration) {
+    void remove(final GlobalRpcRegistration registration) {
         implementations.remove(registration.getType(), registration);
     }
 
-    private void notifyPathAnnouncement(QName context, QName identifier, InstanceIdentifier path) {
+    void notifyPathAnnouncement(final QName context, final QName identifier, final InstanceIdentifier path) {
         RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier);
         RouteChange<RpcRoutingContext, InstanceIdentifier> change = RoutingUtils.announcementChange(contextWrapped , path);
         for(ListenerRegistration<RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> routeListener : routeChangeListeners) {
@@ -451,15 +233,12 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
                 routeListener.getInstance().onRouteChange(change);
             } catch (Exception e) {
                 LOG.error("Unhandled exception during invoking onRouteChange for {}",routeListener.getInstance(),e);
-
             }
         }
 
     }
 
-
-
-    private void notifyPathWithdrawal(QName context,QName identifier, InstanceIdentifier path) {
+    void notifyPathWithdrawal(final QName context,final QName identifier, final InstanceIdentifier path) {
         RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier);
         RouteChange<RpcRoutingContext, InstanceIdentifier> change = RoutingUtils.removalChange(contextWrapped , path);
         for(ListenerRegistration<RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> routeListener : routeChangeListeners) {
@@ -473,7 +252,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
 
     @Override
     public <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
-            L listener) {
+            final L listener) {
         ListenerRegistration<L> reg = routeChangeListeners.registerWithType(listener);
         RouteChange<RpcRoutingContext, InstanceIdentifier> initial = createInitialRouteChange();
         try {
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/broker/spi/rpc/RpcRoutingStrategy.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/broker/spi/rpc/RpcRoutingStrategy.java
new file mode 100644 (file)
index 0000000..81203c5
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.broker.spi.rpc;
+
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+
+import com.google.common.base.Optional;
+
+public abstract class RpcRoutingStrategy implements Identifiable<QName> {
+
+    private final QName identifier;
+    private static final QName CONTEXT_REFERENCE = QName.create("urn:opendaylight:yang:extension:yang-ext",
+            "2013-07-09", "context-reference");
+
+    private RpcRoutingStrategy(final QName identifier) {
+        super();
+        this.identifier = identifier;
+    }
+
+    /**
+     * Returns leaf QName in which RPC Route is stored
+     *
+     *
+     * @return leaf QName in which RPC Route is stored
+     * @throws UnsupportedOperationException If RPC is not content routed.
+     *  ({@link #isContextBasedRouted()} returned <code>false</code>)
+     */
+    public abstract QName getLeaf();
+
+    /**
+     * Returns identity QName which represents RPC Routing context
+     *
+     * @return identity QName which represents RPC Routing context
+     * @throws UnsupportedOperationException If RPC is not content routed.
+     *  ({@link #isContextBasedRouted()} returned <code>false</code>)
+     */
+    public abstract QName getContext();
+
+    @Override
+    public QName getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * Returns true if RPC is routed by context.
+     *
+     * @return true if RPC is routed by content.
+     */
+    public abstract boolean isContextBasedRouted();
+
+    public static RpcRoutingStrategy from(final RpcDefinition rpc) {
+        ContainerSchemaNode input = rpc.getInput();
+        if (input != null) {
+            for (DataSchemaNode schemaNode : input.getChildNodes()) {
+                Optional<QName> context = getRoutingContext(schemaNode);
+                if (context.isPresent()) {
+                    return createRoutedStrategy(rpc, context.get(), schemaNode.getQName());
+                }
+            }
+        }
+        return createGlobalStrategy(rpc);
+    }
+
+    public static  Optional<QName> getRoutingContext(final DataSchemaNode schemaNode) {
+        for (UnknownSchemaNode extension : schemaNode.getUnknownSchemaNodes()) {
+            if (CONTEXT_REFERENCE.equals(extension.getNodeType())) {
+                return Optional.fromNullable(extension.getQName());
+            }
+        }
+        return Optional.absent();
+    }
+
+    private static RpcRoutingStrategy createRoutedStrategy(final RpcDefinition rpc, final QName context, final QName leafNode) {
+        return new RoutedRpcStrategy(rpc.getQName(), context, leafNode);
+    }
+
+
+
+    private static RpcRoutingStrategy createGlobalStrategy(final RpcDefinition rpc) {
+        GlobalRpcStrategy ret = new GlobalRpcStrategy(rpc.getQName());
+        return ret;
+    }
+
+    private static class RoutedRpcStrategy extends RpcRoutingStrategy {
+
+        final QName context;
+        private final QName leaf;
+
+        private RoutedRpcStrategy(final QName identifier, final QName ctx, final QName leaf) {
+            super(identifier);
+            this.context = ctx;
+            this.leaf = leaf;
+        }
+
+        @Override
+        public QName getContext() {
+            return context;
+        }
+
+        @Override
+        public QName getLeaf() {
+            return leaf;
+        }
+
+        @Override
+        public boolean isContextBasedRouted() {
+            return true;
+        }
+    }
+
+    private static class GlobalRpcStrategy extends RpcRoutingStrategy {
+
+        public GlobalRpcStrategy(final QName identifier) {
+            super(identifier);
+        }
+
+        @Override
+        public boolean isContextBasedRouted() {
+            return false;
+        }
+
+        @Override
+        public QName getContext() {
+            throw new UnsupportedOperationException("Not routed strategy does not have context.");
+        }
+
+        @Override
+        public QName getLeaf() {
+            throw new UnsupportedOperationException("Not routed strategy does not have context.");
+        }
+    }
+}
\ No newline at end of file
index 9fa68eeea6f87c7f1a4cb4634b0759a61cc2f83e..8045f8cb4a9556160b44fb46d4d3bbc12374435a 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.controller.sal.connect.netconf.listener;
 
 import java.util.ArrayDeque;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Queue;
@@ -26,16 +25,14 @@ import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguratio
 import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.connect.api.RemoteDevice;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
-import org.opendaylight.controller.sal.connect.util.FailedRpcResult;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -86,9 +83,9 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
                                            final NetconfClientConfiguration config) {
         if(config instanceof NetconfReconnectingClientConfiguration) {
             dispatch.createReconnectingClient((NetconfReconnectingClientConfiguration) config);
+        } else {
+            dispatch.createClient(config);
         }
-
-        dispatch.createClient(config);
     }
 
     private void tearDown( String reason ) {
@@ -140,9 +137,10 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
 
     private RpcResult<NetconfMessage> createErrorRpcResult( RpcError.ErrorType errorType, String message )
     {
-        return new FailedRpcResult<NetconfMessage>( RpcErrors.getRpcError( null,
-                NetconfDocumentedException.ErrorTag.operation_failed.getTagValue(),
-                null, RpcError.ErrorSeverity.ERROR, message, errorType, null ) );
+        return RpcResultBuilder.<NetconfMessage>failed()
+                .withError( errorType, NetconfDocumentedException.ErrorTag.operation_failed.getTagValue(),
+                            message )
+                .build();
     }
 
     @Override
@@ -208,8 +206,8 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
                 logger.warn( "{}: Invalid request-reply match, reply message contains different message-id, request: {}, response: {}",
                              id, msgToS( request.request ), msgToS( message ), e );
 
-                request.future.set( new FailedRpcResult<NetconfMessage>(
-                                                           NetconfMessageTransformUtil.toRpcError( e ) ) );
+                request.future.set( RpcResultBuilder.<NetconfMessage>failed()
+                        .withRpcError( NetconfMessageTransformUtil.toRpcError( e ) ).build() );
                 return;
             }
 
@@ -220,12 +218,12 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
                 logger.warn( "{}: Error reply from remote device, request: {}, response: {}", id,
                              msgToS( request.request ), msgToS( message ), e );
 
-                request.future.set( new FailedRpcResult<NetconfMessage>(
-                                                          NetconfMessageTransformUtil.toRpcError( e ) ) );
+                request.future.set( RpcResultBuilder.<NetconfMessage>failed()
+                        .withRpcError( NetconfMessageTransformUtil.toRpcError( e ) ).build() );
                 return;
             }
 
-            request.future.set(Rpcs.getRpcResult( true, message, Collections.<RpcError>emptySet() ) );
+            request.future.set( RpcResultBuilder.<NetconfMessage>success( message ).build() );
         }
     }
 
index 8b6ac7d5671643cdad49babaecd0026de338f9c6..26c6a2758cc10beb574df359ccb6707dd41e319b 100644 (file)
@@ -11,12 +11,11 @@ import java.util.concurrent.ExecutionException;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.connect.util.FailedRpcResult;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -74,8 +73,8 @@ public final class NetconfDeviceCommitHandler implements DataCommitHandler<Insta
 
         @Override
         public RpcResult<Void> finish() throws IllegalStateException {
-            return new FailedRpcResult<>(RpcErrors.getRpcError(null, null, null, RpcError.ErrorSeverity.ERROR,
-                    id + ": Unexpected operation error during pre-commit operations", RpcError.ErrorType.APPLICATION, e));
+            return RpcResultBuilder.<Void>failed().withError( RpcError.ErrorType.APPLICATION,
+                    id + ": Unexpected operation error during pre-commit operations", e ).build();
         }
 
         @Override
index 6a62b1e20bba755367111924f78a49a6e2de7d5c..8d5b7aed2f4482b7730d764598e2fd56f44c25a1 100644 (file)
@@ -9,17 +9,19 @@ package org.opendaylight.controller.sal.connect.netconf.sal;
 
 import com.google.common.base.Function;
 import com.google.common.util.concurrent.Futures;
+
 import java.util.Collections;
 import java.util.Set;
 
 import javax.annotation.Nullable;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -66,7 +68,8 @@ public final class NetconfDeviceRpc implements RpcImplementation {
         if (netconfMessageRpcResult.isSuccessful()) {
             return transformer.toRpcResult(netconfMessageRpcResult.getResult(), rpc);
         } else {
-            return Rpcs.getRpcResult(false, netconfMessageRpcResult.getErrors());
+            return RpcResultBuilder.<CompositeNode> failed()
+                                      .withRpcErrors(netconfMessageRpcResult.getErrors()).build();
         }
     }
 
index 01af84c9acf72057ec02b4b9123525f81cf00cd7..fc54bfbc3d8f0b93ec58d9df664b26815a500184 100644 (file)
@@ -7,9 +7,9 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.sal;
 
+import com.google.common.base.Preconditions;
 import java.util.Collection;
 import java.util.Collections;
-
 import java.util.concurrent.ExecutorService;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
@@ -23,8 +23,6 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 final class NetconfDeviceSalProvider implements AutoCloseable, Provider, BindingAwareProvider {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfDeviceSalProvider.class);
@@ -41,13 +39,13 @@ final class NetconfDeviceSalProvider implements AutoCloseable, Provider, Binding
 
     public MountProvisionInstance getMountInstance() {
         Preconditions.checkState(mountInstance != null,
-                "%s: Sal provider was not initialized by sal. Cannot publish notification", id);
+                "%s: Sal provider was not initialized by sal. Cannot get mount instance", id);
         return mountInstance;
     }
 
     public NetconfDeviceDatastoreAdapter getDatastoreAdapter() {
         Preconditions.checkState(datastoreAdapter != null,
-                "%s: Sal provider %s was not initialized by sal. Cannot publish notification", id);
+                "%s: Sal provider %s was not initialized by sal. Cannot get datastore adapter", id);
         return datastoreAdapter;
     }
 
index 1737b8234a610267c9aa7f82eddd7a1f9912f502..0ef76d330dbab15d908401a695e61ba25b0d1802 100644 (file)
@@ -33,14 +33,13 @@ import java.util.concurrent.ExecutionException;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
-import org.opendaylight.controller.sal.connect.util.FailedRpcResult;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
@@ -211,8 +210,8 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
             throw new RuntimeException(id + ": Interrupted while waiting for response", e);
         } catch (final ExecutionException e) {
             LOG.warn("{}: Failed to finish commit operation", id, e);
-            return new FailedRpcResult<>(RpcErrors.getRpcError(null, null, null, RpcError.ErrorSeverity.ERROR,
-                    id + ": Unexpected operation error during commit operation", RpcError.ErrorType.APPLICATION, e));
+            return RpcResultBuilder.<Void>failed().withError( RpcError.ErrorType.APPLICATION,
+                            id + ": Unexpected operation error during commit operation", e ).build();
         }
     }
 
index f9e6239bed3dd4ed03cceacbfb0cb8fde1228bd9..80d0f67ac49c72b47d35e6ca094ec4610099c1b1 100644 (file)
@@ -8,18 +8,19 @@
 package org.opendaylight.controller.sal.connect.netconf.schema.mapping;
 
 import com.google.common.base.Optional;
-import java.util.Collections;
+
 import java.util.List;
 import java.util.Set;
+
 import javax.activation.UnsupportedDataTypeException;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.controller.sal.connect.util.MessageCounter;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
@@ -90,7 +91,7 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
             return toRpcResult(message, rpc, schemaContext.get());
         } else {
             final CompositeNode node = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
-            return Rpcs.getRpcResult(true, node, Collections.<RpcError>emptySet());
+            return RpcResultBuilder.success( node ).build();
         }
     }
 
@@ -114,7 +115,7 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
             compositeNode = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
         }
 
-        return Rpcs.getRpcResult(true, compositeNode, Collections.<RpcError> emptySet());
+        return RpcResultBuilder.success( compositeNode ).build();
     }
 
     @Override
index 0ea3d6a35ac74c873d3965a3a1d90e7c514aa99b..0aeec64690d971abfa7f74b1bd58385e669163fe 100644 (file)
@@ -27,9 +27,9 @@ import javax.annotation.Nullable;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -140,9 +140,14 @@ public class NetconfMessageTransformUtil {
             }
         }
 
-        return RpcErrors.getRpcError( null, ex.getErrorTag().getTagValue(), infoBuilder.toString(),
-                toRpcErrorSeverity( ex.getErrorSeverity() ), ex.getLocalizedMessage(),
-                toRpcErrorType( ex.getErrorType() ), ex.getCause() );
+        ErrorSeverity severity = toRpcErrorSeverity( ex.getErrorSeverity() );
+        return severity == ErrorSeverity.ERROR ?
+                    RpcResultBuilder.newError(
+                        toRpcErrorType( ex.getErrorType() ), ex.getErrorTag().getTagValue(),
+                        ex.getLocalizedMessage(), null, infoBuilder.toString(), ex.getCause() ) :
+                    RpcResultBuilder.newWarning(
+                        toRpcErrorType( ex.getErrorType() ), ex.getErrorTag().getTagValue(),
+                        ex.getLocalizedMessage(), null, infoBuilder.toString(), ex.getCause() );
     }
 
     private static ErrorSeverity toRpcErrorSeverity( final NetconfDocumentedException.ErrorSeverity severity ) {
@@ -181,7 +186,7 @@ public class NetconfMessageTransformUtil {
                     .addAll(Collections2.filter(node.getValue(), new Predicate<Node<?>>() {
                         @Override
                         public boolean apply(@Nullable final Node<?> input) {
-                            return input.getNodeType() != inputQName;
+                            return !inputQName.equals(input.getNodeType());
                         }
                     })) //
                     .build();
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/util/FailedRpcResult.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/util/FailedRpcResult.java
deleted file mode 100644 (file)
index 49b16d4..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.connect.util;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public final class FailedRpcResult<T> implements RpcResult<T> {
-
-    private final RpcError rpcError;
-
-    public FailedRpcResult(final RpcError rpcError) {
-        this.rpcError = rpcError;
-    }
-
-    @Override
-    public boolean isSuccessful() {
-        return false;
-    }
-
-    @Override
-    public T getResult() {
-        return null;
-    }
-
-    @Override
-    public Collection<RpcError> getErrors() {
-        return Collections.singletonList(rpcError);
-    }
-}
index c1b9f7b47ba8b8009b620655a729703e1809346f..ec2a820daab098618461d617155fa6804a369326 100644 (file)
@@ -27,7 +27,6 @@ import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
@@ -38,8 +37,8 @@ import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransf
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -65,8 +64,8 @@ public class NetconfDeviceTest {
         }
     }
 
-    private static final  RpcResult<NetconfMessage> rpcResult = Rpcs.getRpcResult(true, netconfMessage, Collections.<RpcError>emptySet());
-    private static final  RpcResult<CompositeNode> rpcResultC = Rpcs.getRpcResult(true, compositeNode, Collections.<RpcError>emptySet());
+    private static final  RpcResult<NetconfMessage> rpcResult = RpcResultBuilder.success(netconfMessage).build();
+    private static final  RpcResult<CompositeNode> rpcResultC = RpcResultBuilder.success(compositeNode).build();
 
     public static final String TEST_NAMESPACE = "test:namespace";
     public static final String TEST_MODULE = "test-module";
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToRpcRequestTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToRpcRequestTest.java
new file mode 100644 (file)
index 0000000..18a3b9f
--- /dev/null
@@ -0,0 +1,81 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+/**
+ * Test case for reported bug 1355
+ *
+ * @author Lukas Sedlak
+ * @see <a
+ *      https://bugs.opendaylight.org/show_bug.cgi?id=1355</a>
+ */
+public class NetconfToRpcRequestTest {
+
+    private String TEST_MODEL_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
+    private String REVISION = "2014-07-14";
+    private QName INPUT_QNAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "input");
+    private QName STREAM_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "stream-name");
+    private QName RPC_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "subscribe");
+
+    NetconfMessageTransformer messageTransformer;
+
+    @SuppressWarnings("deprecation")
+    @Before
+    public void setup() throws Exception {
+        final List<InputStream> modelsToParse = Collections
+            .singletonList(getClass().getResourceAsStream("/schemas/rpc-notification-subscription.yang"));
+        final YangContextParser parser = new YangParserImpl();
+        final Set<Module> modules = parser.parseYangModelsFromStreams(modelsToParse);
+        assertTrue(!modules.isEmpty());
+        final SchemaContext schemaContext = parser.resolveSchemaContext(modules);
+        assertNotNull(schemaContext);
+
+        messageTransformer = new NetconfMessageTransformer();
+        messageTransformer.onGlobalContextUpdated(schemaContext);
+    }
+
+    @Test
+    public void test() throws Exception {
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(RPC_NAME);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(INPUT_QNAME);
+        inputBuilder.addLeaf(STREAM_NAME, "NETCONF");
+
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final CompositeNode flattenedNode = NetconfMessageTransformUtil.flattenInput(root);
+        assertNotNull(flattenedNode);
+        assertEquals(1, flattenedNode.size());
+
+        final List<CompositeNode> inputNode = flattenedNode.getCompositesByName(INPUT_QNAME);
+        assertNotNull(inputNode);
+        assertTrue(inputNode.isEmpty());
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(RPC_NAME, root);
+        assertNotNull(message);
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/rpc-notification-subscription.yang b/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/rpc-notification-subscription.yang
new file mode 100644 (file)
index 0000000..b13d90f
--- /dev/null
@@ -0,0 +1,38 @@
+module rpc-notification-subscription {
+
+  namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
+  prefix "rpc";
+
+  organization
+    "Cisco Systems, Inc.";
+
+  contact
+    "lsedlak@cisco.com";
+
+  description
+    "Test model for testing of rpc INPUT parameter during subscription call.";
+
+  revision 2014-07-14 {
+    description
+      "Initial revision.";
+  }
+
+  rpc subscribe {
+    description
+      "Test rpc to init subscription";
+
+    input {
+      leaf stream-name {
+        type string;
+        default "NETCONF";
+        description
+          "Optional stream name param.";
+      }
+
+      anyxml data {
+        description
+          "Optional additional data.";
+      }
+    }
+  }
+}
\ No newline at end of file
index a2c228788f3a27659ae5a2db56f31dfb136d8886..ead1740ffd8befb557d85688b4a443f7edfd1134 100644 (file)
@@ -8,12 +8,13 @@
 package org.opendaylight.controller.sal.restconf.impl;
 
 import com.google.common.util.concurrent.Futures;
-import java.util.Collections;
+
 import java.util.concurrent.Future;
+
 import javax.ws.rs.core.Response.Status;
+
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
@@ -24,8 +25,8 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -176,8 +177,8 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
         LOG.info("Delete Configuration via Restconf: {}", path);
         CompositeNode redDataAtPath = transaction.readConfigurationData(path);
         if (redDataAtPath == null) {
-            return Futures.immediateFuture(Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
-                    Collections.<RpcError> emptyList()));
+            return Futures.immediateFuture(RpcResultBuilder.<TransactionStatus>
+                                                    success(TransactionStatus.COMMITED).build());
         }
         transaction.removeConfigurationData(path);
         return transaction.commit();
index d12bf9e44efa96be39b2dea863c2339e74e8577b..313b766ed3312bad6cb5f74a542e84893226aa54 100644 (file)
@@ -36,8 +36,7 @@ import javax.ws.rs.core.UriInfo;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
+
 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
@@ -50,8 +49,8 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
@@ -112,7 +111,7 @@ public class InvokeRpcMethodTest {
         CompositeNode payload = preparePayload();
 
         when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(
-                Futures.<RpcResult<CompositeNode>> immediateFuture(Rpcs.<CompositeNode> getRpcResult(true)));
+                Futures.<RpcResult<CompositeNode>> immediateFuture(RpcResultBuilder.<CompositeNode>success().build()));
 
         StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", payload, uriInfo);
         assertTrue(structData == null);
@@ -132,7 +131,7 @@ public class InvokeRpcMethodTest {
 
     @Test
     public void testInvokeRpcWithNoPayloadRpc_FailNoErrors() {
-        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(false);
+        RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>failed().build();
 
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
         when(
@@ -177,11 +176,13 @@ public class InvokeRpcMethodTest {
 
     @Test
     public void testInvokeRpcWithNoPayloadRpc_FailWithRpcError() {
-        List<RpcError> rpcErrors = Arrays.asList(RpcErrors.getRpcError(null, "bogusTag", null, ErrorSeverity.ERROR,
-                "foo", RpcError.ErrorType.TRANSPORT, null), RpcErrors.getRpcError("app-tag", "in-use", null,
-                ErrorSeverity.WARNING, "bar", RpcError.ErrorType.RPC, null));
+        List<RpcError> rpcErrors = Arrays.asList(
+            RpcResultBuilder.newError( RpcError.ErrorType.TRANSPORT, "bogusTag", "foo" ),
+            RpcResultBuilder.newWarning( RpcError.ErrorType.RPC, "in-use", "bar",
+                                         "app-tag", null, null ) );
 
-        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(false, rpcErrors);
+        RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>failed()
+                                                              .withRpcErrors(rpcErrors).build();
 
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
         when(
@@ -205,7 +206,7 @@ public class InvokeRpcMethodTest {
 
     @Test
     public void testInvokeRpcWithNoPayload_Success() {
-        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true);
+        RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
 
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
         when(
@@ -246,7 +247,7 @@ public class InvokeRpcMethodTest {
 
     @Test
     public void testInvokeRpcMethodWithInput() {
-        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true);
+        RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
 
         CompositeNode payload = mock(CompositeNode.class);
 
@@ -279,8 +280,8 @@ public class InvokeRpcMethodTest {
     @Test
     public void testInvokeRpcWithNoPayloadWithOutput_Success() {
         CompositeNode compositeNode = mock(CompositeNode.class);
-        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true, compositeNode,
-                Collections.<RpcError> emptyList());
+        RpcResult<CompositeNode> rpcResult =
+                                  RpcResultBuilder.<CompositeNode>success(compositeNode).build();
 
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
         when(
@@ -299,7 +300,7 @@ public class InvokeRpcMethodTest {
 
     @Test
     public void testMountedRpcCallNoPayload_Success() throws Exception {
-        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true);
+        RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
 
         ListenableFuture<RpcResult<CompositeNode>> mockListener = mock(ListenableFuture.class);
         when(mockListener.get()).thenReturn(rpcResult);
index 1442338e2c24292b181645e3e7e06005f206a112..af9dd283594ea3943f9265e5a2ecade495a85e7f 100644 (file)
@@ -37,7 +37,6 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountService;
 import org.opendaylight.controller.sal.rest.api.Draft02;
@@ -52,7 +51,7 @@ import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -125,10 +124,10 @@ public class RestPostOperationTest extends JerseyTest {
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
         List<RpcError> rpcErrors = new ArrayList<>();
-        rpcErrors.add(RpcErrors.getRpcError("applicationTag1", "tag1", "info1", ErrorSeverity.ERROR, "message1",
-                ErrorType.RPC, null));
-        rpcErrors.add(RpcErrors.getRpcError("applicationTag2", "tag2", "info2", ErrorSeverity.WARNING, "message2",
-                ErrorType.PROTOCOL, null));
+        rpcErrors.add( RpcResultBuilder.newError( ErrorType.RPC, "tag1", "message1",
+                                                  "applicationTag1", "info1", null ) );
+        rpcErrors.add( RpcResultBuilder.newWarning( ErrorType.PROTOCOL, "tag2", "message2",
+                                                    "applicationTag2", "info2", null ) );
         mockInvokeRpc(null, false, rpcErrors);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
index f0d3fb6822874c332f27307971b909f19ea034e9..18311104a41f9761dd5bede15965df9625ea061b 100644 (file)
@@ -11,7 +11,6 @@ import static org.hamcrest.CoreMatchers.equalTo;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
-import static org.opendaylight.controller.sal.common.util.RpcErrors.getRpcError;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -23,6 +22,7 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfError;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 /**
  * Unit tests for RestconfError.
@@ -144,41 +144,41 @@ public class RestconfErrorTest {
     public void testRestConfErrorWithRpcError() {
 
         // All fields set
-        RpcError rpcError = getRpcError("mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(), "mock error-info",
-                RpcError.ErrorSeverity.ERROR, "mock error-message", RpcError.ErrorType.PROTOCOL, new Exception(
-                        "mock cause"));
+        RpcError rpcError = RpcResultBuilder.newError(
+                RpcError.ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE.getTagValue(), "mock error-message",
+                "mock app-tag", "mock error-info", new Exception( "mock cause" ) );
 
         validateRestConfError("mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE, "mock app-tag",
                 "mock error-info", new RestconfError(rpcError));
 
         // All fields set except 'info' - expect error-info set to 'cause'
-        rpcError = getRpcError("mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(), null,
-                RpcError.ErrorSeverity.ERROR, "mock error-message", RpcError.ErrorType.PROTOCOL, new Exception(
-                        "mock cause"));
+        rpcError = RpcResultBuilder.newError(
+                RpcError.ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE.getTagValue(), "mock error-message",
+                "mock app-tag", null, new Exception( "mock cause" ) );
 
         validateRestConfError("mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE, "mock app-tag",
                 new Contains("mock cause"), new RestconfError(rpcError));
 
         // Some fields set - expect error-info set to ErrorSeverity
-        rpcError = getRpcError(null, ErrorTag.ACCESS_DENIED.getTagValue(), null, RpcError.ErrorSeverity.ERROR, null,
-                RpcError.ErrorType.RPC, null);
+        rpcError = RpcResultBuilder.newError(
+                RpcError.ErrorType.RPC, ErrorTag.ACCESS_DENIED.getTagValue(), null, null, null, null );
 
         validateRestConfError(null, ErrorType.RPC, ErrorTag.ACCESS_DENIED, null, "<severity>error</severity>",
                 new RestconfError(rpcError));
 
         // 'tag' field not mapped to ErrorTag - expect error-tag set to
         // OPERATION_FAILED
-        rpcError = getRpcError(null, "not mapped", null, RpcError.ErrorSeverity.WARNING, null,
-                RpcError.ErrorType.TRANSPORT, null);
+        rpcError = RpcResultBuilder.newWarning(
+                RpcError.ErrorType.TRANSPORT, "not mapped", null, null, null, null );
 
         validateRestConfError(null, ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED, null,
                 "<severity>warning</severity>", new RestconfError(rpcError));
 
         // No fields set - edge case
-        rpcError = getRpcError(null, null, null, null, null, null, null);
+        rpcError = RpcResultBuilder.newError( null, null, null, null, null, null );
 
-        validateRestConfError(null, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, null, (String) null,
-                new RestconfError(rpcError));
+        validateRestConfError( null, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED,
+                               null, "<severity>error</severity>", new RestconfError( rpcError ) );
     }
 
     private void validateRestConfError(String expectedMessage, ErrorType expectedErrorType, ErrorTag expectedErrorTag,
diff --git a/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-routed-rpc.yang b/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-routed-rpc.yang
new file mode 100644 (file)
index 0000000..c3a9824
--- /dev/null
@@ -0,0 +1,46 @@
+module opendaylight-test-routed-rpc {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:rpc:routing";
+    prefix "rpc";
+    import yang-ext { prefix ext; }
+
+    description
+        "Test model for testing of registering rpc service on binding independent mount point 
+        and retrieving rpc service via binding aware mount point.";
+
+    revision "2014-07-01" {
+        description
+            "Initial revision";
+    }
+
+    identity test-context {
+        description "Test Context";
+    }
+    
+    typedef encapsulated-route {
+        type instance-identifier;
+    }
+    
+    grouping route-in-grouping {
+        leaf route {
+            type instance-identifier;
+            ext:context-reference test-context;
+        }
+    }
+    
+    grouping encapsulated-route-in-grouping {
+        leaf route {
+            type encapsulated-route;
+            ext:context-reference test-context;
+        }
+    }
+
+    rpc routed-simple-route {
+        input {
+            leaf route {
+                type instance-identifier;
+                ext:context-reference test-context;
+            }
+        }
+    }
+}
index 50ae8fd04fcce09c66a9eb7dd512af433df058d7..c6aa545935af5e2ae9771343706ac24a0518a363 100644 (file)
@@ -1,15 +1,12 @@
 package org.opendaylight.controller.sample.kitchen.impl;
 
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+
 import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sample.kitchen.api.EggsType;
 import org.opendaylight.controller.sample.kitchen.api.KitchenService;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
@@ -20,10 +17,10 @@ import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -89,7 +86,8 @@ public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntime
                     }
 
                     return Futures.immediateFuture(
-                              Rpcs.<Void> getRpcResult( atLeastOneSucceeded, errorList.build() ) );
+                              RpcResultBuilder.<Void> status( atLeastOneSucceeded )
+                                              .withRpcErrors( errorList.build() ).build() );
                 }
         } );
     }
@@ -102,7 +100,7 @@ public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntime
             public RpcResult<Void> call() throws Exception {
 
                 // We don't actually do anything here - just return a successful result.
-                return Rpcs.<Void> getRpcResult( true, Collections.<RpcError>emptyList() );
+                return RpcResultBuilder.<Void> success().build();
             }
         } );
     }
@@ -113,11 +111,9 @@ public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntime
         if( toasterOutOfBread )
         {
             log.info( "We're out of toast but we can make eggs" );
-            return Futures.immediateFuture( Rpcs.<Void> getRpcResult( true,
-                       Arrays.asList( RpcErrors.getRpcError( "", "partial-operation", null,
-                                          ErrorSeverity.WARNING,
-                                          "Toaster is out of bread but we can make you eggs",
-                                          ErrorType.APPLICATION, null ) ) ) );
+            return Futures.immediateFuture( RpcResultBuilder.<Void> success()
+                     .withWarning( ErrorType.APPLICATION, "partial-operation",
+                                      "Toaster is out of bread but we can make you eggs" ).build() );
         }
 
         // Access the ToasterService to make the toast.
index d2b0f90194a9a066558f6d4dca5d1d8751ec01aa..de5ddd9a75298f61d5c4ce15c00b9df0e170cc92 100644 (file)
@@ -7,9 +7,6 @@
  */
 package org.opendaylight.controller.sample.toaster.provider;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
@@ -28,8 +25,6 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.RestockToasterInput;
@@ -43,7 +38,7 @@ import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
@@ -163,8 +158,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
         }
 
         // Always return success from the cancel toast call.
-        return Futures.immediateFuture( Rpcs.<Void> getRpcResult( true,
-                                        Collections.<RpcError>emptyList() ) );
+        return Futures.immediateFuture( RpcResultBuilder.<Void> success().build() );
     }
 
     /**
@@ -181,17 +175,14 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
         return futureResult;
     }
 
-    private List<RpcError> makeToasterOutOfBreadError() {
-        return Arrays.asList(
-                RpcErrors.getRpcError( "out-of-stock", "resource-denied", null, null,
-                                       "Toaster is out of bread",
-                                       ErrorType.APPLICATION, null ) );
+    private RpcError makeToasterOutOfBreadError() {
+        return RpcResultBuilder.newError( ErrorType.APPLICATION, "resource-denied",
+                "Toaster is out of bread", "out-of-stock", null, null );
     }
 
-    private List<RpcError> makeToasterInUseError() {
-        return Arrays.asList(
-            RpcErrors.getRpcError( "", "in-use", null, ErrorSeverity.WARNING,
-                                   "Toaster is busy", ErrorType.APPLICATION, null ) );
+    private RpcError makeToasterInUseError() {
+        return RpcResultBuilder.newWarning( ErrorType.APPLICATION, "in-use",
+                "Toaster is busy", null, null, null );
     }
 
     private void checkStatusAndMakeToast( final MakeToastInput input,
@@ -225,8 +216,8 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
                         if( outOfBread() ) {
                             LOG.debug( "Toaster is out of bread" );
 
-                            return Futures.immediateFuture( Rpcs.<TransactionStatus>getRpcResult(
-                                       false, null, makeToasterOutOfBreadError() ) );
+                            return Futures.immediateFuture( RpcResultBuilder.<TransactionStatus>failed()
+                                    .withRpcError( makeToasterOutOfBreadError() ).build() );
                         }
 
                         LOG.debug( "Setting Toaster status to Down" );
@@ -244,8 +235,8 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
                     // Return an error since we are already making toast. This will get
                     // propagated to the commitFuture below which will interpret the null
                     // TransactionStatus in the RpcResult as an error condition.
-                    return Futures.immediateFuture( Rpcs.<TransactionStatus>getRpcResult(
-                            false, null, makeToasterInUseError() ) );
+                    return Futures.immediateFuture( RpcResultBuilder.<TransactionStatus>failed()
+                            .withRpcError( makeToasterInUseError() ).build() );
                 }
         } );
 
@@ -265,7 +256,8 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
                     // the read above returned ToasterStatus.Down. Either way, fail the
                     // futureResult and copy the errors.
 
-                    futureResult.set( Rpcs.<Void>getRpcResult( false, null, result.getErrors() ) );
+                    futureResult.set( RpcResultBuilder.<Void>failed().withRpcErrors(
+                                                                     result.getErrors() ).build() );
                 }
             }
 
@@ -286,10 +278,8 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
                     LOG.error( "Failed to commit Toaster status", ex );
 
                     // Got some unexpected error so fail.
-                    futureResult.set( Rpcs.<Void> getRpcResult( false, null, Arrays.asList(
-                        RpcErrors.getRpcError( null, null, null, ErrorSeverity.ERROR,
-                                               ex.getMessage(),
-                                               ErrorType.APPLICATION, ex ) ) ) );
+                    futureResult.set( RpcResultBuilder.<Void> failed()
+                                        .withError( ErrorType.APPLICATION, ex.getMessage() ).build() );
                 }
             }
         } );
@@ -312,7 +302,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
             notificationProvider.publish( reStockedNotification );
         }
 
-        return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true, Collections.<RpcError>emptyList()));
+        return Futures.immediateFuture( RpcResultBuilder.<Void> success().build() );
     }
 
     /**
@@ -416,8 +406,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
 
                     LOG.debug("Toast done");
 
-                    futureResult.set( Rpcs.<Void>getRpcResult( true, null,
-                                                          Collections.<RpcError>emptyList() ) );
+                    futureResult.set( RpcResultBuilder.<Void>success().build() );
 
                     return null;
                 }
index c770bde9206c03bba89027bc77b5fcb835e8dd03..1360a54d6fbaf2609067f1617337e8af76ec7852 100644 (file)
@@ -60,6 +60,7 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
     }
 
     private State state = State.IDLE;
+    private final Promise<S> promise;
     private final Timer timer;
     private final long connectionTimeoutMillis;
 
@@ -68,6 +69,7 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
             L sessionListener, long connectionTimeoutMillis) {
         super(promise, channel);
         this.sessionPreferences = sessionPreferences;
+        this.promise = promise;
         this.timer = timer;
         this.sessionListener = sessionListener;
         this.connectionTimeoutMillis = connectionTimeoutMillis;
@@ -106,28 +108,40 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
 
         channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ExceptionHandlingInboundChannelHandler());
 
+        // FIXME, make sessionPreferences return HelloMessage, move NetconfHelloMessage to API
+        sendMessage((NetconfHelloMessage)helloMessage);
+
+        replaceHelloMessageOutboundHandler();
+        changeState(State.OPEN_WAIT);
+
         timeout = this.timer.newTimeout(new TimerTask() {
             @Override
             public void run(final Timeout timeout) {
                 synchronized (this) {
                     if (state != State.ESTABLISHED) {
+
                         logger.debug("Connection timeout after {}, session is in state {}", timeout, state);
-                        final IllegalStateException cause = new IllegalStateException(
-                                "Session was not established after " + timeout);
-                        negotiationFailed(cause);
+
+                        // Do not fail negotiation if promise is done or canceled
+                        // It would result in setting result of the promise second time and that throws exception
+                        if (isPromiseFinished() == false) {
+                            // FIXME BUG-1365 calling "negotiation failed" closes the channel, but the channel does not get closed if data is still being transferred
+                            // Loopback connection initiation might
+                            negotiationFailed(new IllegalStateException("Session was not established after " + timeout));
+                        }
+
                         changeState(State.FAILED);
                     } else if(channel.isOpen()) {
                         channel.pipeline().remove(NAME_OF_EXCEPTION_HANDLER);
                     }
                 }
             }
-        }, connectionTimeoutMillis, TimeUnit.MILLISECONDS);
 
-        // FIXME, make sessionPreferences return HelloMessage, move NetconfHelloMessage to API
-        sendMessage((NetconfHelloMessage)helloMessage);
+            private boolean isPromiseFinished() {
+                return promise.isDone() || promise.isCancelled();
+            }
 
-        replaceHelloMessageOutboundHandler();
-        changeState(State.OPEN_WAIT);
+        }, connectionTimeoutMillis, TimeUnit.MILLISECONDS);
     }
 
     private void cancelTimeout() {
diff --git a/pom.xml b/pom.xml
index af8400242924501d0aca460e46da718327876bdb..242ab8eb89fce53b5ee7396b02790df9e96b781b 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/dummy-console</module>
     <module>opendaylight/karaf-branding</module>
     <module>opendaylight/distribution/opendaylight-karaf</module>
+    <module>features</module>
   </modules>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>