Merge "Fix for Bug 934 - issue in validations for nuetronPort creation and updatePort"
authorEd Warnicke <eaw@cisco.com>
Thu, 22 May 2014 01:08:59 +0000 (01:08 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 22 May 2014 01:08:59 +0000 (01:08 +0000)
74 files changed:
.gitignore
opendaylight/commons/opendaylight/pom.xml
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/dummy-console/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java
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/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategy.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 [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPutsTest.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java with 98% similarity]
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizationOperation.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/BackwardsCompatibleDataBroker.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingListenerInvoker.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataPreconditionFailedException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTree.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidateNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeSnapshot.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreUtils.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java with 98% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AbstractDataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java with 60% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationApplyOperation.java with 83% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/NodeModification.java with 94% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/OperationWithModification.java with 89% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java with 92% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreMetadataNode.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java with 66% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreNodeCompositeBuilder.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java with 70% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java [moved from opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationMetadataTreeTest.java with 81% similarity]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperationRoot.java with 95% similarity]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImpl.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandler.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImplTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/MockRoutingTable.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImplTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandlerTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/MessagingUtil.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/RemoteServerTestClient.java
opendaylight/md-sal/sal-rest-docgen/pom.xml
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectNameAttributeWritingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleIdentityRefAttributeWritingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java

index 6fc003be270022a4c55a2d4b2ccdb951886ccbbd..f8cf74f8263758e9cf39e2a4dbbf30d6c904628e 100644 (file)
@@ -25,3 +25,5 @@ classes
 out/
 .externalToolBuilders
 maven-eclipse.xml
+.DS_STORE
+.metadata
index 81cc16da9fc3feb51e9ef02eb379bada33293de7..89fd22d5a21e7815aa3f8e9c0b7b1c9677e18007 100644 (file)
@@ -18,8 +18,8 @@
     <aopalliance.version>1.0.0</aopalliance.version>
     <appauth.version>0.4.2-SNAPSHOT</appauth.version>
     <!-- Controller Modules Versions -->
-    <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
     <aries.util.version>1.1.0</aries.util.version>
+    <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
     <asm.version>4.1</asm.version>
     <!-- Plugin Versions -->
     <bouncycastle.version>1.50</bouncycastle.version>
         <artifactId>netconf-netty-util</artifactId>
         <version>${netconf.version}</version>
       </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>netconf-netty-util</artifactId>
-        <version>${netconf.version}</version>
-        <type>test-jar</type>
-      </dependency>
       <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <artifactId>netconf-monitoring</artifactId>
         <version>${netconf.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-netty-util</artifactId>
+        <version>${netconf.version}</version>
+        <type>test-jar</type>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>netconf-ssh</artifactId>
         <artifactId>concepts</artifactId>
         <version>${yangtools.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>object-cache-api</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>object-cache-guava</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.yangtools</groupId>
         <artifactId>restconf-client-api</artifactId>
index 377785ac41a21b4013587303cd64c68211baf1ea..31cdedd5724f89a0da51f2880219b765562b1605 100644 (file)
       <version>${karaf.version}</version>
       <type>kar</type>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
     <!-- scope is runtime so the feature repo is listed in the features
       service config file, and features may be installed using the
       karaf-maven-plugin configuration -->
       <type>kar</type>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-features</artifactId>
+      <version>${config.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
     <!--<dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>base-features</artifactId>
index 04818e78c61a10e636a9b5a2ce9fdf42b8ab1910..48e661f196370f1497429f805312853d9b7e1bf7 100644 (file)
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>concepts</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>object-cache-api</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>object-cache-guava</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>restconf-client-api</artifactId>
index 6d90eb39dad12dcc598aa82e3935ced0443c4fe2..8901c2e0b5777cb22c81e1431f3fa10498c746be 100644 (file)
@@ -16,7 +16,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>${bundle.plugin.version}</version>
         <extensions>true</extensions>
         <configuration>
           <instructions>
index 00ce31233578f4774c7d854442092408df542489..57682bc6c978c82084a00f6c3834c1d1f5e215f3 100644 (file)
@@ -11,13 +11,17 @@ import java.util.Arrays
 import java.util.Dictionary
 import java.util.Hashtable
 import org.apache.felix.dm.Component
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext
-import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider
 import org.opendaylight.controller.sal.binding.api.NotificationService
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter
 import org.opendaylight.controller.sal.compatibility.topology.TopologyAdapter
+import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase
 import org.opendaylight.controller.sal.core.Node
 import org.opendaylight.controller.sal.core.NodeConnector
@@ -26,6 +30,7 @@ import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerSer
 import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService
 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService
 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService
+import org.opendaylight.controller.sal.packet.IPluginInDataPacketService
 import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService
 import org.opendaylight.controller.sal.reader.IPluginInReadService
 import org.opendaylight.controller.sal.reader.IPluginOutReadService
@@ -34,22 +39,15 @@ import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
 import org.opendaylight.controller.sal.utils.GlobalConstants
 import org.opendaylight.controller.sal.utils.INodeConnectorFactory
 import org.opendaylight.controller.sal.utils.INodeFactory
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices
-import org.opendaylight.controller.sal.packet.IPluginInDataPacketService
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService
 import org.osgi.framework.BundleContext
 
 import static org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider
-import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
 
 class ComponentActivator extends ComponentActivatorAbstractBase {
 
index f54defdf14498960fc73726b541f6775f0110362..8908504f15171ebe2018ee5feb4915fe199b67a6 100644 (file)
@@ -10,11 +10,13 @@ package org.opendaylight.controller.sal.compatibility
 import java.util.ArrayList
 import java.util.Collections
 import java.util.List
+import java.util.Map
 import java.util.Set
-import java.util.ArrayList;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.CopyOnWriteArrayList
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
 import org.opendaylight.controller.sal.core.Edge
@@ -76,10 +78,6 @@ import org.slf4j.LoggerFactory
 
 import static extension org.opendaylight.controller.sal.common.util.Arguments.*
 import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import java.util.concurrent.ConcurrentHashMap
-import java.util.Map
-import java.util.HashMap
 
 class InventoryAndReadAdapter implements IPluginInReadService,
                                              IPluginInInventoryService,
index 9a19e104173d11a41d449e450e5d7bb3f43e092f..2d490564e1a8e4a99f31b7eb86a361f6aea3c71a 100644 (file)
@@ -8,9 +8,9 @@
 package org.opendaylight.controller.sal.compatibility.topology
 
 import com.google.common.collect.FluentIterable
-import java.util.Collections
 import java.util.List
 import java.util.concurrent.CopyOnWriteArrayList
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
 import org.opendaylight.controller.sal.core.ConstructionException
 import org.opendaylight.controller.sal.core.Edge
 import org.opendaylight.controller.sal.core.Node
@@ -21,13 +21,12 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.slf4j.LoggerFactory
 
 import static com.google.common.base.Preconditions.*
+
 import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
-import org.slf4j.LoggerFactory
 
 class TopologyMapping {
     private static val LOG = LoggerFactory.getLogger(TopologyMapping);
index 63c5664a0c4b2de63e5b6e90279eb59f37e050ef..81ccb35cd982070bc85a7845dfa10d8787f8e450 100644 (file)
@@ -10,8 +10,8 @@ package org.opendaylight.controller.sal.compatibility.test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
 
@@ -19,17 +19,53 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.junit.Test;
-import org.opendaylight.controller.sal.action.*;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.Flood;
+import org.opendaylight.controller.sal.action.FloodAll;
+import org.opendaylight.controller.sal.action.HwPath;
+import org.opendaylight.controller.sal.action.Loopback;
+import org.opendaylight.controller.sal.action.PopVlan;
+import org.opendaylight.controller.sal.action.PushVlan;
+import org.opendaylight.controller.sal.action.SetDlDst;
+import org.opendaylight.controller.sal.action.SetDlSrc;
+import org.opendaylight.controller.sal.action.SetDlType;
+import org.opendaylight.controller.sal.action.SetNextHop;
+import org.opendaylight.controller.sal.action.SetNwDst;
+import org.opendaylight.controller.sal.action.SetNwSrc;
+import org.opendaylight.controller.sal.action.SetNwTos;
+import org.opendaylight.controller.sal.action.SetTpDst;
+import org.opendaylight.controller.sal.action.SetTpSrc;
+import org.opendaylight.controller.sal.action.SetVlanCfi;
+import org.opendaylight.controller.sal.action.SetVlanId;
+import org.opendaylight.controller.sal.action.SetVlanPcp;
+import org.opendaylight.controller.sal.action.SwPath;
 import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
 import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
@@ -140,7 +176,7 @@ public class TestFromSalConversionsUtils {
             if (layer4Match instanceof SctpMatch) {
                 assertEquals("Sctp source port is incorrect.", 0xffff, (int) ((SctpMatch) layer4Match)
                         .getSctpSourcePort().getValue());
-                assertEquals("Sctp dest port is incorrect.", (int) 0xfffe, (int) ((SctpMatch) layer4Match)
+                assertEquals("Sctp dest port is incorrect.", 0xfffe, (int) ((SctpMatch) layer4Match)
                         .getSctpDestinationPort().getValue());
                 sctpFound = true;
             }
@@ -151,9 +187,9 @@ public class TestFromSalConversionsUtils {
             assertEquals("Wrong protocol", TCP, match.getIpMatch().getIpProtocol().byteValue());
             layer4Match = match.getLayer4Match();
             if (layer4Match instanceof TcpMatch) {
-                assertEquals("Tcp source port is incorrect.", (int) 0xabcd, (int) ((TcpMatch) layer4Match)
+                assertEquals("Tcp source port is incorrect.", 0xabcd, (int) ((TcpMatch) layer4Match)
                         .getTcpSourcePort().getValue());
-                assertEquals("Tcp dest port is incorrect.", (int) 0xdcba, (int) ((TcpMatch) layer4Match)
+                assertEquals("Tcp dest port is incorrect.", 0xdcba, (int) ((TcpMatch) layer4Match)
                         .getTcpDestinationPort().getValue());
                 sctpFound = true;
             }
@@ -164,9 +200,9 @@ public class TestFromSalConversionsUtils {
             assertEquals("Wrong protocol", UDP, match.getIpMatch().getIpProtocol().byteValue());
             layer4Match = match.getLayer4Match();
             if (layer4Match instanceof UdpMatch) {
-                assertEquals("Udp source port is incorrect.", (int) 0xcdef, (int) ((UdpMatch) layer4Match)
+                assertEquals("Udp source port is incorrect.", 0xcdef, (int) ((UdpMatch) layer4Match)
                         .getUdpSourcePort().getValue());
-                assertEquals("Udp dest port is incorrect.", (int) 0xfedc, (int) ((UdpMatch) layer4Match)
+                assertEquals("Udp dest port is incorrect.", 0xfedc, (int) ((UdpMatch) layer4Match)
                         .getUdpDestinationPort().getValue());
                 sctpFound = true;
             }
@@ -227,13 +263,13 @@ public class TestFromSalConversionsUtils {
                     assertEquals("Wrong value of vlad ID in PushVlanAction.", (Integer) 4095,
                             ((PushVlanActionCase) innerAction).getPushVlanAction().getVlanId().getValue());
                 } else if (innerAction instanceof SetDlDstActionCase) {
-                    assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa", 
+                    assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
                             ((SetDlDstActionCase) innerAction).getSetDlDstAction().getAddress().getValue());
                 } else if (innerAction instanceof SetDlSrcActionCase) {
-                    assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa", 
+                    assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
                             ((SetDlSrcActionCase) innerAction).getSetDlSrcAction().getAddress().getValue());
                 } else if (innerAction instanceof SetDlTypeActionCase) {
-                    assertEquals("Wrong data link type in SetDlTypeAction.", (long) 513,
+                    assertEquals("Wrong data link type in SetDlTypeAction.", 513,
                             (long) ((SetDlTypeActionCase) innerAction).getSetDlTypeAction().getDlType().getValue());
                 } else if (innerAction instanceof SetNextHopActionCase) {
                     Address address = ((SetNextHopActionCase) innerAction).getSetNextHopAction().getAddress();
index 3f9d5c78546af7b0f40111b745fe89c8fefc5c91..f1be5c6922ecda45cc75f343b3f6355e402e013d 100644 (file)
@@ -13,18 +13,17 @@ import java.util.AbstractMap.SimpleEntry;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
-import java.util.concurrent.Callable;
 
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 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.InstanceIdentifier.Item;
 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.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
@@ -44,6 +43,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
@@ -364,9 +364,9 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         } else if (List.class.isAssignableFrom(returnType)) {
             try {
                 return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
-                        new Callable<Class>() {
+                        new Supplier<Class>() {
                             @Override
-                            public Class call() {
+                            public Class get() {
                                 Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
                                         .getGenericReturnType());
                                 if (listResult instanceof Class
index ddc79ae075e7551cfd369a81795da0f040b427e6..e08e9a4e0580556d038cbe01e6de2dc0ed064735 100644 (file)
@@ -443,9 +443,6 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
     }
 
     private static class BackwardsCompatibleConfigurationDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
-
-
-        @SuppressWarnings("rawtypes")
         private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
 
         public BackwardsCompatibleConfigurationDataChangeInvoker(final DataChangeListener listener) {
index b27c80d784e39fce232ae227a752f3dd3b77ab99..5bbebe6f1b00544021bb64d5cdf0ea4bf77c82a5 100644 (file)
@@ -62,7 +62,6 @@ import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
 import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
@@ -73,12 +72,11 @@ 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.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.slf4j.Logger;
@@ -87,7 +85,6 @@ 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.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.common.util.concurrent.Futures;
@@ -736,224 +733,13 @@ public class BindingIndependentConnector implements //
                         }
                     }
                     checkState(targetMethod != null, "Rpc method not found");
-                    Optional<Class<?>> outputClass = BindingReflections.resolveRpcOutputClass(targetMethod);
-                    Optional<Class<? extends DataContainer>> inputClass = BindingReflections
-                            .resolveRpcInputClass(targetMethod);
-
-                    RpcInvocationStrategy strategy = null;
-                    if (outputClass.isPresent()) {
-                        if (inputClass.isPresent()) {
-                            strategy = new DefaultInvocationStrategy(rpc, targetMethod, outputClass.get(), inputClass
-                                    .get());
-                        } else {
-                            strategy = new NoInputInvocationStrategy(rpc, targetMethod, outputClass.get());
-                        }
-                    } else if (inputClass.isPresent()) {
-                        strategy = new NoOutputInvocationStrategy(rpc, targetMethod, inputClass.get());
-                    } else {
-                        strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod);
-                    }
-                    return strategy;
+                    return  new RpcInvocationStrategy(rpc,targetMethod, mappingService, biRpcRegistry);
                 }
 
             });
         }
     }
 
-    private abstract class RpcInvocationStrategy {
-
-        protected final Method targetMethod;
-        protected final QName rpc;
-
-        public RpcInvocationStrategy(final QName rpc, final Method targetMethod) {
-            this.targetMethod = targetMethod;
-            this.rpc = rpc;
-        }
-
-        public abstract Future<RpcResult<?>> forwardToDomBroker(DataObject input);
-
-        public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
-                throws Exception;
-
-        public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            return uncheckedInvoke(rpcService, domInput);
-        }
-    }
-
-    private class DefaultInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> inputClass;
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> outputClass;
-
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public DefaultInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass,
-                final Class<? extends DataContainer> inputClass) {
-            super(rpc, targetMethod);
-            this.outputClass = new WeakReference(outputClass);
-            this.inputClass = new WeakReference(inputClass);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
-            Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
-            if (futureResult == null) {
-                return Rpcs.getRpcResult(false);
-            }
-            RpcResult<?> bindingResult = futureResult.get();
-            final Object resultObj = bindingResult.getResult();
-            if (resultObj instanceof DataObject) {
-                final CompositeNode output = mappingService.toDataDom((DataObject) resultObj);
-                return Rpcs.getRpcResult(true, output, Collections.<RpcError> emptySet());
-            }
-            return Rpcs.getRpcResult(true);
-        }
-
-        @Override
-        public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if (biRpcRegistry == null) {
-                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
-            }
-
-            CompositeNode xml = mappingService.toDataDom(input);
-            CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-
-            return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
-                    new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
-                        @Override
-                        public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
-                            Object baResultValue = null;
-                            if (input.getResult() != null) {
-                                baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(),
-                                        input.getResult());
-                            }
-                            return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors());
-                        }
-                    });
-        }
-    }
-
-    private class NoInputInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> outputClass;
-
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public NoInputInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass) {
-            super(rpc, targetMethod);
-            this.outputClass = new WeakReference(outputClass);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
-            if (futureResult == null) {
-                return Rpcs.getRpcResult(false);
-            }
-            RpcResult<?> bindingResult = futureResult.get();
-            final Object resultObj = bindingResult.getResult();
-            if (resultObj instanceof DataObject) {
-                final CompositeNode output = mappingService.toDataDom((DataObject) resultObj);
-                return Rpcs.getRpcResult(true, output, Collections.<RpcError> emptySet());
-            }
-            return Rpcs.getRpcResult(true);
-        }
-
-        @Override
-        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if (biRpcRegistry != null) {
-                CompositeNode xml = mappingService.toDataDom(input);
-                CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-                return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
-                        new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
-                            @Override
-                            public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
-                                Object baResultValue = null;
-                                if (input.getResult() != null) {
-                                    baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(),
-                                            input.getResult());
-                                }
-                                return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors());
-                            }
-                        });
-            } else {
-                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
-            }
-        }
-    }
-
-    private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
-
-        public NoInputNoOutputInvocationStrategy(final QName rpc, final Method targetMethod) {
-            super(rpc, targetMethod);
-        }
-
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            @SuppressWarnings("unchecked")
-            Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
-            RpcResult<Void> bindingResult = result.get();
-            return Rpcs.getRpcResult(bindingResult.isSuccessful(), bindingResult.getErrors());
-        }
-
-        @Override
-        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            return Futures.immediateFuture(null);
-        }
-    }
-
-    private class NoOutputInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> inputClass;
-
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public NoOutputInvocationStrategy(final QName rpc, final Method targetMethod,
-                final Class<? extends DataContainer> inputClass) {
-            super(rpc, targetMethod);
-            this.inputClass = new WeakReference(inputClass);
-        }
-
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
-            Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
-            if (result == null) {
-                return Rpcs.getRpcResult(false);
-            }
-            RpcResult<?> bindingResult = result.get();
-            return Rpcs.getRpcResult(true);
-        }
-
-        @Override
-        public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if (biRpcRegistry == null) {
-                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
-            }
-
-            CompositeNode xml = mappingService.toDataDom(input);
-            CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-
-            return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
-                    new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
-                        @Override
-                        public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
-                            return Rpcs.<Void> getRpcResult(input.isSuccessful(), null, input.getErrors());
-                        }
-                    });
-        }
-    }
-
     public boolean isRpcForwarding() {
         return rpcForwarding;
     }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategy.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategy.java
new file mode 100644 (file)
index 0000000..d08b217
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ ** Copyright (c) 2014 Brocade Communications 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.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.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/*
+ * RPC's can have both input, output, one or the other, or neither.
+ *
+ * This class handles the permutations and provides two means of invocation:
+ * 1. forwardToDomBroker
+ * 2.
+ *
+ * Weak References to the input and output classes are used to allow these classes to
+ * be from another OSGi bundle/class loader which may come and go.
+ *
+ */
+public class RpcInvocationStrategy {
+
+    private final BindingIndependentMappingService mappingService;
+    private final RpcProvisionRegistry biRpcRegistry;
+    protected final Method targetMethod;
+    protected final QName rpc;
+
+    @SuppressWarnings("rawtypes")
+    private final WeakReference<Class> inputClass;
+
+    @SuppressWarnings("rawtypes")
+    private final WeakReference<Class> outputClass;
+
+    @SuppressWarnings({ "rawtypes" })
+    public RpcInvocationStrategy(final QName rpc,
+                                 final Method targetMethod,
+                                 final BindingIndependentMappingService mappingService,
+                                 final RpcProvisionRegistry biRpcRegistry ) {
+
+        this.targetMethod = targetMethod;
+        this.rpc = rpc;
+
+        Optional<Class<?>> outputClassOption = BindingReflections.resolveRpcOutputClass(targetMethod);
+        Optional<Class<? extends DataContainer>> inputClassOption = BindingReflections.resolveRpcInputClass(targetMethod);
+
+        if ( outputClassOption != null && outputClassOption.isPresent() ) {
+            this.outputClass = new WeakReference(outputClassOption.get() ) ;
+        } else {
+            this.outputClass = null ;
+        }
+        if ( inputClassOption != null && inputClassOption.isPresent() ) {
+            this.inputClass = new WeakReference(inputClassOption.get() ) ;
+        } else {
+            this.inputClass = null ;
+        }
+
+        this.mappingService = mappingService;
+        this.biRpcRegistry = biRpcRegistry;
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
+
+        if(biRpcRegistry == null) {
+            return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
+        }
+
+        CompositeNode inputXml = null;
+        if( input != null ) {
+            CompositeNode xml = mappingService.toDataDom(input);
+            inputXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
+        } else {
+            inputXml = ImmutableCompositeNode.create( rpc, Collections.<Node<?>>emptyList() );
+        }
+
+        Function<RpcResult<CompositeNode>, RpcResult<?>> transformationFunction =
+                                       new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
+            @Override
+            public RpcResult<?> apply(RpcResult<CompositeNode> result) {
+
+                Object output = null;
+
+                if( getOutputClass() != null ) {
+                    if (result.getResult() != null) {
+                        output = mappingService.dataObjectFromDataDom(getOutputClass().get(),
+                                                                    result.getResult());
+                    }
+                }
+
+                return Rpcs.getRpcResult(result.isSuccessful(), output, result.getErrors());
+            }
+        };
+
+        return Futures.transform(biRpcRegistry.invokeRpc(rpc, inputXml), transformationFunction);
+    }
+
+    @SuppressWarnings("unchecked")
+    private RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+
+        Future<RpcResult<?>> futureResult = null;
+
+        if( inputClass != null ){
+            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
+            futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
+
+        } else {
+            futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
+        }
+
+        if (futureResult == null) {
+            return Rpcs.getRpcResult(false);
+        }
+
+        RpcResult<?> bindingResult = futureResult.get();
+
+        Collection<RpcError> errors = bindingResult.getErrors();
+        if( errors == null ) {
+            errors = Collections.<RpcError>emptySet();
+        }
+
+        final Object resultObj = bindingResult.getResult();
+        CompositeNode output = null;
+        if (resultObj instanceof DataObject) {
+            output = mappingService.toDataDom((DataObject)resultObj);
+        }
+        return Rpcs.getRpcResult( bindingResult.isSuccessful(), output, errors);
+    }
+
+    public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+        return uncheckedInvoke(rpcService, domInput);
+    }
+
+    @SuppressWarnings("rawtypes")
+    public WeakReference<Class> getOutputClass() {
+        return outputClass;
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategyTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategyTest.java
new file mode 100644 (file)
index 0000000..c5aea8f
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+* Copyright (c) 2014 Brocade Communications 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.connect.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+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.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class RpcInvocationStrategyTest {
+
+    @Mock
+    private BindingIndependentMappingService mockMappingService;
+    @Mock
+    private RpcProvisionRegistry mockbiRpcRegistry;
+
+    private RpcInvocationStrategy rpcInvocationStrategy;
+    private ListenableFuture<RpcResult<DataObject>> futureDataObj;
+    private ListenableFuture<RpcResult<CompositeNode>> futureCompNode;
+    private final RpcError rpcError = mock(RpcError.class);
+    private final Collection<RpcError> errors = new ArrayList<RpcError>();
+
+    private final CompositeNode inputInvokeOn = mock(CompositeNode.class);
+    private final CompositeNode outputInvokeOn = mock(CompositeNode.class);
+
+    private final DataObject toDataDomInput = mock(DataObject.class);
+    private final CompositeNode toDataDomReturn = mock(CompositeNode.class);
+    private final CompositeNode invokeRpcResult = mock(CompositeNode.class);
+
+    private final DataObject inputForward = mock(DataObject.class);
+    private final DataObject outputForward = mock(DataObject.class);
+
+    private QName mockQName;
+    private URI urn;
+
+    private final MockRpcService mockRpcService = new MockRpcService();
+
+    public class MockRpcService implements RpcService {
+
+        public Future<?> rpcnameWithInputNoOutput(DataObject input) {
+            return futureDataObj;
+        }
+
+        public Future<RpcResult<DataObject>> rpcnameWithInputWithOutput(DataObject input) {
+            return futureDataObj;
+        }
+
+        public Future<RpcResult<DataObject>> rpcnameNoInputWithOutput() {
+            return futureDataObj;
+        }
+
+        public Future<?> rpcnameNoInputNoOutput() {
+            return futureDataObj;
+        }
+    }
+
+    public RpcInvocationStrategyTest() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Before
+    public void testInit() throws Exception {
+        urn = new URI(new String("urn:a:valid:urn"));
+    }
+
+    private void setupForForwardToDom(boolean hasOutput, boolean hasInput, int expectedErrorSize) {
+
+        if (expectedErrorSize > 0)
+            errors.add(rpcError);
+        RpcResult<CompositeNode> result = Rpcs.getRpcResult(true, invokeRpcResult, errors);
+        futureCompNode = Futures.immediateFuture(result);
+        if( hasInput )
+        {
+            when(mockMappingService.toDataDom(inputForward)).thenReturn(toDataDomReturn);
+        }
+        when(mockbiRpcRegistry.invokeRpc(eq(mockQName), any(CompositeNode.class))).thenReturn(
+                futureCompNode);
+        if (hasOutput) {
+            when(
+                    mockMappingService.dataObjectFromDataDom(eq(rpcInvocationStrategy
+                            .getOutputClass().get()), any(CompositeNode.class))).thenReturn(
+                    outputForward);
+        }
+
+    }
+
+    private void validateForwardToDomBroker(ListenableFuture<RpcResult<?>> forwardToDomBroker,
+            boolean expectedSuccess, DataObject expectedResult, int expectedErrorSize)
+            throws InterruptedException, ExecutionException {
+        assertNotNull(forwardToDomBroker);
+        assertEquals(expectedSuccess, forwardToDomBroker.get().isSuccessful());
+        assertEquals(expectedResult, forwardToDomBroker.get().getResult());
+        assertEquals(expectedErrorSize, forwardToDomBroker.get().getErrors().size());
+    }
+
+    private void setupTestMethod(String rpcName, String testMethodName, boolean hasInput)
+            throws NoSuchMethodException {
+        mockQName = new QName(urn, new Date(0L), new String("prefix"), new String(rpcName));
+        java.lang.reflect.Method rpcMethod = hasInput ? MockRpcService.class.getMethod(rpcName,
+                DataObject.class) : MockRpcService.class.getMethod(rpcName);
+        rpcInvocationStrategy = new RpcInvocationStrategy(mockQName, rpcMethod, mockMappingService,
+                mockbiRpcRegistry);
+    }
+
+    /*
+     * forwardToDomBroker tests
+     */
+    @Test
+    public void testForwardToDomBroker_WithInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputNoOutput", "testForwardToDomBroker_WithInputNoOutput",
+                true);
+        setupForForwardToDom(false, true, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(inputForward);
+
+        validateForwardToDomBroker(forwardToDomBroker, true, null, 0);
+    }
+
+    @Test
+    public void testForwardToDomBroker_WithInputNoOutput_error() throws Exception {
+        setupTestMethod("rpcnameWithInputNoOutput",
+                "testForwardToDomBroker_WithInputNoOutput_error", true);
+        setupForForwardToDom(false, true, 1);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(inputForward);
+
+        validateForwardToDomBroker(forwardToDomBroker, true, null, 1);
+    }
+
+    @Test
+    public void testForwardToDomBroker_WithInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputWithOutput", "testForwardToDomBroker_WithInputWithOutput",
+                true);
+        setupForForwardToDom(true, true, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(inputForward);
+        validateForwardToDomBroker(forwardToDomBroker, true, outputForward, 0);
+    }
+
+    @Test
+    public void testForwardToDomBroker_NoInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputWithOutput", "testForwardToDomBroker_NoInputWithOutput",
+                false);
+        setupForForwardToDom(true, false, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(null);
+        validateForwardToDomBroker(forwardToDomBroker, true, outputForward, 0);
+    }
+
+    @Test
+    public void testForwardToDomBroker_NoInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputNoOutput", "testForwardToDomBroker_NoInputNoOutput", false);
+        setupForForwardToDom(false, false, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(null);
+        validateForwardToDomBroker(forwardToDomBroker, true, null, 0);
+    }
+
+    /*
+     * invokeOn Tests
+     */
+    private void setupRpcResultsWithOutput(int expectedErrorSize) {
+        if (expectedErrorSize > 0)
+            errors.add(rpcError);
+        RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+        futureCompNode = Futures.immediateFuture(resultCompNode);
+        RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, toDataDomInput, errors);
+        futureDataObj = Futures.immediateFuture(resultDataObj);
+
+        when(mockMappingService.toDataDom(toDataDomInput)).thenReturn(outputInvokeOn);
+    }
+
+    private void setupRpcResultsNoOutput(int expectedErrorSize) {
+        if (expectedErrorSize > 0)
+            errors.add(rpcError);
+        RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+        futureCompNode = Futures.immediateFuture(resultCompNode);
+        RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, null, errors);
+        futureDataObj = Futures.immediateFuture(resultDataObj);
+    }
+
+    private void validateReturnedImmediateFuture(
+            ListenableFuture<RpcResult<CompositeNode>> immediateFuture, boolean expectedSuccess,
+            CompositeNode expectedReturn, int expectedErrorSize) throws InterruptedException,
+            ExecutionException {
+        assertNotNull(immediateFuture);
+        assertEquals(expectedSuccess, immediateFuture.get().isSuccessful());
+        assertEquals(expectedReturn, immediateFuture.get().getResult());
+        assertEquals(expectedErrorSize, immediateFuture.get().getErrors().size());
+    }
+
+    @Test
+    public void testInvokeOn_NoInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputNoOutput", "testInvokeOn_NoInputNoOutput", false);
+        setupRpcResultsNoOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, null, 0);
+    }
+
+    @Test
+    public void testInvokeOn_NoInputNoOutput_errors() throws Exception {
+        setupTestMethod("rpcnameNoInputNoOutput", "testInvokeOn_NoInputNoOutput", false);
+        setupRpcResultsNoOutput(1);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, null, 1);
+    }
+
+    @Test
+    public void testInvokeOn_WithInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputNoOutput", "testInvokeOn_WithInputNoOutput", true);
+        setupRpcResultsNoOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, null, 0);
+    }
+
+    @Test
+    public void testInvokeOn_WithInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputWithOutput", "testInvokeOn_WithInputWithOutput", true);
+        setupRpcResultsWithOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, outputInvokeOn, 0);
+    }
+
+    @Test
+    public void testInvokeOn_NoInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputWithOutput", "testInvokeOn_NoInputWithOutput", false);
+        setupRpcResultsWithOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, outputInvokeOn, 0);
+    }
+}
@@ -48,7 +48,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-public class MultipleAugmentationPuts extends AbstractDataServiceTest implements DataChangeListener {
+public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implements DataChangeListener {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
     private static final String NODE_ID = "openflow:1";
@@ -76,7 +76,7 @@ public class MultipleAugmentationPuts extends AbstractDataServiceTest implements
      *
      * @throws Exception
      */
-    @Test
+    @Test( timeout = 15000)
     public void testAugmentSerialization() throws Exception {
 
         baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
index f869254dcf1efa2832f792005c7f22f02d9be033..a7c6b0c66fe4e688a9d868a89b7c761e64c962fc 100644 (file)
@@ -285,7 +285,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             ImmutableMap.Builder<QName, Object> keys = ImmutableMap.builder();
             for (QName key : keyDefinition) {
 
@@ -325,7 +325,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -343,7 +343,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -377,7 +377,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -397,7 +397,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -602,7 +602,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
         }
 
index b2217a6f0a0ba70cb7947a0b825c8e77f7d65648..5b34fba69ac1b0eaebabaf8a82c801082eacc864 100644 (file)
@@ -1,36 +1,28 @@
 package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
 
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 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.DataReader;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.core.api.data.DataProviderService;
 import org.opendaylight.controller.sal.core.api.data.DataValidator;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 
 public class BackwardsCompatibleDataBroker implements DataProviderService, SchemaContextListener {
 
-    DOMDataBroker backingBroker;
-    DataNormalizer normalizer;
-    private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
-
+    private final DOMDataBroker backingBroker;
+    private DataNormalizer normalizer;
 
     public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl) {
         backingBroker = newBiDataImpl;
@@ -43,7 +35,7 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
 
     @Override
     public CompositeNode readConfigurationData(final InstanceIdentifier legacyPath) {
-        BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+        final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
         try {
             return tx.readConfigurationData(legacyPath);
         } finally {
@@ -53,7 +45,7 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
 
     @Override
     public CompositeNode readOperationalData(final InstanceIdentifier legacyPath) {
-        BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+        final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
         try {
             return tx.readOperationalData(legacyPath);
         } finally {
@@ -67,9 +59,19 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
     }
 
     @Override
-    public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier path,
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier legacyPath,
             final DataChangeListener listener) {
-        return fakeRegistry .register(listener);
+        final InstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
+
+        final TranslatingListenerInvoker translatingCfgListener =
+                TranslatingListenerInvoker.createConfig(listener, normalizer);
+        translatingCfgListener.register(backingBroker, normalizedPath);
+
+        final TranslatingListenerInvoker translatingOpListener =
+                TranslatingListenerInvoker.createOperational(listener, normalizer);
+        translatingOpListener.register(backingBroker, normalizedPath);
+
+        return new DelegateListenerRegistration(translatingCfgListener, translatingOpListener, listener);
     }
 
     @Override
@@ -90,7 +92,7 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
         return null;
     }
 
-    // Obsolote functionality
+    // Obsolete functionality
 
     @Override
     public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
@@ -124,25 +126,26 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
         throw new UnsupportedOperationException("Data Reader contract is not supported.");
     }
 
-    private final class TranslatingListenerInvoker implements DOMDataChangeListener, Delegator<DataChangeListener> {
-
+    private static class DelegateListenerRegistration implements ListenerRegistration<DataChangeListener> {
+        private final TranslatingListenerInvoker translatingCfgListener;
+        private final TranslatingListenerInvoker translatingOpListener;
+        private final DataChangeListener listener;
 
-        private DataChangeListener delegate;
+        public DelegateListenerRegistration(final TranslatingListenerInvoker translatingCfgListener, final TranslatingListenerInvoker translatingOpListener, final DataChangeListener listener) {
+            this.translatingCfgListener = translatingCfgListener;
+            this.translatingOpListener = translatingOpListener;
+            this.listener = listener;
+        }
 
         @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
-
-            DataChangeEvent<InstanceIdentifier, CompositeNode> legacyChange = null;
-            delegate.onDataChanged(legacyChange);
+        public void close() {
+            translatingCfgListener.close();
+            translatingOpListener.close();
         }
 
         @Override
-        public DataChangeListener getDelegate() {
-
-            return delegate;
+        public DataChangeListener getInstance() {
+            return listener;
         }
-
-
     }
-
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java
new file mode 100644 (file)
index 0000000..827e4ca
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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.impl.compat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.collect.Maps;
+
+public abstract class TranslatingDataChangeEvent implements
+        DataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
+
+    private TranslatingDataChangeEvent() {
+    }
+
+    public static DataChangeEvent<InstanceIdentifier, CompositeNode> createOperational(
+            final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+        return new OperationalChangeEvent(change, normalizer);
+    }
+
+    public static DataChangeEvent<InstanceIdentifier, CompositeNode> createConfiguration(
+            final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+        return new ConfigurationChangeEvent(change, normalizer);
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public CompositeNode getOriginalConfigurationSubtree() {
+        return null;
+    }
+
+    @Override
+    public CompositeNode getOriginalOperationalSubtree() {
+        return null;
+    }
+
+    @Override
+    public CompositeNode getUpdatedConfigurationSubtree() {
+        return null;
+    }
+
+    @Override
+    public CompositeNode getUpdatedOperationalSubtree() {
+        return null;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private final static class OperationalChangeEvent extends TranslatingDataChangeEvent {
+
+        private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+        private final DataNormalizer normalizer;
+        private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+        public OperationalChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+                                        final DataNormalizer normalizer) {
+            this.delegate = change;
+            this.normalizer = normalizer;
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+            return transformToLegacy(normalizer, delegate.getCreatedData());
+        }
+
+
+        @Override
+        public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+            return delegate.getRemovedPaths();
+        }
+
+        @Override
+        public CompositeNode getOriginalOperationalSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+        }
+
+        @Override
+        public CompositeNode getUpdatedOperationalSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+            return transformToLegacy(normalizer, delegate.getOriginalData());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+            if(updatedCache == null) {
+                final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+                final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+                final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+                updatedComposite.putAll(created);
+                updatedComposite.putAll(updated);
+                updatedCache = Collections.unmodifiableMap(updatedComposite);
+            }
+            return updatedCache;
+        }
+
+        @Override
+        public String toString() {
+            return "OperationalChangeEvent [delegate=" + delegate + "]";
+        }
+
+    }
+
+    private static Map<InstanceIdentifier, CompositeNode> transformToLegacy(final DataNormalizer normalizer, final Map<InstanceIdentifier, ? extends NormalizedNode<?, ?>> nodes) {
+        final Map<InstanceIdentifier, CompositeNode> legacy = Maps.newHashMap();
+
+        for (final Map.Entry<InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : nodes.entrySet()) {
+            try {
+                legacy.put(normalizer.toLegacy(entry.getKey()), normalizer.toLegacy(entry.getKey(), entry.getValue()));
+            } catch (final DataNormalizationException e) {
+                throw new IllegalStateException("Unable to transform data change event to legacy format", e);
+            }
+        }
+        return legacy;
+    }
+
+    private final static class ConfigurationChangeEvent extends TranslatingDataChangeEvent {
+
+        private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+        private final DataNormalizer normalizer;
+        private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+        public ConfigurationChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+                                        final DataNormalizer normalizer) {
+            this.delegate = change;
+            this.normalizer = normalizer;
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+            return transformToLegacy(normalizer, delegate.getCreatedData());
+        }
+
+
+        @Override
+        public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+            return delegate.getRemovedPaths();
+        }
+
+        @Override
+        public CompositeNode getOriginalConfigurationSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+        }
+
+        @Override
+        public CompositeNode getUpdatedConfigurationSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+            return transformToLegacy(normalizer, delegate.getOriginalData());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+            if(updatedCache == null) {
+                final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+                final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+                final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+                updatedComposite.putAll(created);
+                updatedComposite.putAll(updated);
+                updatedCache = Collections.unmodifiableMap(updatedComposite);
+            }
+            return updatedCache;
+        }
+
+        @Override
+        public String toString() {
+            return "ConfigurationChangeEvent [delegate=" + delegate + "]";
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingListenerInvoker.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingListenerInvoker.java
new file mode 100644 (file)
index 0000000..1ce252d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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.impl.compat;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+abstract class TranslatingListenerInvoker implements AutoCloseable, DOMDataChangeListener, Delegator<DataChangeListener> {
+
+    private final DataChangeListener delegate;
+    private final DataNormalizer normalizer;
+    protected ListenerRegistration<DOMDataChangeListener> reg;
+
+    protected TranslatingListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+        this.delegate = listener;
+        this.normalizer = normalizer;
+    }
+
+    static TranslatingListenerInvoker createConfig(final DataChangeListener listener, final DataNormalizer normalizer) {
+        return new TranslatingConfigListenerInvoker(listener, normalizer);
+    }
+
+    static TranslatingListenerInvoker createOperational(final DataChangeListener listener, final DataNormalizer normalizer) {
+        return new TranslatingOperationalListenerInvoker(listener, normalizer);
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+        delegate.onDataChanged(getLegacyEvent(normalizer, normalizedChange));
+    }
+
+    abstract DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer,
+                                                                               final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange);
+
+    @Override
+    public DataChangeListener getDelegate() {
+        return delegate;
+    }
+
+    abstract void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath);
+
+    @Override
+    public void close() {
+        if (reg != null) {
+            reg.close();
+        }
+    }
+
+    static final class TranslatingConfigListenerInvoker extends TranslatingListenerInvoker {
+
+        public TranslatingConfigListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+            super(listener, normalizer);
+        }
+
+        DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+            return TranslatingDataChangeEvent.createConfiguration(normalizedChange, normalizer);
+        }
+
+        @Override
+        void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+            reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, normalizedPath, this,
+                    AsyncDataBroker.DataChangeScope.SUBTREE);
+        }
+    }
+
+    static final class TranslatingOperationalListenerInvoker extends TranslatingListenerInvoker {
+
+        public TranslatingOperationalListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+            super(listener, normalizer);
+        }
+
+        DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+            return TranslatingDataChangeEvent.createOperational(normalizedChange, normalizer);
+        }
+
+        @Override
+        void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+            reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, normalizedPath, this,
+                    AsyncDataBroker.DataChangeScope.SUBTREE);
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java
deleted file mode 100644 (file)
index 6baf764..0000000
+++ /dev/null
@@ -1,50 +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.md.sal.dom.store.impl;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-public class DataPreconditionFailedException extends Exception {
-
-    /**
-     *
-     */
-    private static final long serialVersionUID = 596430355175413427L;
-    private final InstanceIdentifier path;
-
-    public DataPreconditionFailedException(final InstanceIdentifier path) {
-        this.path = path;
-    }
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final String message) {
-        super(message);
-        this.path = path;
-    }
-
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final Throwable cause) {
-        super(cause);
-        this.path = path;
-    }
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause) {
-        super(message, cause);
-        this.path = path;
-    }
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause, final boolean enableSuppression,
-            final boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
-        this.path = path;
-    }
-
-    public InstanceIdentifier getPath() {
-        return path;
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java
deleted file mode 100644 (file)
index 3124199..0000000
+++ /dev/null
@@ -1,120 +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.md.sal.dom.store.impl;
-
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-/**
- * Read-only snapshot of the data tree.
- */
-final class DataTree {
-    public static final class Snapshot {
-        private final SchemaContext schemaContext;
-        private final StoreMetadataNode rootNode;
-
-        @VisibleForTesting
-        Snapshot(final SchemaContext schemaContext, final StoreMetadataNode rootNode) {
-            this.schemaContext = Preconditions.checkNotNull(schemaContext);
-            this.rootNode = Preconditions.checkNotNull(rootNode);
-        }
-
-        public SchemaContext getSchemaContext() {
-            return schemaContext;
-        }
-
-        public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
-            return NormalizedNodeUtils.findNode(rootNode.getData(), path);
-        }
-
-        // FIXME: this is a leak of information
-        @Deprecated
-        StoreMetadataNode getRootNode() {
-            return rootNode;
-        }
-
-        @Override
-        public String toString() {
-            return rootNode.getSubtreeVersion().toString();
-        }
-    }
-
-    private static final Logger LOG = LoggerFactory.getLogger(DataTree.class);
-    private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
-    private StoreMetadataNode rootNode;
-    private SchemaContext currentSchemaContext;
-
-    private DataTree(StoreMetadataNode rootNode, final SchemaContext schemaContext) {
-        this.rootNode = Preconditions.checkNotNull(rootNode);
-        this.currentSchemaContext = schemaContext;
-    }
-
-    public synchronized void setSchemaContext(final SchemaContext newSchemaContext) {
-        Preconditions.checkNotNull(newSchemaContext);
-
-        LOG.info("Attepting to install schema context {}", newSchemaContext);
-
-        /*
-         * FIXME: we should walk the schema contexts, both current and new and see
-         *        whether they are compatible here. Reject incompatible changes.
-         */
-
-        // Ready to change the context now, make sure no operations are running
-        rwLock.writeLock().lock();
-        try {
-            this.currentSchemaContext = newSchemaContext;
-        } finally {
-            rwLock.writeLock().unlock();
-        }
-    }
-
-    public static DataTree create(final SchemaContext schemaContext) {
-        final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
-        final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
-
-        return new DataTree(StoreMetadataNode.createEmpty(data), schemaContext);
-    }
-
-    public Snapshot takeSnapshot() {
-        rwLock.readLock().lock();
-
-        try {
-            return new Snapshot(currentSchemaContext, rootNode);
-        } finally {
-            rwLock.readLock().unlock();
-        }
-    }
-
-    public void commitSnapshot(Snapshot currentSnapshot, StoreMetadataNode newDataTree) {
-        // Ready to change the context now, make sure no operations are running
-        rwLock.writeLock().lock();
-        try {
-            Preconditions.checkState(currentSnapshot.rootNode == rootNode,
-                    String.format("Store snapshot %s and transaction snapshot %s differ.",
-                            rootNode, currentSnapshot.rootNode));
-
-            this.rootNode = newDataTree;
-        } finally {
-            rwLock.writeLock().unlock();
-        }
-    }
-}
index 7d2ff30b1fe64f96d89619894e83d26880f8bd73..00df6580effda8da33e80a648653935049010c47 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
-import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.increase;
 
 import java.util.Collections;
 import java.util.concurrent.Callable;
@@ -17,10 +16,13 @@ import java.util.concurrent.atomic.AtomicLong;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.InMemoryDataTreeFactory;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
@@ -31,7 +33,6 @@ import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
@@ -42,22 +43,17 @@ import com.google.common.base.Objects;
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
 public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, SchemaContextListener {
-
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
-    private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
-
+    private final DataTree dataTree = InMemoryDataTreeFactory.getInstance().create();
+    private final ListenerTree listenerTree = ListenerTree.create();
+    private final AtomicLong txCounter = new AtomicLong(0);
     private final ListeningExecutorService executor;
     private final String name;
-    private final AtomicLong txCounter = new AtomicLong(0);
-    private final ListenerTree listenerTree = ListenerTree.create();
-    private final DataTree dataTree = DataTree.create(null);
-    private ModificationApplyOperation operationTree = new AlwaysFailOperation();
 
     public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) {
         this.name = Preconditions.checkNotNull(name);
@@ -76,25 +72,17 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        return new SnapshotBackedReadWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree);
+        return new SnapshotBackedReadWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new SnapshotBackedWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree);
+        return new SnapshotBackedWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this);
     }
 
     @Override
     public synchronized void onGlobalContextUpdated(final SchemaContext ctx) {
-        /*
-         * Order of operations is important: dataTree may reject the context
-         * and creation of ModificationApplyOperation may fail. So pre-construct
-         * the operation, then update the data tree and then move the operation
-         * into view.
-         */
-        final ModificationApplyOperation newOperationTree = SchemaAwareApplyOperationRoot.from(ctx);
         dataTree.setSchemaContext(ctx);
-        operationTree = newOperationTree;
     }
 
     @Override
@@ -145,28 +133,6 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         return name + "-" + txCounter.getAndIncrement();
     }
 
-    private void commit(final DataTree.Snapshot currentSnapshot, final StoreMetadataNode newDataTree,
-            final ResolveDataChangeEventsTask listenerResolver) {
-        LOG.debug("Updating Store snaphot version: {} with version:{}", currentSnapshot, newDataTree.getSubtreeVersion());
-
-        if (LOG.isTraceEnabled()) {
-            LOG.trace("Data Tree is {}", StoreUtils.toStringTree(newDataTree.getData()));
-        }
-
-        /*
-         * The commit has to occur atomically with regard to listener
-         * registrations.
-         */
-        synchronized (this) {
-            dataTree.commitSnapshot(currentSnapshot, newDataTree);
-
-            for (ChangeListenerNotifyTask task : listenerResolver.call()) {
-                LOG.trace("Scheduling invocation of listeners: {}", task);
-                executor.submit(task);
-            }
-        }
-    }
-
     private static abstract class AbstractDOMStoreTransaction implements DOMStoreTransaction {
         private final Object identifier;
 
@@ -197,10 +163,10 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     }
 
     private static final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
-            DOMStoreReadTransaction {
-        private DataTree.Snapshot stableSnapshot;
+    DOMStoreReadTransaction {
+        private DataTreeSnapshot stableSnapshot;
 
-        public SnapshotBackedReadTransaction(final Object identifier, final DataTree.Snapshot snapshot) {
+        public SnapshotBackedReadTransaction(final Object identifier, final DataTreeSnapshot snapshot) {
             super(identifier);
             this.stableSnapshot = Preconditions.checkNotNull(snapshot);
             LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot);
@@ -221,15 +187,15 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     }
 
     private static class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements
-            DOMStoreWriteTransaction {
-        private MutableDataTree mutableTree;
+    DOMStoreWriteTransaction {
+        private DataTreeModification mutableTree;
         private InMemoryDOMDataStore store;
         private boolean ready = false;
 
-        public SnapshotBackedWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot,
-                final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
+        public SnapshotBackedWriteTransaction(final Object identifier, final DataTreeSnapshot snapshot,
+                final InMemoryDOMDataStore store) {
             super(identifier);
-            mutableTree = MutableDataTree.from(snapshot, applyOper);
+            mutableTree = snapshot.newModification();
             this.store = store;
             LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot);
         }
@@ -295,7 +261,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
             return store.submit(this);
         }
 
-        protected MutableDataTree getMutatedView() {
+        protected DataTreeModification getMutatedView() {
             return mutableTree;
         }
 
@@ -306,18 +272,18 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     }
 
     private static class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements
-            DOMStoreReadWriteTransaction {
+    DOMStoreReadWriteTransaction {
 
-        protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot,
-                final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
-            super(identifier, snapshot, store, applyOper);
+        protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataTreeSnapshot snapshot,
+                final InMemoryDOMDataStore store) {
+            super(identifier, snapshot, store);
         }
 
         @Override
         public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
             LOG.trace("Tx: {} Read: {}", getIdentifier(), path);
             try {
-                return Futures.immediateFuture(getMutatedView().read(path));
+                return Futures.immediateFuture(getMutatedView().readNode(path));
             } catch (Exception e) {
                 LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
                 throw e;
@@ -328,63 +294,40 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     private class ThreePhaseCommitImpl implements DOMStoreThreePhaseCommitCohort {
 
         private final SnapshotBackedWriteTransaction transaction;
-        private final NodeModification modification;
+        private final DataTreeModification modification;
 
-        private DataTree.Snapshot storeSnapshot;
-        private Optional<StoreMetadataNode> proposedSubtree;
         private ResolveDataChangeEventsTask listenerResolver;
+        private DataTreeCandidate candidate;
 
         public ThreePhaseCommitImpl(final SnapshotBackedWriteTransaction writeTransaction) {
             this.transaction = writeTransaction;
-            this.modification = transaction.getMutatedView().getRootModification();
+            this.modification = transaction.getMutatedView();
         }
 
         @Override
         public ListenableFuture<Boolean> canCommit() {
-            final DataTree.Snapshot snapshotCapture = dataTree.takeSnapshot();
-            final ModificationApplyOperation snapshotOperation = operationTree;
-
             return executor.submit(new Callable<Boolean>() {
-
                 @Override
-                public Boolean call() throws Exception {
-                    Boolean applicable = false;
+                public Boolean call() {
                     try {
-                        snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification,
-                            Optional.of(snapshotCapture.getRootNode()));
-                        applicable = true;
+                        dataTree.validate(modification);
+                        LOG.debug("Store Transaction: {} can be committed", transaction.getIdentifier());
+                        return true;
                     } catch (DataPreconditionFailedException e) {
                         LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e);
-                        applicable = false;
+                        return false;
                     }
-                    LOG.debug("Store Transaction: {} : canCommit : {}", transaction.getIdentifier(), applicable);
-                    return applicable;
                 }
             });
         }
 
         @Override
         public ListenableFuture<Void> preCommit() {
-            storeSnapshot = dataTree.takeSnapshot();
-            if (modification.getModificationType() == ModificationType.UNMODIFIED) {
-                return Futures.immediateFuture(null);
-            }
             return executor.submit(new Callable<Void>() {
-
                 @Override
-                public Void call() throws Exception {
-                    StoreMetadataNode metadataTree = storeSnapshot.getRootNode();
-
-                    proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
-                            increase(metadataTree.getSubtreeVersion()));
-
-                    listenerResolver = ResolveDataChangeEventsTask.create() //
-                            .setRootPath(PUBLIC_ROOT_PATH) //
-                            .setBeforeRoot(Optional.of(metadataTree)) //
-                            .setAfterRoot(proposedSubtree) //
-                            .setModificationRoot(modification) //
-                            .setListenerRoot(listenerTree);
-
+                public Void call() {
+                    candidate = dataTree.prepare(modification);
+                    listenerResolver = ResolveDataChangeEventsTask.create(candidate, listenerTree);
                     return null;
                 }
             });
@@ -392,48 +335,28 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
         @Override
         public ListenableFuture<Void> abort() {
-            storeSnapshot = null;
-            proposedSubtree = null;
-            return Futures.<Void> immediateFuture(null);
+            candidate = null;
+            return Futures.immediateFuture(null);
         }
 
         @Override
         public ListenableFuture<Void> commit() {
-            if (modification.getModificationType() == ModificationType.UNMODIFIED) {
-                return Futures.immediateFuture(null);
+            checkState(candidate != null, "Proposed subtree must be computed");
+
+            /*
+             * The commit has to occur atomically with regard to listener
+             * registrations.
+             */
+            synchronized (this) {
+                dataTree.commit(candidate);
+
+                for (ChangeListenerNotifyTask task : listenerResolver.call()) {
+                    LOG.trace("Scheduling invocation of listeners: {}", task);
+                    executor.submit(task);
+                }
             }
 
-            checkState(proposedSubtree != null, "Proposed subtree must be computed");
-            checkState(storeSnapshot != null, "Proposed subtree must be computed");
-            // return ImmediateFuture<>;
-            InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(), listenerResolver);
-            return Futures.<Void> immediateFuture(null);
-        }
-
-    }
-
-    private static final class AlwaysFailOperation implements ModificationApplyOperation {
-
-        @Override
-        public Optional<StoreMetadataNode> apply(final NodeModification modification,
-                final Optional<StoreMetadataNode> storeMeta, final UnsignedLong subtreeVersion) {
-            throw new IllegalStateException("Schema Context is not available.");
+            return Futures.immediateFuture(null);
         }
-
-        @Override
-        public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
-            throw new IllegalStateException("Schema Context is not available.");
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-            throw new IllegalStateException("Schema Context is not available.");
-        }
-
-        @Override
-        public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
-            throw new IllegalStateException("Schema Context is not available.");
-        }
-
     }
 }
index 44d50166af21df772f478d057fa479d879e0b829..b36ef3dd7c16250bfcc101ab4567be3feaaadbc4 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
-import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.append;
+import static org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils.append;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -22,11 +22,12 @@ import java.util.concurrent.Callable;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.SimpleEventFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Node;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
@@ -38,6 +39,7 @@ 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.HashMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
@@ -62,60 +64,17 @@ import com.google.common.collect.Multimap;
  * </ul>
  *
  */
-public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
+final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
     private static final Logger LOG = LoggerFactory.getLogger(ResolveDataChangeEventsTask.class);
     private static final DOMImmutableDataChangeEvent NO_CHANGE = builder(DataChangeScope.BASE).build();
 
-    private InstanceIdentifier rootPath;
-    private ListenerTree listenerRoot;
-    private NodeModification modificationRoot;
-    private Optional<StoreMetadataNode> beforeRoot;
-    private Optional<StoreMetadataNode> afterRoot;
     private final Multimap<ListenerTree.Node, DOMImmutableDataChangeEvent> events = HashMultimap.create();
+    private final DataTreeCandidate candidate;
+    private final ListenerTree listenerRoot;
 
-    protected InstanceIdentifier getRootPath() {
-        return rootPath;
-    }
-
-    protected ResolveDataChangeEventsTask setRootPath(final InstanceIdentifier rootPath) {
-        this.rootPath = rootPath;
-        return this;
-    }
-
-    protected ListenerTree getListenerRoot() {
-        return listenerRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setListenerRoot(final ListenerTree listenerRoot) {
-        this.listenerRoot = listenerRoot;
-        return this;
-    }
-
-    protected NodeModification getModificationRoot() {
-        return modificationRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setModificationRoot(final NodeModification modificationRoot) {
-        this.modificationRoot = modificationRoot;
-        return this;
-    }
-
-    protected Optional<StoreMetadataNode> getBeforeRoot() {
-        return beforeRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setBeforeRoot(final Optional<StoreMetadataNode> beforeRoot) {
-        this.beforeRoot = beforeRoot;
-        return this;
-    }
-
-    protected Optional<StoreMetadataNode> getAfterRoot() {
-        return afterRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setAfterRoot(final Optional<StoreMetadataNode> afterRoot) {
-        this.afterRoot = afterRoot;
-        return this;
+    public ResolveDataChangeEventsTask(DataTreeCandidate candidate, ListenerTree listenerTree) {
+        this.candidate = Preconditions.checkNotNull(candidate);
+        this.listenerRoot = Preconditions.checkNotNull(listenerTree);
     }
 
     /**
@@ -129,11 +88,8 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
      */
     @Override
     public Iterable<ChangeListenerNotifyTask> call() {
-        LOG.trace("Resolving events for {}", modificationRoot);
-
         try (final Walker w = listenerRoot.getWalker()) {
-            resolveAnyChangeEvent(rootPath, Collections.singleton(w.getRootNode()), modificationRoot, beforeRoot,
-                    afterRoot);
+            resolveAnyChangeEvent(candidate.getRootPath(), Collections.singleton(w.getRootNode()), candidate.getRootNode());
             return createNotificationTasks();
         }
     }
@@ -298,29 +254,38 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
      * @return Data Change Event of this node and all it's children
      */
     private DOMImmutableDataChangeEvent resolveAnyChangeEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final NodeModification modification,
-            final Optional<StoreMetadataNode> before, final Optional<StoreMetadataNode> after) {
-        // No listeners are present in listener registration subtree
-        // no before and after state is present
-        if (!before.isPresent() && !after.isPresent()) {
+            final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode node) {
+
+        if (node.getModificationType() != ModificationType.UNMODIFIED &&
+                !node.getDataAfter().isPresent() && !node.getDataBefore().isPresent()) {
+            LOG.debug("Modification at {} has type {}, but no before- and after-data. Assuming unchanged.",
+                    path, node.getModificationType());
             return NO_CHANGE;
         }
-        switch (modification.getModificationType()) {
+
+        // no before and after state is present
+
+        switch (node.getModificationType()) {
         case SUBTREE_MODIFIED:
-            return resolveSubtreeChangeEvent(path, listeners, modification, before.get(), after.get());
+            return resolveSubtreeChangeEvent(path, listeners, node);
         case MERGE:
         case WRITE:
-            if (before.isPresent()) {
-                return resolveReplacedEvent(path, listeners, before.get().getData(), after.get().getData());
+            Preconditions.checkArgument(node.getDataAfter().isPresent(),
+                    "Modification at {} has type {} but no after-data", path, node.getModificationType());
+            if (node.getDataBefore().isPresent()) {
+                return resolveReplacedEvent(path, listeners, node.getDataBefore().get(), node.getDataAfter().get());
             } else {
-                return resolveCreateEvent(path, listeners, after.get());
+                return resolveCreateEvent(path, listeners, node.getDataAfter().get());
             }
         case DELETE:
-            return resolveDeleteEvent(path, listeners, before.get());
-        default:
+            Preconditions.checkArgument(node.getDataBefore().isPresent(),
+                    "Modification at {} has type {} but no before-data", path, node.getModificationType());
+            return resolveDeleteEvent(path, listeners, node.getDataBefore().get());
+        case UNMODIFIED:
             return NO_CHANGE;
         }
 
+        throw new IllegalStateException(String.format("Unhandled node state %s at %s", node.getModificationType(), path));
     }
 
     private DOMImmutableDataChangeEvent resolveReplacedEvent(final InstanceIdentifier path,
@@ -355,7 +320,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
     private DOMImmutableDataChangeEvent resolveNodeContainerReplaced(final InstanceIdentifier path,
             final Collection<Node> listeners,
             final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont,
-            final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
+                    final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
         final Set<PathArgument> alreadyProcessed = new HashSet<>();
         final List<DOMImmutableDataChangeEvent> childChanges = new LinkedList<>();
 
@@ -430,17 +395,17 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
      * @return
      */
     private DOMImmutableDataChangeEvent resolveCreateEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final StoreMetadataNode afterState) {
+            final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> afterState) {
         @SuppressWarnings({ "unchecked", "rawtypes" })
-        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState.getData();
+        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState;
         return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getCreateEventFactory());
     }
 
     private DOMImmutableDataChangeEvent resolveDeleteEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final StoreMetadataNode beforeState) {
+            final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> beforeState) {
 
         @SuppressWarnings({ "unchecked", "rawtypes" })
-        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState.getData();
+        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState;
         return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getRemoveEventFactory());
     }
 
@@ -450,7 +415,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
         final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
         DOMImmutableDataChangeEvent propagateEvent = event;
         // We have listeners for this node or it's children, so we will try
-            // to do additional processing
+        // to do additional processing
         if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
             LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory);
 
@@ -481,30 +446,31 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
     }
 
     private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final NodeModification modification,
-            final StoreMetadataNode before, final StoreMetadataNode after) {
+            final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode modification) {
 
-        Builder one = builder(DataChangeScope.ONE).setBefore(before.getData()).setAfter(after.getData());
+        Preconditions.checkArgument(modification.getDataBefore().isPresent(), "Subtree change with before-data not present at path %s", path);
+        Preconditions.checkArgument(modification.getDataAfter().isPresent(), "Subtree change with after-data not present at path %s", path);
 
-        Builder subtree = builder(DataChangeScope.SUBTREE).setBefore(before.getData()).setAfter(after.getData());
+        Builder one = builder(DataChangeScope.ONE).
+                setBefore(modification.getDataBefore().get()).
+                setAfter(modification.getDataAfter().get());
+        Builder subtree = builder(DataChangeScope.SUBTREE).
+                setBefore(modification.getDataBefore().get()).
+                setAfter(modification.getDataAfter().get());
 
-        for (NodeModification childMod : modification.getModifications()) {
+        for (DataTreeCandidateNode childMod : modification.getChildNodes()) {
             PathArgument childId = childMod.getIdentifier();
             InstanceIdentifier childPath = append(path, childId);
             Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
 
-            Optional<StoreMetadataNode> childBefore = before.getChild(childId);
-            Optional<StoreMetadataNode> childAfter = after.getChild(childId);
-
             switch (childMod.getModificationType()) {
             case WRITE:
             case MERGE:
             case DELETE:
-                one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod, childBefore, childAfter));
+                one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod));
                 break;
             case SUBTREE_MODIFIED:
-                subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod, childBefore.get(),
-                        childAfter.get()));
+                subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod));
                 break;
             case UNMODIFIED:
                 // no-op
@@ -556,7 +522,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
         }
     }
 
-    public static ResolveDataChangeEventsTask create() {
-        return new ResolveDataChangeEventsTask();
+    public static ResolveDataChangeEventsTask create(DataTreeCandidate candidate, ListenerTree listenerTree) {
+        return new ResolveDataChangeEventsTask(candidate, listenerTree);
     }
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataPreconditionFailedException.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataPreconditionFailedException.java
new file mode 100644 (file)
index 0000000..bb2111e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public class DataPreconditionFailedException extends Exception {
+    private static final long serialVersionUID = 1L;
+    private final InstanceIdentifier path;
+
+    public DataPreconditionFailedException(final InstanceIdentifier path, final String message) {
+        super(message);
+        this.path = Preconditions.checkNotNull(path);
+    }
+
+    public DataPreconditionFailedException(final InstanceIdentifier path, final String message, final Throwable cause) {
+        super(message, cause);
+        this.path = Preconditions.checkNotNull(path);
+    }
+
+    public InstanceIdentifier getPath() {
+        return path;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTree.java
new file mode 100644 (file)
index 0000000..ee9726a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Interface representing a data tree which can be modified in an MVCC fashion.
+ */
+public interface DataTree {
+    /**
+     * Take a read-only point-in-time snapshot of the tree.
+     *
+     * @return Data tree snapshot.
+     */
+    DataTreeSnapshot takeSnapshot();
+
+    /**
+     * Make the data tree use a new schema context. The context will be used
+     * only by subsequent operations.
+     *
+     * @param newSchemaContext new SchemaContext
+     * @throws IllegalArgumentException if the new context is incompatible
+     */
+    void setSchemaContext(SchemaContext newSchemaContext);
+
+    /**
+     * Validate whether a particular modification can be applied to the data tree.
+     */
+    void validate(DataTreeModification modification) throws DataPreconditionFailedException;
+
+    /**
+     * Prepare a modification for commit.
+     *
+     * @param modification
+     * @return candidate data tree
+     */
+    DataTreeCandidate prepare(DataTreeModification modification);
+
+    /**
+     * Commit a data tree candidate.
+     *
+     * @param candidate data tree candidate
+     */
+    void commit(DataTreeCandidate candidate);
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidate.java
new file mode 100644 (file)
index 0000000..906e284
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * 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.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public interface DataTreeCandidate {
+    DataTreeCandidateNode getRootNode();
+    InstanceIdentifier getRootPath();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidateNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidateNode.java
new file mode 100644 (file)
index 0000000..b1ca45b
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+public interface DataTreeCandidateNode {
+    PathArgument getIdentifier();
+    Iterable<DataTreeCandidateNode> getChildNodes();
+
+    ModificationType getModificationType();
+    Optional<NormalizedNode<?, ?>> getDataAfter();
+    Optional<NormalizedNode<?, ?>> getDataBefore();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeFactory.java
new file mode 100644 (file)
index 0000000..7422c11
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.store.impl.tree;
+
+/**
+ * Factory interface for creating data trees.
+ */
+public interface DataTreeFactory {
+       /**
+        * Create a new data tree.
+        *
+        * @return A data tree instance.
+        */
+       DataTree create();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeModification.java
new file mode 100644 (file)
index 0000000..cff90a4
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Class encapsulation of set of modifications to a base tree. This tree is backed
+ * by a read-only snapshot and tracks modifications on top of that. The modification
+ * has the ability to rebase itself to a new snapshot.
+ */
+public interface DataTreeModification extends DataTreeSnapshot {
+       void delete(InstanceIdentifier path);
+       void merge(InstanceIdentifier path, NormalizedNode<?, ?> data);
+       void write(InstanceIdentifier path, NormalizedNode<?, ?> data);
+       void seal();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeSnapshot.java
new file mode 100644 (file)
index 0000000..a94acc5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+/**
+ * Read-only snapshot of a {@link DataTree}. The snapshot is stable and isolated,
+ * e.g. data tree changes occurring after the snapshot has been taken are not
+ * visible through the snapshot.
+ */
+public interface DataTreeSnapshot {
+    /**
+     * Read a particular node from the snapshot.
+     *
+     * @param path Path of the node
+     * @return Optional result encapsulating the presence and value of the node
+     */
+    Optional<NormalizedNode<?, ?>> readNode(InstanceIdentifier path);
+
+    /**
+     * Create a new data tree modification based on this snapshot, using the
+     * specified data application strategy.
+     *
+     * @param strategy data modification strategy
+     * @return A new data tree modification
+     */
+    DataTreeModification newModification();
+}
@@ -5,7 +5,7 @@
  * 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.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
 
 import java.util.Set;
 
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AbstractDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AbstractDataTreeCandidate.java
new file mode 100644 (file)
index 0000000..cddda5c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+abstract class AbstractDataTreeCandidate implements DataTreeCandidate {
+    private final InstanceIdentifier rootPath;
+
+    protected AbstractDataTreeCandidate(final InstanceIdentifier rootPath) {
+        this.rootPath = Preconditions.checkNotNull(rootPath);
+    }
+
+    @Override
+    public final InstanceIdentifier getRootPath() {
+        return rootPath;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java
new file mode 100644 (file)
index 0000000..4e3aa49
--- /dev/null
@@ -0,0 +1,31 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Optional;
+import com.google.common.primitives.UnsignedLong;
+
+final class AlwaysFailOperation implements ModificationApplyOperation {
+
+    @Override
+    public Optional<StoreMetadataNode> apply(final NodeModification modification,
+            final Optional<StoreMetadataNode> storeMeta, final UnsignedLong subtreeVersion) {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+
+    @Override
+    public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+
+    @Override
+    public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+
+    @Override
+    public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java
new file mode 100644 (file)
index 0000000..f04e379
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * 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.store.impl.tree.data;
+
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * Read-only snapshot of the data tree.
+ */
+final class InMemoryDataTree implements DataTree {
+    private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTree.class);
+    private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
+
+    private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
+    private ModificationApplyOperation applyOper = new AlwaysFailOperation();
+    private SchemaContext currentSchemaContext;
+    private StoreMetadataNode rootNode;
+
+    public InMemoryDataTree(StoreMetadataNode rootNode, final SchemaContext schemaContext) {
+        this.rootNode = Preconditions.checkNotNull(rootNode);
+
+        if (schemaContext != null) {
+            // Also sets applyOper
+            setSchemaContext(schemaContext);
+        }
+    }
+
+    @Override
+    public synchronized void setSchemaContext(final SchemaContext newSchemaContext) {
+        Preconditions.checkNotNull(newSchemaContext);
+
+        LOG.info("Attepting to install schema context {}", newSchemaContext);
+
+        /*
+         * FIXME: we should walk the schema contexts, both current and new and see
+         *        whether they are compatible here. Reject incompatible changes.
+         */
+
+        // Instantiate new apply operation, this still may fail
+        final ModificationApplyOperation newApplyOper = SchemaAwareApplyOperation.from(newSchemaContext);
+
+        // Ready to change the context now, make sure no operations are running
+        rwLock.writeLock().lock();
+        try {
+            this.applyOper = newApplyOper;
+            this.currentSchemaContext = newSchemaContext;
+        } finally {
+            rwLock.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public InMemoryDataTreeSnapshot takeSnapshot() {
+        rwLock.readLock().lock();
+        try {
+            return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, applyOper);
+        } finally {
+            rwLock.readLock().unlock();
+        }
+    }
+
+    @Override
+    public void validate(DataTreeModification modification) throws DataPreconditionFailedException {
+        Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
+
+        final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
+        m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.of(rootNode));
+    }
+
+    @Override
+    public synchronized DataTreeCandidate prepare(DataTreeModification modification) {
+        Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
+
+        final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
+        final NodeModification root = m.getRootModification();
+
+        if (root.getModificationType() == ModificationType.UNMODIFIED) {
+            return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root);
+        }
+
+        rwLock.writeLock().lock();
+        try {
+            // FIXME: rootNode needs to be a read-write snapshot here...
+            final Optional<StoreMetadataNode> newRoot = m.getStrategy().apply(m.getRootModification(), Optional.of(rootNode), StoreUtils.increase(rootNode.getSubtreeVersion()));
+            Preconditions.checkState(newRoot.isPresent(), "Apply strategy failed to produce root node");
+            return new InMemoryDataTreeCandidate(PUBLIC_ROOT_PATH, root, rootNode, newRoot.get());
+        } finally {
+            rwLock.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public synchronized void commit(DataTreeCandidate candidate) {
+        if (candidate instanceof NoopDataTreeCandidate) {
+            return;
+        }
+
+        Preconditions.checkArgument(candidate instanceof InMemoryDataTreeCandidate, "Invalid candidate class %s", candidate.getClass());
+        final InMemoryDataTreeCandidate c = (InMemoryDataTreeCandidate)candidate;
+
+        LOG.debug("Updating Store snapshot version: {} with version:{}", rootNode.getSubtreeVersion(), c.getAfterRoot().getSubtreeVersion());
+
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Data Tree is {}", StoreUtils.toStringTree(c.getAfterRoot().getData()));
+        }
+
+        // Ready to change the context now, make sure no operations are running
+        rwLock.writeLock().lock();
+        try {
+            Preconditions.checkState(c.getBeforeRoot() == rootNode,
+                    String.format("Store tree %s and candidate base %s differ.", rootNode, c.getBeforeRoot()));
+            this.rootNode = c.getAfterRoot();
+        } finally {
+            rwLock.writeLock().unlock();
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java
new file mode 100644 (file)
index 0000000..72562f0
--- /dev/null
@@ -0,0 +1,119 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
+    private static abstract class AbstractNode implements DataTreeCandidateNode {
+        private final StoreMetadataNode newMeta;
+        private final StoreMetadataNode oldMeta;
+        private final NodeModification mod;
+
+        protected AbstractNode(final NodeModification mod,
+                final StoreMetadataNode oldMeta, final StoreMetadataNode newMeta) {
+            this.newMeta = newMeta;
+            this.oldMeta = oldMeta;
+            this.mod = Preconditions.checkNotNull(mod);
+        }
+
+        protected final NodeModification getMod() {
+            return mod;
+        }
+
+        protected final StoreMetadataNode getNewMeta() {
+            return newMeta;
+        }
+
+        protected final StoreMetadataNode getOldMeta() {
+            return oldMeta;
+        }
+
+        private static final StoreMetadataNode childMeta(final StoreMetadataNode parent, final PathArgument id) {
+            return parent == null ? null : parent.getChild(id).orNull();
+        }
+
+        @Override
+        public Iterable<DataTreeCandidateNode> getChildNodes() {
+            return Iterables.transform(mod.getModifications(), new Function<NodeModification, DataTreeCandidateNode>() {
+                @Override
+                public DataTreeCandidateNode apply(final NodeModification input) {
+                    final PathArgument id = input.getIdentifier();
+                    return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
+                }
+            });
+        }
+
+        @Override
+        public ModificationType getModificationType() {
+            return mod.getModificationType();
+        }
+
+        private Optional<NormalizedNode<?, ?>> optionalData(StoreMetadataNode meta) {
+            if (meta == null) {
+                return Optional.absent();
+            }
+            return Optional.<NormalizedNode<?,?>>of(meta.getData());
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataAfter() {
+            return optionalData(newMeta);
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataBefore() {
+            return optionalData(oldMeta);
+        }
+    }
+
+    private static final class ChildNode extends AbstractNode {
+        public ChildNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) {
+            super(mod, oldMeta, newMeta);
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            return getMod().getIdentifier();
+        }
+    }
+
+    private static final class RootNode extends AbstractNode {
+        public RootNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) {
+            super(mod, oldMeta, newMeta);
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            throw new IllegalStateException("Attempted to get identifier of the root node");
+        }
+    }
+
+    private final RootNode root;
+
+    InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot,
+            final StoreMetadataNode oldRoot, final StoreMetadataNode newRoot) {
+        super(rootPath);
+        this.root = new RootNode(modificationRoot, oldRoot, newRoot);
+    }
+
+    StoreMetadataNode getAfterRoot() {
+        return root.getNewMeta();
+    }
+
+    StoreMetadataNode getBeforeRoot() {
+        return root.getOldMeta();
+    }
+
+    @Override
+    public DataTreeCandidateNode getRootNode() {
+        return root;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java
new file mode 100644 (file)
index 0000000..7614611
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeFactory;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * A factory for creating in-memory data trees.
+ */
+public final class InMemoryDataTreeFactory implements DataTreeFactory {
+       private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory();
+
+       private InMemoryDataTreeFactory() {
+               // Never instantiated externally
+       }
+
+       @Override
+       public InMemoryDataTree create() {
+               final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
+               final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
+
+               return new InMemoryDataTree(StoreMetadataNode.createEmpty(data), null);
+       }
+
+       /**
+        * Get an instance of this factory. This method cannot fail.
+        *
+        * @return Data tree factory instance.
+        */
+       public static final InMemoryDataTreeFactory getInstance() {
+               return INSTANCE;
+       }
+}
@@ -5,15 +5,15 @@
  * 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.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import static com.google.common.base.Preconditions.checkState;
 
 import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
@@ -26,28 +26,42 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 
-/*
- * FIXME: the thread safety of concurrent write/delete/read/seal operations
- *        needs to be evaluated.
- */
-class MutableDataTree {
-    private static final Logger LOG = LoggerFactory.getLogger(MutableDataTree.class);
-    private final AtomicBoolean sealed = new AtomicBoolean();
+final class InMemoryDataTreeModification implements DataTreeModification {
+    private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
+
+    /*
+     * FIXME: the thread safety of concurrent write/delete/read/seal operations
+     *        needs to be evaluated.
+     */
+    private static final AtomicIntegerFieldUpdater<InMemoryDataTreeModification> SEALED_UPDATER =
+            AtomicIntegerFieldUpdater.newUpdater(InMemoryDataTreeModification.class, "sealed");
+    private volatile int sealed = 0;
+
     private final ModificationApplyOperation strategyTree;
-    private final NodeModification rootModification;
-    private final DataTree.Snapshot snapshot;
+    private final InMemoryDataTreeSnapshot snapshot;
+    private final NodeModification rootNode;
 
-    private MutableDataTree(final DataTree.Snapshot snapshot, final ModificationApplyOperation strategyTree) {
+    InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
         this.snapshot = Preconditions.checkNotNull(snapshot);
-        this.strategyTree = Preconditions.checkNotNull(strategyTree);
-        this.rootModification = NodeModification.createUnmodified(snapshot.getRootNode());
+        this.strategyTree = Preconditions.checkNotNull(resolver);
+        this.rootNode = NodeModification.createUnmodified(snapshot.getRootNode());
+    }
+
+    NodeModification getRootModification() {
+        return rootNode;
     }
 
+    ModificationApplyOperation getStrategy() {
+        return strategyTree;
+    }
+
+    @Override
     public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
         checkSealed();
         resolveModificationFor(path).write(value);
     }
 
+    @Override
     public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
         checkSealed();
         mergeImpl(resolveModificationFor(path),data);
@@ -66,27 +80,30 @@ class MutableDataTree {
         op.merge(data);
     }
 
+    @Override
     public void delete(final InstanceIdentifier path) {
         checkSealed();
         resolveModificationFor(path).delete();
     }
 
-    public Optional<NormalizedNode<?, ?>> read(final InstanceIdentifier path) {
-        Entry<InstanceIdentifier, NodeModification> modification = TreeNodeUtils.findClosestsOrFirstMatch(rootModification, path, NodeModification.IS_TERMINAL_PREDICATE);
-
-        Optional<StoreMetadataNode> result = resolveSnapshot(modification);
+    @Override
+    public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+        /*
+         * Walk the tree from the top, looking for the first node between root and
+         * the requested path which has been modified. If no such node exists,
+         * we use the node itself.
+         */
+        final Entry<InstanceIdentifier, NodeModification> entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, NodeModification.IS_TERMINAL_PREDICATE);
+        final InstanceIdentifier key = entry.getKey();
+        final NodeModification mod = entry.getValue();
+
+        final Optional<StoreMetadataNode> result = resolveSnapshot(key, mod);
         if (result.isPresent()) {
             NormalizedNode<?, ?> data = result.get().getData();
-            return NormalizedNodeUtils.findNode(modification.getKey(), data, path);
+            return NormalizedNodeUtils.findNode(key, data, path);
+        } else {
+            return Optional.absent();
         }
-        return Optional.absent();
-    }
-
-    private Optional<StoreMetadataNode> resolveSnapshot(
-            final Entry<InstanceIdentifier, NodeModification> keyModification) {
-        InstanceIdentifier path = keyModification.getKey();
-        NodeModification modification = keyModification.getValue();
-        return resolveSnapshot(path, modification);
     }
 
     private Optional<StoreMetadataNode> resolveSnapshot(final InstanceIdentifier path,
@@ -110,7 +127,7 @@ class MutableDataTree {
     }
 
     private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
-        NodeModification modification = rootModification;
+        NodeModification modification = rootNode;
         // We ensure strategy is present.
         ModificationApplyOperation operation = resolveModificationStrategy(path);
         for (PathArgument pathArg : path.getPath()) {
@@ -119,26 +136,25 @@ class MutableDataTree {
         return OperationWithModification.from(operation, modification);
     }
 
-    public static MutableDataTree from(final DataTree.Snapshot snapshot, final ModificationApplyOperation resolver) {
-        return new MutableDataTree(snapshot, resolver);
-    }
-
+    @Override
     public void seal() {
-        final boolean success = sealed.compareAndSet(false, true);
+        final boolean success = SEALED_UPDATER.compareAndSet(this, 0, 1);
         Preconditions.checkState(success, "Attempted to seal an already-sealed Data Tree.");
-        rootModification.seal();
+        rootNode.seal();
     }
 
     private void checkSealed() {
-        checkState(!sealed.get(), "Data Tree is sealed. No further modifications allowed.");
+        checkState(sealed == 0, "Data Tree is sealed. No further modifications allowed.");
     }
 
-    protected NodeModification getRootModification() {
-        return rootModification;
+    @Override
+    public String toString() {
+        return "MutableDataTree [modification=" + rootNode + "]";
     }
 
     @Override
-    public String toString() {
-        return "MutableDataTree [modification=" + rootModification + "]";
+    public DataTreeModification newModification() {
+        // FIXME: transaction chaining
+        throw new UnsupportedOperationException("Implement this as part of transaction chaining");
     }
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java
new file mode 100644 (file)
index 0000000..ce2d8c9
--- /dev/null
@@ -0,0 +1,47 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
+    private final ModificationApplyOperation applyOper;
+    private final SchemaContext schemaContext;
+    private final StoreMetadataNode rootNode;
+
+    InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final StoreMetadataNode rootNode,
+            final ModificationApplyOperation applyOper) {
+        this.schemaContext = Preconditions.checkNotNull(schemaContext);
+        this.rootNode = Preconditions.checkNotNull(rootNode);
+        this.applyOper = Preconditions.checkNotNull(applyOper);
+    }
+
+    StoreMetadataNode getRootNode() {
+        return rootNode;
+    }
+
+    SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    @Override
+    public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+        return NormalizedNodeUtils.findNode(rootNode.getData(), path);
+    }
+
+    @Override
+    public InMemoryDataTreeModification newModification() {
+        return new InMemoryDataTreeModification(this, applyOper);
+    }
+
+    @Override
+    public String toString() {
+        return rootNode.getSubtreeVersion().toString();
+    }
+
+}
\ No newline at end of file
@@ -5,10 +5,9 @@
  * 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.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
@@ -38,7 +37,7 @@ import com.google.common.primitives.UnsignedLong;
  *
  *
  */
-public interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
+interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
 
     /**
      *
@@ -80,14 +79,14 @@ public interface ModificationApplyOperation extends StoreTreeNode<ModificationAp
     Optional<ModificationApplyOperation> getChild(PathArgument child);
 
     /**
-    *
-    * Checks if provided node modification could be applied to current metadata node.
-    *
-    * @param modification Modification
-    * @param current Metadata Node to which modification should be applied
-    * @return true if modification is applicable
-    *         false if modification is no applicable
+     *
+     * Checks if provided node modification could be applied to current metadata node.
+     *
+     * @param modification Modification
+     * @param current Metadata Node to which modification should be applied
+     * @return true if modification is applicable
+     *         false if modification is no applicable
      * @throws DataPreconditionFailedException
-    */
+     */
     void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
 }
@@ -5,7 +5,7 @@
  * 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.store.impl.tree;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import static com.google.common.base.Preconditions.checkState;
 
@@ -14,6 +14,8 @@ import java.util.Map;
 
 import javax.annotation.concurrent.GuardedBy;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -29,9 +31,8 @@ import com.google.common.base.Predicate;
  *
  * This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
  * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
- *
  */
-public class NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
+final class NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
 
     public static final Predicate<NodeModification> IS_TERMINAL_PREDICATE = new Predicate<NodeModification>() {
         @Override
@@ -67,7 +68,7 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
      *
      * @return
      */
-    public NormalizedNode<?, ?> getWritenValue() {
+    public NormalizedNode<?, ?> getWrittenValue() {
         return value;
     }
 
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java
new file mode 100644 (file)
index 0000000..8a46748
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.store.impl.tree.data;
+
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class NoopDataTreeCandidate extends AbstractDataTreeCandidate {
+    private static final DataTreeCandidateNode ROOT = new DataTreeCandidateNode() {
+        @Override
+        public ModificationType getModificationType() {
+            return ModificationType.UNMODIFIED;
+        }
+
+        @Override
+        public Iterable<DataTreeCandidateNode> getChildNodes() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            throw new IllegalStateException("Attempted to read identifier of the no-operation change");
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataAfter() {
+            return Optional.absent();
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataBefore() {
+            return Optional.absent();
+        }
+    };
+
+    protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot) {
+        super(rootPath);
+        Preconditions.checkArgument(modificationRoot.getModificationType() == ModificationType.UNMODIFIED);
+    }
+
+    @Override
+    public DataTreeCandidateNode getRootNode() {
+        return ROOT;
+    }
+}
@@ -5,17 +5,15 @@
  * 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.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
 import com.google.common.primitives.UnsignedLong;
 
-public class OperationWithModification {
+final class OperationWithModification {
 
     private final NodeModification modification;
 
@@ -5,7 +5,7 @@
  * 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.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
@@ -15,10 +15,9 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
@@ -70,7 +69,7 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.primitives.UnsignedLong;
 
-public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
+abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
 
     public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
         if (schemaNode instanceof ContainerSchemaNode) {
@@ -111,15 +110,17 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
     public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
             final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
         AugmentationSchema augSchema = null;
-        allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
-            boolean containsAll = true;
-            for (DataSchemaNode child : potential.getChildNodes()) {
-                if (identifier.getPossibleChildNames().contains(child.getQName())) {
-                    augSchema = potential;
-                    break allAugments;
+
+        allAugments:
+            for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
+                for (DataSchemaNode child : potential.getChildNodes()) {
+                    if (identifier.getPossibleChildNames().contains(child.getQName())) {
+                        augSchema = potential;
+                        break allAugments;
+                    }
                 }
             }
-        }
+
         if (augSchema != null) {
             return new AugmentationModificationStrategy(augSchema, resolvedTree);
         }
@@ -135,11 +136,11 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
     @Override
     public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
         if (modification.getModificationType() == ModificationType.WRITE) {
-            verifyWritenStructure(modification.getWritenValue());
+            verifyWrittenStructure(modification.getWrittenValue());
         }
     }
 
-    protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
+    protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
 
     @Override
     public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
@@ -233,8 +234,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
     protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
             StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
 
-    public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
-            SchemaAwareApplyOperation {
+    public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
 
         private final T schema;
         private final Class<? extends NormalizedNode<?, ?>> nodeClass;
@@ -246,8 +246,8 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
 
         @Override
-        protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
-            checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
+        protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+            checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
         }
 
         @Override
@@ -272,9 +272,8 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         @Override
         protected StoreMetadataNode applyWrite(final NodeModification modification,
                 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-            UnsignedLong nodeVersion = subtreeVersion;
-            return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
-                    .setData(modification.getWritenValue()).build();
+            return StoreMetadataNode.builder(subtreeVersion).setSubtreeVersion(subtreeVersion)
+                    .setData(modification.getWrittenValue()).build();
         }
 
         @Override
@@ -329,13 +328,20 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
 
         @SuppressWarnings("rawtypes")
         @Override
-        protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
-            checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
-            checkArgument(writenValue instanceof NormalizedNodeContainer);
-            NormalizedNodeContainer writenCont = (NormalizedNodeContainer) writenValue;
-            for (Object child : writenCont.getValue()) {
+        protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+            checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+            checkArgument(writtenValue instanceof NormalizedNodeContainer);
+
+            NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
+            for (Object child : container.getValue()) {
                 checkArgument(child instanceof NormalizedNode);
-                NormalizedNode childNode = (NormalizedNode) child;
+
+                /*
+                 * FIXME: fail-fast semantics:
+                 *
+                 * We can validate the data structure here, aborting the commit
+                 * before it ever progresses to being committed.
+                 */
             }
         }
 
@@ -343,7 +349,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         protected StoreMetadataNode applyWrite(final NodeModification modification,
                 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
 
-            NormalizedNode<?, ?> newValue = modification.getWritenValue();
+            NormalizedNode<?, ?> newValue = modification.getWrittenValue();
 
             final UnsignedLong nodeVersion;
             if (currentMeta.isPresent()) {
@@ -352,15 +358,14 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
                 nodeVersion = subtreeVersion;
             }
 
-            final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
+            final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion);
             if (!modification.hasAdditionalModifications()) {
                 return newValueMeta;
             }
 
             @SuppressWarnings("rawtypes")
             NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
-            StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
-                    .setNodeVersion(nodeVersion) //
+            StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(nodeVersion, dataBuilder) //
                     .setSubtreeVersion(subtreeVersion);
 
             return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
@@ -381,8 +386,8 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
 
             @SuppressWarnings("rawtypes")
             NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
-            StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder, currentMeta)
-                    .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
+            StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(dataBuilder, currentMeta)
+                    .setIdentifier(modification.getIdentifier())
                     .setSubtreeVersion(updatedSubtreeVersion);
 
             return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion);
@@ -436,8 +441,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
     }
 
-    public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
-            NormalizedNodeContainerModificationStrategy {
+    public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends NormalizedNodeContainerModificationStrategy {
 
         private final T schema;
         private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
@@ -487,8 +491,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
 
     }
 
-    public static class ContainerModificationStrategy extends
-            DataNodeContainerModificationStrategy<ContainerSchemaNode> {
+    public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
 
         public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
             super(schemaNode, ContainerNode.class);
@@ -502,8 +505,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
     }
 
-    public static class UnkeyedListItemModificationStrategy extends
-            DataNodeContainerModificationStrategy<ListSchemaNode> {
+    public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
 
         public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
             super(schemaNode, UnkeyedListEntryNode.class);
@@ -517,8 +519,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
     }
 
-    public static class AugmentationModificationStrategy extends
-            DataNodeContainerModificationStrategy<AugmentationSchema> {
+    public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy<AugmentationSchema> {
 
         protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
             super(createAugmentProxy(schema,resolved), AugmentationNode.class);
@@ -534,12 +535,10 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
 
     public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
 
-        private final ChoiceNode schema;
         private final Map<PathArgument, ModificationApplyOperation> childNodes;
 
         public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
             super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
-            this.schema = schemaNode;
             ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
 
             for (ChoiceCaseNode caze : schemaNode.getCases()) {
@@ -653,7 +652,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         @Override
         protected StoreMetadataNode applyWrite(final NodeModification modification,
                 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-            return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
+            return StoreMetadataNode.createRecursively(modification.getWrittenValue(), subtreeVersion);
         }
 
         @Override
@@ -665,7 +664,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
 
         @Override
-        protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
+        protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
 
         }
 
@@ -737,10 +736,6 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
     }
 
-    public void verifyIdentifier(final PathArgument identifier) {
-
-    }
-
     public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
         Set<DataSchemaNode> realChildSchemas = new HashSet<>();
         for(DataSchemaNode augChild : schema.getChildNodes()) {
@@ -5,7 +5,7 @@
  * 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.store.impl.tree;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import static com.google.common.base.Preconditions.checkState;
 
@@ -23,14 +23,12 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.primitives.UnsignedLong;
 
-public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
-
+class StoreMetadataNode implements Immutable, Identifiable<PathArgument> {
+    private final Map<PathArgument, StoreMetadataNode> children;
     private final UnsignedLong nodeVersion;
     private final UnsignedLong subtreeVersion;
     private final NormalizedNode<?, ?> data;
 
-    private final Map<PathArgument, StoreMetadataNode> children;
-
     /**
      *
      * @param data
@@ -38,11 +36,11 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
      * @param subtreeVersion
      * @param children Map of children, must not be modified externally
      */
-    protected StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
+    private StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
             final UnsignedLong subtreeVersion, final Map<PathArgument, StoreMetadataNode> children) {
-        this.nodeVersion = nodeVersion;
-        this.subtreeVersion = subtreeVersion;
-        this.data = data;
+        this.nodeVersion = Preconditions.checkNotNull(nodeVersion);
+        this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+        this.data = Preconditions.checkNotNull(data);
         this.children = Preconditions.checkNotNull(children);
     }
 
@@ -51,16 +49,11 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
                 Collections.<PathArgument, StoreMetadataNode>emptyMap());
     }
 
-    public StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
-            final UnsignedLong subtreeVersion) {
-        this(data, nodeVersion, subtreeVersion, Collections.<PathArgument, StoreMetadataNode>emptyMap());
-    }
-
-    public static Builder builder() {
-        return new Builder();
+    public static Builder builder(final UnsignedLong version) {
+        return new Builder(version);
     }
 
-    public static Builder builder(StoreMetadataNode node) {
+    public static Builder builder(final StoreMetadataNode node) {
         return new Builder(node);
     }
 
@@ -81,8 +74,7 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
         return this.data;
     }
 
-    @Override
-    public Optional<StoreMetadataNode> getChild(final PathArgument key) {
+    Optional<StoreMetadataNode> getChild(final PathArgument key) {
         return Optional.fromNullable(children.get(key));
     }
 
@@ -91,33 +83,17 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
         return "StoreMetadataNode [identifier=" + getIdentifier() + ", nodeVersion=" + nodeVersion + "]";
     }
 
-    public static Optional<UnsignedLong> getVersion(final Optional<StoreMetadataNode> currentMetadata) {
-        if (currentMetadata.isPresent()) {
-            return Optional.of(currentMetadata.get().getNodeVersion());
-        }
-        return Optional.absent();
-    }
-
-    public static Optional<StoreMetadataNode> getChild(final Optional<StoreMetadataNode> parent,
-            final PathArgument child) {
-        if (parent.isPresent()) {
-            return parent.get().getChild(child);
-        }
-        return Optional.absent();
-    }
-
     public static final StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node,
-            final UnsignedLong nodeVersion, final UnsignedLong subtreeVersion) {
-        Builder builder = builder() //
-                .setNodeVersion(nodeVersion) //
-                .setSubtreeVersion(subtreeVersion) //
+            final UnsignedLong version) {
+        Builder builder = builder(version) //
+                .setSubtreeVersion(version) //
                 .setData(node);
         if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
 
             @SuppressWarnings("unchecked")
             NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> nodeContainer = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) node;
             for (NormalizedNode<?, ?> subNode : nodeContainer.getValue()) {
-                builder.add(createRecursively(subNode, nodeVersion, subtreeVersion));
+                builder.add(createRecursively(subNode, version));
             }
         }
         return builder.build();
@@ -125,30 +101,22 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
 
     public static class Builder {
 
-        private UnsignedLong nodeVersion;
+        private final UnsignedLong nodeVersion;
         private UnsignedLong subtreeVersion;
         private NormalizedNode<?, ?> data;
         private Map<PathArgument, StoreMetadataNode> children;
         private boolean dirty = false;
 
-        private Builder() {
+        private Builder(final UnsignedLong version) {
+            this.nodeVersion = Preconditions.checkNotNull(version);
             children = new HashMap<>();
         }
 
-        public Builder(StoreMetadataNode node) {
+        private Builder(final StoreMetadataNode node) {
+            this.nodeVersion = node.getNodeVersion();
             children = new HashMap<>(node.children);
         }
 
-        public UnsignedLong getVersion() {
-            return nodeVersion;
-
-        }
-
-        public Builder setNodeVersion(final UnsignedLong version) {
-            this.nodeVersion = version;
-            return this;
-        }
-
         public Builder setSubtreeVersion(final UnsignedLong version) {
             this.subtreeVersion = version;
             return this;
@@ -186,7 +154,4 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
         }
     }
 
-    public static StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node, final UnsignedLong version) {
-        return createRecursively(node, version, version);
-    }
 }
@@ -5,7 +5,7 @@
  * 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.store.impl.tree;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
@@ -20,18 +20,18 @@ import com.google.common.primitives.UnsignedLong;
  *
  */
 @SuppressWarnings("rawtypes")
-public class StoreNodeCompositeBuilder {
+class StoreNodeCompositeBuilder {
 
     private final StoreMetadataNode.Builder metadata;
 
     private final NormalizedNodeContainerBuilder data;
 
-    private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder) {
-        this.metadata = StoreMetadataNode.builder();
+    private StoreNodeCompositeBuilder(final UnsignedLong version, final NormalizedNodeContainerBuilder nodeBuilder) {
+        this.metadata = StoreMetadataNode.builder(version);
         this.data = Preconditions.checkNotNull(nodeBuilder);
     }
 
-    public StoreNodeCompositeBuilder(NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
+    private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder, final StoreMetadataNode currentMeta) {
         this.metadata = StoreMetadataNode.builder(currentMeta);
         this.data = Preconditions.checkNotNull(nodeBuilder);
     }
@@ -44,7 +44,7 @@ public class StoreNodeCompositeBuilder {
     }
 
     @SuppressWarnings("unchecked")
-    public StoreNodeCompositeBuilder remove(PathArgument id) {
+    public StoreNodeCompositeBuilder remove(final PathArgument id) {
         metadata.remove(id);
         data.removeChild(id);
         return this;
@@ -54,11 +54,11 @@ public class StoreNodeCompositeBuilder {
         return metadata.setData(data.build()).build();
     }
 
-    public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder) {
-        return new StoreNodeCompositeBuilder(nodeBuilder);
+    public static StoreNodeCompositeBuilder create(final UnsignedLong version, final NormalizedNodeContainerBuilder nodeBuilder) {
+        return new StoreNodeCompositeBuilder(version, nodeBuilder);
     }
 
-    public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
+    public static StoreNodeCompositeBuilder create(final NormalizedNodeContainerBuilder nodeBuilder, final StoreMetadataNode currentMeta) {
         return new StoreNodeCompositeBuilder(nodeBuilder, currentMeta);
     }
 
@@ -68,11 +68,6 @@ public class StoreNodeCompositeBuilder {
         return this;
     }
 
-    public StoreNodeCompositeBuilder setNodeVersion(final UnsignedLong nodeVersion) {
-        metadata.setNodeVersion(nodeVersion);
-        return this;
-    }
-
     public StoreNodeCompositeBuilder setSubtreeVersion(final UnsignedLong updatedSubtreeVersion) {
         metadata.setSubtreeVersion(updatedSubtreeVersion);
         return this;
index 9cbf4282e47649ee42302746d4078d202924c2fe..357a516b57ab29575f4742c6ac2230ddc9aa1ead 100644 (file)
@@ -8,29 +8,22 @@
 package org.opendaylight.controller.sal.dom.broker
 
 import java.util.Hashtable
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker
+import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService
 import org.opendaylight.controller.sal.core.api.data.DataProviderService
 import org.opendaylight.controller.sal.core.api.data.DataStore
 import org.opendaylight.controller.sal.core.api.model.SchemaService
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
 import org.opendaylight.controller.sal.core.api.mount.MountService
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener
 import org.osgi.framework.BundleContext
 import org.osgi.framework.ServiceRegistration
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker
-import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl
-import com.google.common.util.concurrent.MoreExecutors
-import com.google.common.collect.ImmutableMap
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType
-import org.opendaylight.controller.sal.core.spi.data.DOMStore
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore
-import java.util.concurrent.Executors
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker
 
 class BrokerConfigActivator implements AutoCloseable {
 
@@ -1,4 +1,11 @@
-package org.opendaylight.controller.md.sal.dom.store.impl;
+/*
+ * 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.store.impl.tree.data;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -19,7 +26,9 @@ import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.ma
 
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -89,14 +98,16 @@ public class ModificationMetadataTreeTest {
                     .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_ONE_NAME)) //
                     .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME)) //
                     .build()) //
-            .build();
+                    .build();
 
     private SchemaContext schemaContext;
+    private ModificationApplyOperation applyOper;
 
     @Before
     public void prepare() {
         schemaContext = TestModel.createTestContext();
         assertNotNull("Schema context must not be null.", schemaContext);
+        applyOper = SchemaAwareApplyOperation.from(schemaContext);
     }
 
     /**
@@ -131,16 +142,16 @@ public class ModificationMetadataTreeTest {
                 .withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
                 .withChild(
                         mapNodeBuilder(OUTER_LIST_QNAME)
-                                .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
-                                .withChild(BAR_NODE).build()).build();
+                        .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
+                        .withChild(BAR_NODE).build()).build();
     }
 
     @Test
     public void basicReadWrites() {
-        MutableDataTree modificationTree = MutableDataTree.from(new DataTree.Snapshot(schemaContext,
-                StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))),
+        DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
+                StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5)), applyOper),
                 new SchemaAwareApplyOperationRoot(schemaContext));
-        Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.read(OUTER_LIST_2_PATH);
+        Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
         assertTrue(originalBarNode.isPresent());
         assertSame(BAR_NODE, originalBarNode.get());
 
@@ -149,22 +160,23 @@ public class ModificationMetadataTreeTest {
 
         // reads node to /outer-list/1/inner_list/two/value
         // and checks if node is already present
-        Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.read(TWO_TWO_VALUE_PATH);
+        Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.readNode(TWO_TWO_VALUE_PATH);
         assertTrue(barTwoCModified.isPresent());
         assertEquals(ImmutableNodes.leafNode(VALUE_QNAME, "test"), barTwoCModified.get());
 
         // delete node to /outer-list/1/inner_list/two/value
         modificationTree.delete(TWO_TWO_VALUE_PATH);
-        Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.read(TWO_TWO_VALUE_PATH);
+        Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.readNode(TWO_TWO_VALUE_PATH);
         assertFalse(barTwoCAfterDelete.isPresent());
     }
 
 
-    public MutableDataTree createEmptyModificationTree() {
+    public DataTreeModification createEmptyModificationTree() {
         /**
          * Creates empty Snapshot with associated schema context.
          */
-        DataTree t = DataTree.create(schemaContext);
+        DataTree t = InMemoryDataTreeFactory.getInstance().create();
+        t.setSchemaContext(schemaContext);
 
         /**
          *
@@ -172,15 +184,13 @@ public class ModificationMetadataTreeTest {
          * context.
          *
          */
-        MutableDataTree modificationTree = MutableDataTree.from(t.takeSnapshot(), new SchemaAwareApplyOperationRoot(
-                schemaContext));
-        return modificationTree;
+        return t.takeSnapshot().newModification();
     }
 
     @Test
     public void createFromEmptyState() {
 
-        MutableDataTree modificationTree = createEmptyModificationTree();
+        DataTreeModification modificationTree = createEmptyModificationTree();
         /**
          * Writes empty container node to /test
          *
@@ -195,14 +205,14 @@ public class ModificationMetadataTreeTest {
         /**
          * Reads list node from /test/outer-list
          */
-        Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.read(OUTER_LIST_PATH);
+        Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.readNode(OUTER_LIST_PATH);
         assertTrue(potentialOuterList.isPresent());
 
         /**
          * Reads container node from /test and verifies that it contains test
          * node
          */
-        Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.read(TEST_PATH);
+        Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.readNode(TEST_PATH);
         ContainerNode containerTest = assertPresentAndType(potentialTest, ContainerNode.class);
 
         /**
@@ -217,23 +227,23 @@ public class ModificationMetadataTreeTest {
 
     @Test
     public void writeSubtreeReadChildren() {
-        MutableDataTree modificationTree = createEmptyModificationTree();
+        DataTreeModification modificationTree = createEmptyModificationTree();
         modificationTree.write(TEST_PATH, createTestContainer());
-        Optional<NormalizedNode<?, ?>> potential = modificationTree.read(TWO_TWO_PATH);
-        MapEntryNode node = assertPresentAndType(potential, MapEntryNode.class);
+        Optional<NormalizedNode<?, ?>> potential = modificationTree.readNode(TWO_TWO_PATH);
+        assertPresentAndType(potential, MapEntryNode.class);
     }
 
     @Test
     public void writeSubtreeDeleteChildren() {
-        MutableDataTree modificationTree = createEmptyModificationTree();
+        DataTreeModification modificationTree = createEmptyModificationTree();
         modificationTree.write(TEST_PATH, createTestContainer());
 
         // We verify data are present
-        Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.read(TWO_TWO_PATH);
-        MapEntryNode node = assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
+        Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.readNode(TWO_TWO_PATH);
+        assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
 
         modificationTree.delete(TWO_TWO_PATH);
-        Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.read(TWO_TWO_PATH);
+        Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.readNode(TWO_TWO_PATH);
         assertFalse(potentialAfterDelete.isPresent());
 
     }
@@ -5,7 +5,7 @@
  * 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.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
index 89274c9ad5e356a3532e0639a5c5c1b2fbf04ebd..1839de15975f381ebc8d32980050cfb16ace72ad 100644 (file)
@@ -17,8 +17,10 @@ import java.io.File;
 import java.io.InputStream;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.URI;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
@@ -27,8 +29,10 @@ import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClient
 import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
 import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
@@ -36,6 +40,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider;
 import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider;
 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
index 8f95e73b15cdcd8307612bb155a0c3c406647a57..e721084763732900a1820e83e4b7d7d92f051d0e 100644 (file)
@@ -180,10 +180,10 @@ public class ClientImpl implements RemoteRpcClient {
    * @param  routeId route identifier
    * @return         remote network address
    */
-  private String lookupRemoteAddressForGlobalRpc(RpcRouter.RouteIdentifier routeId){
+  private String lookupRemoteAddressForGlobalRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
     checkNotNull(routeId, "route must not be null");
 
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable = routingTableProvider.getRoutingTable();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
     checkNotNull(routingTable.isPresent(), "Routing table is null");
 
     String address = null;
@@ -202,10 +202,10 @@ public class ClientImpl implements RemoteRpcClient {
    * @param  routeId route identifier
    * @return         remote network address
    */
-  private String lookupRemoteAddressForRpc(RpcRouter.RouteIdentifier routeId){
+  private String lookupRemoteAddressForRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
     checkNotNull(routeId, "route must not be null");
 
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable = routingTableProvider.getRoutingTable();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
     checkNotNull(routingTable.isPresent(), "Routing table is null");
 
     String address = routingTable.get().getLastAddedRoute(routeId);
@@ -230,7 +230,7 @@ public class ClientImpl implements RemoteRpcClient {
    */
   private void closeZmqContext() {
     ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask zmqTermination = new FutureTask(new Runnable() {
+    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
 
       @Override
       public void run() {
index 9e66c20613e89db5cc5825e376b339ef52f9bba7..37bff7b7bba8ce091be33dc11a0ffff14979993f 100644 (file)
@@ -7,19 +7,19 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import org.zeromq.ZMQ;
-
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.Enumeration;
 
+import org.zeromq.ZMQ;
+
 /**
  * Provides a ZeroMQ Context object
  */
 public class Context {
-  private ZMQ.Context zmqContext = ZMQ.context(1);
+  private final ZMQ.Context zmqContext = ZMQ.context(1);
   private String uri;
   private final String DEFAULT_RPC_PORT = "5554";
 
@@ -69,7 +69,7 @@ public class Context {
    */
   private String findIpAddress() {
     String hostAddress = null;
-    Enumeration e = null;
+    Enumeration<?> e = null;
     try {
       e = NetworkInterface.getNetworkInterfaces();
     } catch (SocketException e1) {
@@ -79,7 +79,7 @@ public class Context {
 
       NetworkInterface n = (NetworkInterface) e.nextElement();
 
-      Enumeration ee = n.getInetAddresses();
+      Enumeration<?> ee = n.getInetAddresses();
       while (ee.hasMoreElements()) {
         InetAddress i = (InetAddress) ee.nextElement();
         if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
index a564a0ad045a533818135b2921c173e684a603b1..94e3232f17b1505f51ff51371c9e7dd1d767a93f 100644 (file)
@@ -8,14 +8,11 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-
 public interface RemoteRpcClient extends AutoCloseable{
 
     void setRoutingTableProvider(RoutingTableProvider provider);
-    
+
     void stop();
-    
+
     void start();
 }
index 53fbb929bb3a5c5942851a224f71c263f6ec2305..76df25682e1b79df3f7762ac1fb8094dac5eda18 100644 (file)
@@ -58,7 +58,7 @@ public class RemoteRpcProvider implements
   private ProviderSession brokerSession;
   private RpcProvisionRegistry rpcProvisionRegistry;
   private BundleContext context;
-  private ServiceTracker clusterTracker;
+  private ServiceTracker<?, ?> clusterTracker;
 
   public RemoteRpcProvider(ServerImpl server, ClientImpl client) {
     this.server = server;
@@ -170,8 +170,8 @@ public class RemoteRpcProvider implements
 
   }
 
-  private RoutingTable<RpcRouter.RouteIdentifier, String> getRoutingTable(){
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable =
+  private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> getRoutingTable(){
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable =
         routingTableProvider.getRoutingTable();
 
     checkState(routingTable.isPresent(), "Routing table is null");
@@ -191,7 +191,7 @@ public class RemoteRpcProvider implements
       RouteIdentifierImpl routeId = new RouteIdentifierImpl();
       routeId.setType(rpc);
 
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
 
       try {
         routingTable.addGlobalRoute(routeId, server.getServerAddress());
@@ -212,7 +212,7 @@ public class RemoteRpcProvider implements
       RouteIdentifierImpl routeId = new RouteIdentifierImpl();
       routeId.setType(rpc);
 
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
 
       try {
         routingTable.removeGlobalRoute(routeId);
@@ -245,9 +245,9 @@ public class RemoteRpcProvider implements
      *
      * @param announcements
      */
-    private void announce(Set<RpcRouter.RouteIdentifier> announcements) {
+    private void announce(Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements) {
       _logger.debug("Announcing [{}]", announcements);
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
       try {
         routingTable.addRoutes(announcements, server.getServerAddress());
       } catch (RoutingTableException | SystemException e) {
@@ -259,9 +259,9 @@ public class RemoteRpcProvider implements
      *
      * @param removals
      */
-    private void remove(Set<RpcRouter.RouteIdentifier> removals){
+    private void remove(Set<RpcRouter.RouteIdentifier<?, ?, ?>> removals){
       _logger.debug("Removing [{}]", removals);
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
       try {
         routingTable.removeRoutes(removals, server.getServerAddress());
       } catch (RoutingTableException | SystemException e) {
@@ -274,9 +274,9 @@ public class RemoteRpcProvider implements
      * @param changes
      * @return
      */
-    private Set<RpcRouter.RouteIdentifier> getRouteIdentifiers(Map<RpcRoutingContext, Set<InstanceIdentifier>> changes) {
+    private Set<RpcRouter.RouteIdentifier<?, ?, ?>> getRouteIdentifiers(Map<RpcRoutingContext, Set<InstanceIdentifier>> changes) {
       RouteIdentifierImpl routeId = null;
-      Set<RpcRouter.RouteIdentifier> routeIdSet = new HashSet<RpcRouter.RouteIdentifier>();
+      Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdSet = new HashSet<>();
 
       for (RpcRoutingContext context : changes.keySet()){
         routeId = new RouteIdentifierImpl();
index 71bab288e6ce3c38c555a036cf3a6b05c35af4de..d960303fcf4b45c5ec5ac7d35ccff04f2fee4a3b 100644 (file)
@@ -8,25 +8,24 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import com.google.common.base.Optional;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
 import org.opendaylight.controller.sal.connector.remoterpc.impl.RoutingTableImpl;
 import org.osgi.framework.BundleContext;
 import org.osgi.util.tracker.ServiceTracker;
 
+import com.google.common.base.Optional;
+
 public class RoutingTableProvider implements AutoCloseable {
 
     @SuppressWarnings("rawtypes")
     final ServiceTracker<RoutingTable,RoutingTable> tracker;
 
-    private RoutingTableImpl routingTableImpl = null;
+    private RoutingTableImpl<?, ?> routingTableImpl = null;
 
     //final private RouteChangeListener routeChangeListener;
-    
-    
+
+
     public RoutingTableProvider(BundleContext ctx){//,RouteChangeListener rcl) {
         @SuppressWarnings("rawtypes")
         ServiceTracker<RoutingTable, RoutingTable> rawTracker = new ServiceTracker<>(ctx, RoutingTable.class, null);
@@ -35,14 +34,14 @@ public class RoutingTableProvider implements AutoCloseable {
 
         //routeChangeListener = rcl;
     }
-    
-    public Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> getRoutingTable() {
+
+    public Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> getRoutingTable() {
         @SuppressWarnings("unchecked")
-        RoutingTable<RpcRouter.RouteIdentifier,String> tracked = tracker.getService();
+        RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> tracked = tracker.getService();
 
         if(tracked instanceof RoutingTableImpl){
             if(routingTableImpl != tracked){
-             routingTableImpl= (RoutingTableImpl)tracked;
+             routingTableImpl= (RoutingTableImpl<?, ?>)tracked;
              //routingTableImpl.setRouteChangeListener(routeChangeListener);
             }
         }
index d256b998d4f8abd254fffea087778600a1b70051..3acea356ceb4747feb48a3ae6126e0435708f74f 100644 (file)
@@ -7,48 +7,33 @@
  */
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Sets;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
-import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.Enumeration;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 /**
  * ZeroMq based implementation of RpcRouter.
  */
 public class ServerImpl implements RemoteRpcServer {
 
-  private Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
+  private final Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
 
   private ExecutorService serverPool;
   protected ServerRequestHandler handler;
@@ -63,7 +48,7 @@ public class ServerImpl implements RemoteRpcServer {
   private volatile State status = State.STOPPED;
 
   private String serverAddress;
-  private int port;
+  private final int port;
 
   public static enum State {
     STARTING, STARTED, STOPPED;
@@ -167,7 +152,7 @@ public class ServerImpl implements RemoteRpcServer {
    */
   private void closeZmqContext() {
     ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask zmqTermination = new FutureTask(new Runnable() {
+    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
 
       @Override
       public void run() {
@@ -249,7 +234,7 @@ public class ServerImpl implements RemoteRpcServer {
    * @return
    */
   private String findIpAddress() {
-    Enumeration e = null;
+    Enumeration<?> e = null;
     try {
       e = NetworkInterface.getNetworkInterfaces();
     } catch (SocketException e1) {
@@ -260,7 +245,7 @@ public class ServerImpl implements RemoteRpcServer {
 
       NetworkInterface n = (NetworkInterface) e.nextElement();
 
-      Enumeration ee = n.getInetAddresses();
+      Enumeration<?> ee = n.getInetAddresses();
       while (ee.hasMoreElements()) {
         InetAddress i = (InetAddress) ee.nextElement();
         _logger.debug("Trying address {}", i);
index 2041f03afba07c58146c1c2d449d3e1f5d2ccc3d..a25387d297935351bbec8d3f6b0af13638f43286 100644 (file)
@@ -8,38 +8,39 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
 import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
 import org.opendaylight.controller.sal.core.api.Broker;
 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.zeromq.ZMQ;
 
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Collection;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
 /**
  *
  */
 public class ServerRequestHandler implements AutoCloseable{
 
-  private Logger _logger = LoggerFactory.getLogger(ServerRequestHandler.class);
+  private final Logger _logger = LoggerFactory.getLogger(ServerRequestHandler.class);
   private final String DEFAULT_NAME = "remote-rpc-worker";
-  private String dealerAddress;
-  private String serverAddress;
-  private int workerCount;
-  private ZMQ.Context context;
-  private Broker.ProviderSession broker;
+  private final String dealerAddress;
+  private final String serverAddress;
+  private final int workerCount;
+  private final ZMQ.Context context;
+  private final Broker.ProviderSession broker;
 
   private RequestHandlerThreadPool workerPool;
   private final AtomicInteger threadId = new AtomicInteger();
@@ -87,7 +88,7 @@ public class ServerRequestHandler implements AutoCloseable{
    * Worker to handles RPC request
    */
   private class Worker implements Runnable {
-    private String name;
+    private final String name;
 
     public Worker(int id){
       this.name = DEFAULT_NAME + "-" + id;
@@ -187,7 +188,7 @@ public class ServerRequestHandler implements AutoCloseable{
   }
 
   class MessageHandler{
-    private ZMQ.Socket socket;
+    private final ZMQ.Socket socket;
     private Message message;          //parsed message received on zmq server port
     private boolean messageForBroker = false; //if the message is valid and not a "ping" message
 
@@ -236,7 +237,7 @@ public class ServerRequestHandler implements AutoCloseable{
       CompositeNode payload = (result != null) ? result.getResult() : null;
 
       String recipient = null;
-      RpcRouter.RouteIdentifier routeId = null;
+      RpcRouter.RouteIdentifier<?, ?, ?> routeId = null;
 
       if (message != null) {
         recipient = message.getSender();
index 21d02be7d7295b5514b4819310f74a744fcb0ae0..cbcfe3e2a9e4833a2c88ffc08fd2bb05b0ed3d79 100644 (file)
@@ -41,7 +41,7 @@ public class Message implements Serializable {
   private MessageType type;
   private String sender;
   private String recipient;
-  private RpcRouter.RouteIdentifier route;
+  private RpcRouter.RouteIdentifier<?, ?, ?> route;
   private Object payload;
 
   public MessageType getType() {
@@ -60,11 +60,11 @@ public class Message implements Serializable {
     this.sender = sender;
   }
 
-  public RpcRouter.RouteIdentifier getRoute() {
+  public RpcRouter.RouteIdentifier<?, ?, ?> getRoute() {
     return route;
   }
 
-  public void setRoute(RpcRouter.RouteIdentifier route) {
+  public void setRoute(RpcRouter.RouteIdentifier<?, ?, ?> route) {
     this.route = route;
   }
 
@@ -123,7 +123,7 @@ public class Message implements Serializable {
     return o.readObject();
   }
 
-  public static class Response extends Message implements RpcRouter.RpcReply {
+  public static class Response extends Message implements RpcRouter.RpcReply<Object> {
     private static final long serialVersionUID = 1L;
     private ResponseCode code; // response code
 
@@ -173,7 +173,7 @@ public class Message implements Serializable {
       return this;
     }
 
-    public MessageBuilder route(RpcRouter.RouteIdentifier route){
+    public MessageBuilder route(RpcRouter.RouteIdentifier<?, ?, ?> route){
       message.setRoute(route);
       return this;
     }
index 0fa12e351c19d075ce934f4ca2ccccafa6918514..f8d14ce62e190a19faf1496b73923cb1a4d25ad0 100644 (file)
@@ -40,8 +40,8 @@ public class ClientImplTest {
 
     //mock routing table
     routingTableProvider = mock(RoutingTableProvider.class);
-    RoutingTable<RpcRouter.RouteIdentifier, String> mockRoutingTable = new MockRoutingTable<String, String>();
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
+    RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> mockRoutingTable = new MockRoutingTable<String, String>();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
     when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
 
     //mock ClientRequestHandler
index 1edd004d3725a5fcbe55a8e7057087cdd83a5b53..09188683cd5ef8e6cc79f6fa3e57825f709279a5 100644 (file)
@@ -99,7 +99,7 @@ public class ClientRequestHandlerTest {
   private Message handleMessageWithTimeout(final Message request) {
     Message response = null;
 
-    FutureTask task = new FutureTask(new Callable<Message>() {
+    FutureTask<?> task = new FutureTask<Message>(new Callable<Message>() {
 
       @Override
       public Message call() {
index 0fe0155bb6a90e48a24e3ce7d3ecaaee37f956f8..179051e4d48ecb2e2f7f7d81b3cabaedb267c5f0 100644 (file)
@@ -7,16 +7,13 @@
  */
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
 import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
 /**
  * Mock implementation of routing table
  */
@@ -59,7 +56,7 @@ public class MockRoutingTable<K, V> implements RoutingTable {
   }
 
   @Override
-  public Set getRoutes(Object o) {
+  public Set<String> getRoutes(Object o) {
     Set<String> routes = new HashSet<String>();
     routes.add("localhost:5554");
     return routes;
index 886ff426c7948d4a95d778d0f5717da1f0aa582e..7ffdf17ce761a2adb0ae763d2bcf15444e958c6f 100644 (file)
@@ -8,28 +8,34 @@
 package org.opendaylight.controller.sal.connector.remoterpc;
 
 
-import com.google.common.base.Optional;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+
 import junit.framework.Assert;
-import org.junit.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
 import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.zeromq.ZMQ;
+
 import zmq.Ctx;
 import zmq.SocketBase;
 
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ThreadPoolExecutor;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import com.google.common.base.Optional;
 
 public class ServerImplTest {
 
@@ -68,12 +74,12 @@ public class ServerImplTest {
     server = new ServerImpl(port);
     server.setBrokerSession(brokerSession);
 
-    RoutingTable<RpcRouter.RouteIdentifier, String> mockRoutingTable = new MockRoutingTable<String, String>();
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
+    RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> mockRoutingTable = new MockRoutingTable<String, String>();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
     when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
 
     when(brokerSession.addRpcRegistrationListener(listener)).thenReturn(null);
-    when(brokerSession.getSupportedRpcs()).thenReturn(Collections.EMPTY_SET);
+    when(brokerSession.getSupportedRpcs()).thenReturn(Collections.<QName>emptySet());
     when(brokerSession.rpc(null, mock(CompositeNode.class))).thenReturn(null);
     server.start();
     Thread.sleep(5000);//wait for server to start
@@ -178,7 +184,7 @@ public class ServerImplTest {
     Thread[] threads = new Thread[Thread.activeCount()];
     Thread.enumerate(threads);
 
-    List<Thread> foundThreads = new ArrayList();
+    List<Thread> foundThreads = new ArrayList<Thread>();
     for (Thread t : threads) {
       if (t.getName().startsWith(name))
         foundThreads.add(t);
index 6e39867e5368cbb30d1db4b174890d79bb30b983..e5fbc761b4a9b02664f9729572de253d46e5c041 100644 (file)
@@ -7,7 +7,15 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 import junit.framework.Assert;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -15,22 +23,15 @@ import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.zeromq.ZMQ;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import static org.mockito.Mockito.mock;
-
 public class ServerRequestHandlerTest {
 
   ServerRequestHandler handler;
   ZMQ.Context context;
   ExecutorService executorService = Executors.newCachedThreadPool();
-  private int workerCount = 2;
-  private String mockDealerAddress = "inproc://rpc-request-handler";
-  private String mockServerIp = "localhost";
-  private int mockServerPort = 5554;
+  private final int workerCount = 2;
+  private final String mockDealerAddress = "inproc://rpc-request-handler";
+  private final String mockServerIp = "localhost";
+  private final int mockServerPort = 5554;
 
   @Before
   public void setUp() throws Exception {
@@ -98,7 +99,7 @@ public class ServerRequestHandlerTest {
     Thread[] threads = new Thread[Thread.activeCount()];
     Thread.enumerate(threads);
 
-    List<Thread> foundThreads = new ArrayList();
+    List<Thread> foundThreads = new ArrayList<Thread>();
     for (Thread t : threads) {
       if (t.getName().startsWith(name))
         foundThreads.add(t);
index a68ee574f339526fa2c7a3f5b06e23a78ea13700..883aa52f3f278d5bd725d9c99c1406f795caf04f 100644 (file)
@@ -7,12 +7,6 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc.utils;
 
-import junit.framework.Assert;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -21,6 +15,13 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
 
+import junit.framework.Assert;
+
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
 public class MessagingUtil {
 
   private static final Logger _logger = LoggerFactory.getLogger(MessagingUtil.class);
@@ -160,7 +161,7 @@ public class MessagingUtil {
     if (context == null) return;
 
     ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask zmqTermination = new FutureTask(new Runnable() {
+    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
 
       @Override
       public void run() {
index a71ab865aa717b84edcc615a6f01d750ac417132..7a4f4a5974606c945a3538fcebe8623f226ddc03 100644 (file)
@@ -1,14 +1,14 @@
 package org.opendaylight.controller.sal.connector.remoterpc.utils;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
 import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.zeromq.ZMQ;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
 public class RemoteServerTestClient {
 
 
@@ -39,7 +39,7 @@ public class RemoteServerTestClient {
   }
   public Message createAddFlowMessage(String serverAddress ){
 
-    RpcRouter.RouteIdentifier routeIdentifier = getAddFlowRpcIdentifier();
+    RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier = getAddFlowRpcIdentifier();
 
     Message addFlow = new Message.MessageBuilder()
         .type(Message.MessageType.REQUEST)
@@ -52,7 +52,7 @@ public class RemoteServerTestClient {
     return addFlow;
   }
 
-  private RpcRouter.RouteIdentifier getAddFlowRpcIdentifier(){
+  private RpcRouter.RouteIdentifier<?, ?, ?> getAddFlowRpcIdentifier(){
     throw new UnsupportedOperationException();
   }
 
index 423d2e48ce7ba73dfdf7eb55528b6c9baf4710ed..8954c058116639b6dae8af9227930209fcfdb81e 100644 (file)
@@ -7,7 +7,6 @@
     <version>1.1-SNAPSHOT</version>
   </parent>
 
-  <groupId>org.opendaylight.controller</groupId>
   <artifactId>sal-rest-docgen</artifactId>
   <packaging>bundle</packaging>
 
@@ -94,7 +93,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.4.0</version>
         <extensions>true</extensions>
         <configuration>
 
index cb8f66081b7dee8b0205b34132ed0b131dac98c6..8f6a7cd1e4d2e4f19918d97fdfbb8f928060a696 100644 (file)
@@ -12,13 +12,8 @@ import com.google.common.base.Preconditions;
 import java.util.List;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
-    private static final Logger logger = LoggerFactory.getLogger(SimpleAttributeReadingStrategy.class);
-
-
     public SimpleAttributeReadingStrategy(String nullableDefault) {
         super(nullableDefault);
     }
@@ -29,20 +24,7 @@ public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStra
         Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + xmlElement
                 + " but was " + configNodes.size());
 
-        String textContent = "";
-        try{
-            textContent = readElementContent(xmlElement);
-        }catch(IllegalStateException | NullPointerException e) {
-            // yuma sends <attribute /> for empty value instead of <attribute></attribute>
-            logger.warn("Ignoring exception caused by failure to read text element", e);
-        }
-
-        if (null == textContent){
-            throw new NetconfDocumentedException(String.format("This element should contain text %s", xmlElement),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.invalid_value,
-                    NetconfDocumentedException.ErrorSeverity.error);
-        }
+        String textContent = readElementContent(xmlElement);
         return AttributeConfigElement.create(postprocessNullableDefault(getNullableDefault()),
                 postprocessParsedValue(textContent));
     }
index 66b945d14b8eca0dce2157bedba23bed403f0fa6..68c8c6fce39eed748dcd9f9725c1c0c16c85c133 100644 (file)
@@ -40,8 +40,9 @@ public class ObjectNameAttributeWritingStrategy implements AttributeWritingStrat
         String refName = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getRefName();
         String namespaceForType = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getNamespace();
 
-        Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(XmlNetconfConstants.PREFIX, XmlNetconfConstants.TYPE_KEY), XmlNetconfConstants.PREFIX,
-                moduleName, Optional.<String>of(namespaceForType));
+        Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document,  XmlNetconfConstants.TYPE_KEY, XmlNetconfConstants.PREFIX,
+                namespaceForType, moduleName);
+
         innerNode.appendChild(typeElement);
 
         final Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, refName, Optional.<String>absent());
index ed3bb2a9d97b5db100aa73fa1c37588bca76d6ce..a2b8e0bfdf6b97a5cc4cdf1e361084e6be0d1078 100644 (file)
@@ -43,9 +43,8 @@ public class SimpleIdentityRefAttributeWritingStrategy extends SimpleAttributeWr
     @Override
     protected Element createElement(Document doc, String key, String value, Optional<String> namespace) {
         QName qName = QName.create(value);
-        String identity = qName.getLocalName();
+        String identityValue = qName.getLocalName();
         String identityNamespace = qName.getNamespace().toString();
-        Element element = XmlUtil.createPrefixedTextElement(doc, XmlUtil.createPrefixedValue(PREFIX, key), PREFIX, identity, Optional.<String>of(identityNamespace));
-        return element;
+        return XmlUtil.createTextElementWithNamespacedContent(doc, key, PREFIX, identityNamespace, identityValue);
     }
 }
index a5a625a2d6859a373511a1c22ffc9b98c9df6521..6a17e97350b3245735385fb9dd68b0497b8e8fb0 100644 (file)
@@ -60,19 +60,17 @@ public class ModuleConfig {
 
     public Element toXml(ObjectName instanceON, ServiceRegistryWrapper depTracker, Document document, String namespace) {
         Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.<String>absent());
-        // Xml.addNamespaceAttr(document, root, namespace);
 
-        final String prefix = getPrefix();
-        Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.TYPE_KEY), prefix,
-                moduleName, Optional.<String>of(namespace));
-        // Xml.addNamespaceAttr(document, typeElement,
-        // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+        // type belongs to config.yang namespace, but needs to be <type prefix:moduleNS>prefix:moduleName</type>
+
+        Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document, XmlNetconfConstants.TYPE_KEY,
+                XmlNetconfConstants.PREFIX, namespace, moduleName);
+
         root.appendChild(typeElement);
+        // name belongs to config.yang namespace
+        String instanceName = ObjectNameUtil.getInstanceName(instanceON);
+        Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, instanceName, Optional.<String>absent());
 
-        Element nameElement = XmlUtil.createTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.NAME_KEY),
-                ObjectNameUtil.getInstanceName(instanceON), Optional.<String>of(namespace));
-        // Xml.addNamespaceAttr(document, nameElement,
-        // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
         root.appendChild(nameElement);
 
         root = instanceConfig.toXml(instanceON, depTracker, namespace, document, root);
@@ -80,10 +78,6 @@ public class ModuleConfig {
         return root;
     }
 
-    private String getPrefix() {
-        return XmlNetconfConstants.PREFIX;
-    }
-
     public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName,
                                          String moduleNamespace, EditStrategyType defaultStrategy, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
 
index eb5c018cf3db0af76ced902576543861b732a4f6..559de7a756f51db69d5047c5c1bd0ac6918832ea 100644 (file)
@@ -131,11 +131,15 @@ public final class Services {
         for (String namespace : mappedServices.keySet()) {
 
             for (Entry<String, Map<String, String>> serviceEntry : mappedServices.get(namespace).entrySet()) {
+                // service belongs to config.yang namespace
                 Element serviceElement = XmlUtil.createElement(document, SERVICE_KEY, Optional.<String>absent());
                 root.appendChild(serviceElement);
 
-                Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(XmlNetconfConstants.PREFIX, TYPE_KEY), XmlNetconfConstants.PREFIX,
-                        serviceEntry.getKey(), Optional.of(namespace));
+                // type belongs to config.yang namespace
+                String serviceType = serviceEntry.getKey();
+                Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document, XmlNetconfConstants.TYPE_KEY,
+                        XmlNetconfConstants.PREFIX, namespace, serviceType);
+
                 serviceElement.appendChild(typeElement);
 
                 for (Entry<String, String> instanceEntry : serviceEntry.getValue().entrySet()) {
index 2e8d1f64ab62cded6bde037c0d082e4604c8785a..f8d21e401cbf7179ba45f11a99c8ab06d718ecc3 100644 (file)
@@ -8,11 +8,42 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector;
 
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
+import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
 import org.custommonkey.xmlunit.AbstractNodeTester;
 import org.custommonkey.xmlunit.NodeTest;
 import org.custommonkey.xmlunit.NodeTestException;
@@ -83,38 +114,6 @@ import org.w3c.dom.Text;
 import org.w3c.dom.traversal.DocumentTraversal;
 import org.xml.sax.SAXException;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
-import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
-
 
 public class NetconfMappingTest extends AbstractConfigTest {
     private static final Logger logger = LoggerFactory.getLogger(NetconfMappingTest.class);
@@ -573,7 +572,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
         String enumContent = "TWO";
 
         for (XmlElement moduleElement : modulesElement.getChildElements("module")) {
-            String name = moduleElement.getOnlyChildElement("prefix:name").getTextContent();
+            String name = moduleElement.getOnlyChildElement("name").getTextContent();
             if(name.equals(INSTANCE_NAME)) {
                 XmlElement enumAttr = moduleElement.getOnlyChildElement(enumName);
                 assertEquals(enumContent, enumAttr.getTextContent());
@@ -599,7 +598,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         for (XmlElement moduleElement : modulesElement.getChildElements("module")) {
             for (XmlElement type : moduleElement.getChildElements("type")) {
-                if (type.getNamespace() != null) {
+                if (type.getNamespaceOptionally().isPresent()) {
                     configAttributeType.add(type.getTextContent());
                 }
             }
index cd53995bce8a54c2bf12e2419ceab87300204edb..fd43f67c056407c15dc0692d938b4fad7c30586b 100644 (file)
@@ -386,10 +386,10 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
             NetconfMessage response = netconfClient.sendMessage(getConfig);
 
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:afi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:afi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:safi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:safi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</afi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</afi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</safi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</safi>"));
 
         } catch (Exception e) {
             fail(Throwables.getStackTraceAsString(e));
index 66603fb6c2d60b90cf2e17c277e65420d3c0b8b1..ac200a0aa668c1a406e044e11205ac90c20fc478 100644 (file)
@@ -10,9 +10,17 @@ package org.opendaylight.controller.netconf.util.xml;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
@@ -28,14 +36,6 @@ import org.w3c.dom.NodeList;
 import org.w3c.dom.Text;
 import org.xml.sax.SAXException;
 
-import javax.annotation.Nullable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 public final class XmlElement {
 
     private final Element element;
@@ -111,7 +111,7 @@ public final class XmlElement {
     public void checkNamespaceAttribute(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
         if (!getNamespaceAttribute().equals(expectedNamespace))
         {
-            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s",
                     getNamespaceAttribute(),
                     expectedNamespace),
                     NetconfDocumentedException.ErrorType.application,
@@ -123,7 +123,7 @@ public final class XmlElement {
     public void checkNamespace(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
         if (!getNamespace().equals(expectedNamespace))
        {
-            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s",
                     getNamespace(),
                     expectedNamespace),
                     NetconfDocumentedException.ErrorType.application,
@@ -320,23 +320,22 @@ public final class XmlElement {
     }
 
     public String getTextContent() throws NetconfDocumentedException {
-        Node textChild = element.getFirstChild();
-        if (null == textChild){
-            throw new NetconfDocumentedException(String.format( "Child node expected, got null for " + getName() + " : " + element),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.invalid_value,
-                    NetconfDocumentedException.ErrorSeverity.error);
+        NodeList childNodes = element.getChildNodes();
+        if (childNodes.getLength() == 0) {
+            return "";
         }
-        if (!(textChild instanceof Text)){
-            throw new NetconfDocumentedException(String.format(getName() + " should contain text." +
-                    Text.class.getName() + " expected, got " + textChild),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.invalid_value,
-                    NetconfDocumentedException.ErrorSeverity.error);
+        for(int i = 0; i < childNodes.getLength(); i++) {
+            Node textChild = childNodes.item(i);
+            if (textChild instanceof Text) {
+                String content = textChild.getTextContent();
+                return content.trim();
+            }
         }
-        String content = textChild.getTextContent();
-        // Trim needed
-        return content.trim();
+        throw new NetconfDocumentedException(getName() + " should contain text.",
+                NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.invalid_value,
+                NetconfDocumentedException.ErrorSeverity.error
+        );
     }
 
     public String getNamespaceAttribute() throws MissingNameSpaceException {
@@ -351,15 +350,24 @@ public final class XmlElement {
         return attribute;
     }
 
-    public String getNamespace() throws MissingNameSpaceException {
+    public Optional<String> getNamespaceOptionally() {
         String namespaceURI = element.getNamespaceURI();
-        if (namespaceURI  == null || namespaceURI.equals("")){
+        if (Strings.isNullOrEmpty(namespaceURI)) {
+            return Optional.absent();
+        } else {
+            return Optional.of(namespaceURI);
+        }
+    }
+
+    public String getNamespace() throws MissingNameSpaceException {
+        Optional<String> namespaceURI = getNamespaceOptionally();
+        if (namespaceURI.isPresent() == false){
             throw new MissingNameSpaceException(String.format("No namespace defined for %s", this),
                     NetconfDocumentedException.ErrorType.application,
                     NetconfDocumentedException.ErrorTag.operation_failed,
                     NetconfDocumentedException.ErrorSeverity.error);
         }
-        return namespaceURI;
+        return namespaceURI.get();
     }
 
     @Override
index 1f81117ca383922ff246c9e10af36b708f84b26a..b2b202b69ef024569d032771ecd35e116812769e 100644 (file)
@@ -10,11 +10,12 @@ package org.opendaylight.controller.netconf.util.xml;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
-
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilder;
@@ -32,17 +33,15 @@ import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
 
 public final class XmlUtil {
 
     public static final String XMLNS_ATTRIBUTE_KEY = "xmlns";
-    private static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+    public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
     private static final DocumentBuilderFactory BUILDERFACTORY;
 
     static {
@@ -118,8 +117,14 @@ public final class XmlUtil {
         return typeElement;
     }
 
-    public static Element createPrefixedTextElement(Document document, String qName, String prefix, String content, Optional<String> namespace) {
-        return createTextElement(document, qName, createPrefixedValue(prefix, content), namespace);
+    public static Element createTextElementWithNamespacedContent(Document document, String qName, String prefix,
+                                                                 String namespace, String contentWithoutPrefix) {
+
+        String content = createPrefixedValue(XmlNetconfConstants.PREFIX, contentWithoutPrefix);
+        Element element = createTextElement(document, qName, content, Optional.<String>absent());
+        String prefixedNamespaceAttr = createPrefixedValue(XMLNS_ATTRIBUTE_KEY, prefix);
+        element.setAttributeNS(XMLNS_URI, prefixedNamespaceAttr, namespace);
+        return element;
     }
 
     public static String createPrefixedValue(String prefix, String value) {