Merge "Store yang store snapshot cache using soft reference."
authorEd Warnicke <eaw@cisco.com>
Mon, 19 May 2014 12:28:20 +0000 (12:28 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 19 May 2014 12:28:20 +0000 (12:28 +0000)
119 files changed:
features/base/pom.xml [new file with mode: 0644]
features/base/src/main/resources/features.xml [new file with mode: 0644]
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/DependencyResolver.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/JmxAttribute.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModule.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/03-toaster-sample.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/99-netconf-connector.xml [moved from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml with 100% similarity]
opendaylight/md-sal/clustered-data-store/implementation/pom.xml [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/cluster/store/ClusteredDataStoreImplModule.java [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/cluster/store/ClusteredDataStoreImplModuleFactory.java [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/ClusteredDataStore.java [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManager.java [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/main/yang/odl-sal-dom-clustered-store-cfg.yang [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java [deleted file]
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java [deleted file]
opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml [deleted file]
opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java [deleted file]
opendaylight/md-sal/clustered-data-store/integrationtest/src/test/resources/controller.xml [deleted file]
opendaylight/md-sal/clustered-data-store/integrationtest/src/test/resources/logback.xml [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareConsumer.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.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/sal/binding/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-spi/pom.xml [deleted file]
opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/DataDomToJavaTransformer.java [deleted file]
opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/JavaToDataDomTransformer.java [deleted file]
opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/Mapper.java [deleted file]
opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/MappingProvider.java [deleted file]
opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcMapper.java [deleted file]
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizationOperation.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataSchemaContainerProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Arguments.java
opendaylight/md-sal/sal-data-api/pom.xml [deleted file]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Consumer.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/Provider.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataTree.java [new file with mode: 0644]
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/ModificationApplyOperation.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/OperationWithModification.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/SchemaAwareApplyOperation.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationMetadataTreeTest.java
opendaylight/md-sal/sal-dom-demo/pom.xml [deleted file]
opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoConsumerImpl.java [deleted file]
opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoProviderImpl.java [deleted file]
opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoUtils.java [deleted file]
opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/SALDemo.java [deleted file]
opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/package-info.java [deleted file]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ResponseException.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend [deleted file]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetOperationTest.java
opendaylight/md-sal/samples/l2switch/implementation/src/main/java/org/opendaylight/controller/sample/l2switch/md/inventory/InventoryService.java
opendaylight/md-sal/samples/l2switch/implementation/src/main/java/org/opendaylight/controller/sample/l2switch/md/packet/PacketHandler.java
opendaylight/md-sal/samples/toaster-consumer/pom.xml
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModuleFactory.java [moved from opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/toaster_consumer/impl/ToasterConsumerModuleFactory.java with 56% similarity]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/toaster_consumer/impl/ToasterConsumerModule.java [deleted file]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/api/EggsType.java [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/api/KitchenService.java [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/toaster/provider/api/ToastConsumer.java [deleted file]
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/toaster/provider/impl/ToastConsumerImpl.java [deleted file]
opendaylight/md-sal/samples/toaster-consumer/src/main/yang/kitchen-service-impl.yang [moved from opendaylight/md-sal/samples/toaster-consumer/src/main/yang/toaster-consumer-impl.yang with 55% similarity]
opendaylight/md-sal/samples/toaster-consumer/src/main/yang/toaster-consumer.yang [deleted file]
opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java
opendaylight/md-sal/samples/toaster-it/src/test/resources/controller.xml
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/sample/toaster/provider/OpendaylightToaster.java
opendaylight/md-sal/samples/toaster-provider/src/main/yang/toaster-provider-impl.yang
opendaylight/md-sal/samples/toaster-provider/src/main/yang/toaster-provider.yang [deleted file]
opendaylight/md-sal/samples/toaster/src/main/yang/toaster.yang
opendaylight/md-sal/test/sal-rest-connector-it/pom.xml [deleted file]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java [deleted file]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/exam.properties [deleted file]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/logback.xml [deleted file]
opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/tomcat-server.xml [deleted file]
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java [deleted file]
opendaylight/netconf/netconf-it/src/test/resources/RSA.pk [deleted file]
opendaylight/netconf/netconf-it/src/test/resources/controller.xml [deleted file]
opendaylight/netconf/netconf-it/src/test/resources/keystore.jks [deleted file]
opendaylight/netconf/netconf-it/src/test/resources/netconfMessages/commit.xml [deleted file]
opendaylight/netconf/netconf-it/src/test/resources/netconfMessages/getConfig.xml [deleted file]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPageLink.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java
opendaylight/sal/connection/implementation/src/main/java/org/opendaylight/controller/sal/connection/implementation/internal/ConnectionService.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
pom.xml

diff --git a/features/base/pom.xml b/features/base/pom.xml
new file mode 100644 (file)
index 0000000..d12432c
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../../opendaylight/commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>base-features</artifactId>
+  <packaging>kar</packaging>
+  <name>${project.artifactId}</name>
+  <description>Base Features POM</description>
+  <properties>
+    <features.file>features.xml</features.file>
+  </properties>
+  <build>
+    <resources>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.karaf.tooling</groupId>
+        <artifactId>karaf-maven-plugin</artifactId>
+        <version>${karaf.version}</version>
+        <extensions>true</extensions>
+        <executions>
+          <execution>
+            <id>features-create-kar</id>
+            <goals>
+              <goal>features-create-kar</goal>
+            </goals>
+            <configuration>
+              <featuresFile>${project.build.directory}/classes/${features.file}</featuresFile>
+            </configuration>
+          </execution>
+        </executions>
+        <!-- There is no useful configuration for the kar mojo. The features-generate-descriptor mojo configuration may be useful -->
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>filter</id>
+            <goals>
+              <goal>resources</goal>
+            </goals>
+            <phase>generate-resources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/${features.file}</file>
+                  <type>xml</type>
+                  <classifier>features</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/features/base/src/main/resources/features.xml b/features/base/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..cc11205
--- /dev/null
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<features name="base-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+
+   <feature name="base-all" description="OpenDaylight Controller"
+      version="${project.version}">
+      <feature>http</feature>
+      <feature>transaction</feature>
+      <feature>base-felix-dm</feature>
+      <feature>base-aries-spi-fly</feature>
+      <feature>base-dummy-console</feature>
+      <feature>base-apache-commons</feature>
+      <feature>base-eclipselink-persistence</feature>
+      <feature>base-gemini-web</feature>
+      <feature>base-tomcat</feature>
+      <feature>base-netty</feature>
+      <feature>base-jersey</feature>
+      <feature>base-spring-security</feature>
+   </feature>
+   <feature name="base-dummy-console" description="Temporary Dummy Console" version="1.1.0-SNAPSHOT">
+      <bundle>mvn:org.opendaylight.controller/dummy-console/1.1.0-SNAPSHOT</bundle>
+   </feature>
+   <feature name="base-felix-dm" description="Felix Dependency Manager"
+      version="${felix.dependencymanager.version}">
+      <bundle start-level="35">mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle>
+      <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager/${felix.dependencymanager.version}</bundle>
+      <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager.shell/${felix.dependencymanager.shell.version}</bundle>
+   </feature>
+   <feature name="base-aries-spi-fly" description="Aries SPI Fly"
+      version="${spifly.version}">
+      <bundle start-level="35">mvn:org.apache.aries/org.apache.aries.util/1.1.0</bundle>
+      <bundle start-level="35">mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/${spifly.version}</bundle>
+      <bundle start-level="35">mvn:org.ow2.asm/asm-all/4.0</bundle>
+   </feature>
+     <feature name='base-netty' version='${netty.version}'>
+        <bundle>wrap:mvn:io.netty/netty-buffer/${netty.version}</bundle>
+        <bundle>wrap:mvn:io.netty/netty-codec/${netty.version}</bundle>
+        <bundle>wrap:mvn:io.netty/netty-transport/${netty.version}</bundle>
+        <bundle>wrap:mvn:io.netty/netty-common/${netty.version}</bundle>
+        <bundle>wrap:mvn:io.netty/netty-handler/${netty.version}</bundle>
+        <bundle>wrap:mvn:io.netty/netty-codec-http/${netty.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/1.1-SNAPSHOT</bundle>
+    </feature>
+    <feature name="base-jersey" description="Jersey" version="${jersey.version}">
+        <feature>base-gemini-web</feature>
+        <bundle>mvn:org.opendaylight.controller.thirdparty/com.sun.jersey.jersey-servlet/${jersey.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-client/${jersey.version}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.version}</bundle>
+   </feature>
+   <feature name="base-jackson" description="Jackson JAX-RS" version="${jackson.version}">
+      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
+      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
+      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
+      <bundle start="true" start-level="35">mvn:org.codehaus.jettison/jettison/${jettison.version}</bundle>
+      <bundle start="true" start-level="35">mvn:javax.ws.rs/jsr311-api/${jsr311.api.version}</bundle>
+      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${jackson.version}</bundle>
+      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${jackson.version}</bundle>
+      <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${jackson.version}</bundle>
+   </feature>
+   <feature name="base-slf4j" description="SLF4J Logging" version="${slf4j.version}">
+      <bundle start-level="35">mvn:org.slf4j/slf4j-jdk14/1.7.2</bundle>
+      <bundle start-level="35">mvn:org.slf4j/slf4j-nop/1.7.2</bundle>
+      <bundle start-level="35">mvn:org.slf4j/slf4j-simple/1.7.2</bundle>
+      <bundle start="true" start-level="35">mvn:org.slf4j/slf4j-api/1.7.2</bundle>
+   </feature>
+   <feature name="base-apache-commons" description="Apache Commons Libraries"
+      version="${project.version}">
+      <bundle start="true" start-level="35">mvn:com.google.guava/guava/${guava.version}</bundle>
+      <bundle start="true" start-level="35">mvn:org.javassist/javassist/${javassist.version}</bundle>
+      <bundle start="true" start-level="35">mvn:commons-io/commons-io/${commons.io.version}</bundle>
+      <bundle start="true" start-level="35">mvn:commons-codec/commons-codec/${commons.codec.version}</bundle>
+      <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang.version}</bundle>
+      <bundle start="true" start-level="35">mvn:commons-net/commons-net/${commons.net.version}</bundle>
+   </feature>
+   <feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
+      <bundle start="true" start-level="35">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
+      <bundle start="true" start-level="35">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
+   </feature>
+   <feature name="base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
+      <feature>http</feature>
+      <feature>transaction</feature>
+      <feature>base-slf4j</feature>
+      <feature>base-felix-dm</feature>
+      <feature>base-jackson</feature>
+      <feature>base-apache-commons</feature>
+      <bundle start="true" start-level="35">mvn:com.google.code.gson/gson/${gson.version}</bundle>
+      <bundle start="true" start-level="35">mvn:commons-fileupload/commons-fileupload/${commons.fileupload.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.core/${geminiweb.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.extender/${geminiweb.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.common/${virgo.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.io/${virgo.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.math/${virgo.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi/${virgo.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi.manifest/${virgo.version}</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.parser.manifest/${virgo.version}</bundle>
+      <bundle start="true" start-level="35">mvn:org.apache.felix/org.apache.felix.fileinstall/3.1.6</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.activation/1.1.0.v201211130549</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.annotation/1.1.0.v201209060031</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.ejb/3.1.1.v201204261316</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.el/2.2.0.v201108011116</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.mail.glassfish/1.4.1.v201108011116</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.xml.rpc/1.1.0.v201005080400</bundle>
+      <bundle start="true" start-level="35">mvn:org.eclipse.jetty.orbit/javax.servlet.jsp/2.2.0.v201112011158</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl/1.2.0.v201105211821</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl.impl/1.2.0.v201210211230</bundle>
+   </feature>
+   <feature name="base-tomcat" description="OpenDaylight Tomcat" version="7.0.32">
+      <feature>base-gemini-web</feature>
+      <feature>base-eclipselink-persistence</feature>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina/7.0.32.v201211201336</bundle>
+      <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.tomcat/${geminiweb.version}</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.ha/7.0.32.v201211201952</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.tribes/7.0.32.v201211201952</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.coyote/7.0.32.v201211201952</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.el/7.0.32.v201211081135</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.jasper/7.0.32.v201211201952</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.juli.extras/7.0.32.v201211081135</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.api/7.0.32.v201211081135</bundle>
+      <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.util/7.0.32.v201211201952</bundle>
+      <bundle start="true" start-level="35">wrap:mvn:virgomirror/org.eclipse.jdt.core.compiler.batch/3.8.0.I20120518-2145</bundle>
+   </feature>
+   <feature name="base-spring" description="Opendaylight Spring Support" version="${spring.version}">
+      <bundle>mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
+      <bundle>mvn:org.aopalliance/com.springsource.org.aopalliance/${aopalliance.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.aop/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.asm/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.beans/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.context/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.context.support/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.core/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.expression/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.transaction/${spring.version}</bundle>
+   </feature>
+   <feature name="base-spring-web" description="OpenDaylight Spring Web" version="${spring.version}">
+      <feature>base-spring</feature>
+      <feature>base-gemini-web</feature>
+      <bundle>mvn:org.springframework/org.springframework.web/${spring.version}</bundle>
+      <bundle>mvn:org.springframework/org.springframework.web.servlet/${spring.version}</bundle>
+   </feature>
+   <feature name="base-spring-security" description="OpenDaylight Spring Security" version="${spring-security.version}">
+      <feature>base-spring-web</feature>
+      <bundle>mvn:org.springframework.security/spring-security-config/${spring-security.version}</bundle>
+      <bundle>mvn:org.springframework.security/spring-security-core/${spring-security.version}</bundle>
+      <bundle>mvn:org.springframework.security/spring-security-taglibs/${spring-security.version}</bundle>
+      <bundle>mvn:org.springframework.security/spring-security-web/${spring-security.version}</bundle>
+   </feature>
+</features>
index aaab66d4b09ce655257de424b8510657dda93b1b..1020ba998c1e17a09026746e85370e84c21b0711 100644 (file)
@@ -19,6 +19,7 @@
     <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>
     <asm.version>4.1</asm.version>
     <!-- Plugin Versions -->
     <bouncycastle.version>1.50</bouncycastle.version>
index b020000d3d742b93ec71ea602c30e902e759fb27..40ff7e17030bc254026574cd34a7a1ca48970819 100644 (file)
@@ -7,12 +7,15 @@
  */
 package org.opendaylight.controller.config.api;
 
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 
-import javax.management.ObjectName;
-
 /**
  * Each new {@link org.opendaylight.controller.config.spi.Module} can receive
  * resolver from {@link org.opendaylight.controller.config.spi.ModuleFactory}
@@ -26,15 +29,13 @@ public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
      * To be used during validation phase to validate serice interface of
      * dependent module.
      *
-     * @param expectedServiceInterface
-     *            MBean/MXBean interface which will back the proxy object.
-     * @param objectName
-     *            ObjectName of dependent module without transaction name
-     *            (platformON).
-     * @param jmxAttribute
-     * @throws {@link IllegalArgumentException} when module is not found
-     * @throws {@link IllegalStateException} if module does not export this
-     *         service interface.
+     * @param expectedServiceInterface MBean/MXBean interface which will back the proxy object.
+     * @param objectName               ObjectName of dependent module without transaction name
+     *                                 (platformON).
+     * @param jmxAttribute             for reporting
+     * @throws IllegalArgumentException when module is not found
+     * @throws IllegalStateException    if module does not export this
+     *                                  service interface.
      */
     void validateDependency(
             Class<? extends AbstractServiceInterface> expectedServiceInterface,
@@ -44,13 +45,11 @@ public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
      * To be used during commit phase to wire actual dependencies.
      *
      * @return dependency instance using
-     *         {@link org.opendaylight.controller.config.spi.Module#getInstance()}
-     * @throws {@link IllegalArgumentException} when module is not found
+     * {@link org.opendaylight.controller.config.spi.Module#getInstance()}
+     * @throws IllegalArgumentException when module is not found
      */
     <T> T resolveInstance(Class<T> expectedType, ObjectName objectName,
-            JmxAttribute jmxAttribute);
-
-    // TODO finish javadoc
+                          JmxAttribute jmxAttribute);
 
     /**
      * To be used during commit phase to resolve identity-ref config attributes.
@@ -59,6 +58,32 @@ public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
      */
     <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass);
 
+
+    /**
+     * Validate identity-ref config attribute.
+     */
     <T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute);
 
+    /**
+     * Can be used during validation or commit phase to get attribute value of dependent module.
+     *
+     * @param name      either direct ObjectName of a Module (type=Module) or service reference (type=ServiceReference) of dependent Module
+     * @param attribute String identifying attribute name in JMX. Note that attributes start with upper case. See {@link org.opendaylight.controller.config.api.JmxAttribute#getAttributeName()}
+     */
+    Object getAttribute(ObjectName name, String attribute)
+            throws MBeanException, AttributeNotFoundException,
+            InstanceNotFoundException, ReflectionException;
+
+
+    /**
+     * Helper method around {@link javax.management.JMX#newMXBeanProxy(javax.management.MBeanServerConnection, javax.management.ObjectName, Class)} }.
+     * Returns MXBean proxy for dependent module. Can be used during validation or commit phase to inspect dependent module's attributes.
+     *
+     * @param objectName either direct ObjectName of a Module (type=Module) or service reference (type=ServiceReference) of dependent Module
+     * @param interfaceClass MXBean interface to be used as a proxy
+     * @param <T> type of proxy for type safe return value
+     * @return instance of MXBean proxy
+     */
+    <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass);
+
 }
index 244f22f58efdd5b1615806a2859fd50902b79172..649b1eb4676e6ab7dfc2ef81f8b13d2b74753e15 100644 (file)
@@ -21,6 +21,9 @@ public class JmxAttribute {
         this.attributeName = attributeName;
     }
 
+    /**
+     * Name of attribute in JMX.
+     */
     public String getAttributeName() {
         return attributeName;
     }
index 3e231201821619d36c95b0cc481938b5eda042f4..39eef8741ba840309b8293e19f14af437652e82e 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.manager.impl;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static java.lang.String.format;
 
 import java.util.ArrayList;
@@ -43,8 +44,6 @@ import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
-import static com.google.common.base.Preconditions.checkNotNull;
 /**
  * This is a JMX bean representing current transaction. It contains
  * transaction identifier, unique version and parent version for
@@ -96,7 +95,7 @@ class ConfigTransactionControllerImpl implements
         this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
         this.transactionStatus = new TransactionStatus();
         this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
-                transactionStatus, writableSRRegistry, codecRegistry);
+                transactionStatus, writableSRRegistry, codecRegistry, transactionsMBeanServer);
         this.transactionsMBeanServer = transactionsMBeanServer;
         this.configMBeanServer = configMBeanServer;
         this.blankTransaction = blankTransaction;
index c229450c30138584e615e552843c1b0f10581dca..4f60a673f5f711ce17815061318f2641bbda0091 100644 (file)
@@ -7,6 +7,19 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
+import static java.lang.String.format;
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.IdentityAttributeRef;
 import org.opendaylight.controller.config.api.JmxAttribute;
@@ -25,14 +38,6 @@ import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.ObjectName;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import static java.lang.String.format;
-
 /**
  * Protect {@link org.opendaylight.controller.config.spi.Module#getInstance()}
  * by creating proxy that would throw exception if those methods are called
@@ -49,15 +54,20 @@ final class DependencyResolverImpl implements DependencyResolver,
     private final Set<ModuleIdentifier> dependencies = new HashSet<>();
     private final ServiceReferenceReadableRegistry readableRegistry;
     private final CodecRegistry codecRegistry;
+    private final String transactionName;
+    private final MBeanServer mBeanServer;
 
     DependencyResolverImpl(ModuleIdentifier currentModule,
                            TransactionStatus transactionStatus, ModulesHolder modulesHolder,
-                           ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
+                           ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry,
+                           String transactionName, MBeanServer mBeanServer) {
         this.codecRegistry = codecRegistry;
         this.name = currentModule;
         this.transactionStatus = transactionStatus;
         this.modulesHolder = modulesHolder;
         this.readableRegistry = readableRegistry;
+        this.transactionName = transactionName;
+        this.mBeanServer = mBeanServer;
     }
 
     /**
@@ -80,7 +90,8 @@ final class DependencyResolverImpl implements DependencyResolver,
 
         JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
                 "is null, expected dependency implementing "
-                        + expectedServiceInterface, jmxAttribute);
+                        + expectedServiceInterface, jmxAttribute
+        );
 
 
         // check that objectName belongs to this transaction - this should be
@@ -91,8 +102,10 @@ final class DependencyResolverImpl implements DependencyResolver,
         JmxAttributeValidationException.checkCondition(
                 hasTransaction == false,
                 format("ObjectName should not contain "
-                        + "transaction name. %s set to %s. ", jmxAttribute,
-                        dependentReadOnlyON), jmxAttribute);
+                                + "transaction name. %s set to %s. ", jmxAttribute,
+                        dependentReadOnlyON
+                ), jmxAttribute
+        );
 
         dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
 
@@ -110,7 +123,8 @@ final class DependencyResolverImpl implements DependencyResolver,
                             + "attribute %s",
                     foundFactory.getImplementationName(), foundFactory,
                     expectedServiceInterface, dependentReadOnlyON,
-                    jmxAttribute);
+                    jmxAttribute
+            );
             throw new JmxAttributeValidationException(message, jmxAttribute);
         }
         synchronized (this) {
@@ -157,7 +171,8 @@ final class DependencyResolverImpl implements DependencyResolver,
             String message = format(
                     "Error while %s resolving instance %s. getInstance() returned null. "
                             + "Expected type %s , attribute %s", name,
-                    dependentModuleIdentifier, expectedType, jmxAttribute);
+                    dependentModuleIdentifier, expectedType, jmxAttribute
+            );
             throw new JmxAttributeValidationException(message, jmxAttribute);
         }
         try {
@@ -166,7 +181,8 @@ final class DependencyResolverImpl implements DependencyResolver,
             String message = format(
                     "Instance cannot be cast to expected type. Instance class is %s , "
                             + "expected type %s , attribute %s",
-                    instance.getClass(), expectedType, jmxAttribute);
+                    instance.getClass(), expectedType, jmxAttribute
+            );
             throw new JmxAttributeValidationException(message, e, jmxAttribute);
         }
     }
@@ -258,4 +274,20 @@ final class DependencyResolverImpl implements DependencyResolver,
         return name;
     }
 
+    @Override
+    public Object getAttribute(ObjectName name, String attribute)
+            throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException {
+        name = translateServiceRefIfPossible(name);
+        // add transaction name
+        name = ObjectNameUtil.withTransactionName(name, transactionName);
+        return mBeanServer.getAttribute(name, attribute);
+    }
+
+    @Override
+    public <T> T newMXBeanProxy(ObjectName name, Class<T> interfaceClass) {
+        name = translateServiceRefIfPossible(name);
+        // add transaction name
+        name = ObjectNameUtil.withTransactionName(name, transactionName);
+        return JMX.newMXBeanProxy(mBeanServer, name, interfaceClass);
+    }
 }
index 0c1531728fb1b58488fe6623047c0fd804528824..2a1a908e7a18875c1baed6997fe9a6e5f6848519 100644 (file)
@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.Map;
 import javax.annotation.concurrent.GuardedBy;
 import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanServer;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.JmxAttribute;
@@ -45,19 +46,25 @@ import org.osgi.framework.BundleContext;
 public class DependencyResolverManager implements DependencyResolverFactory, AutoCloseable {
     @GuardedBy("this")
     private final Map<ModuleIdentifier, DependencyResolverImpl> moduleIdentifiersToDependencyResolverMap = new HashMap<>();
+    private final TransactionIdentifier transactionIdentifier;
     private final ModulesHolder modulesHolder;
     private final TransactionStatus transactionStatus;
     private final ServiceReferenceReadableRegistry readableRegistry;
     private final CodecRegistry codecRegistry;
     private final DeadlockMonitor deadlockMonitor;
+    private final MBeanServer mBeanServer;
 
     public DependencyResolverManager(TransactionIdentifier transactionIdentifier,
-                                     TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
+                                     TransactionStatus transactionStatus,
+                                     ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry,
+                                     MBeanServer mBeanServer) {
+        this.transactionIdentifier = transactionIdentifier;
         this.modulesHolder = new ModulesHolder(transactionIdentifier);
         this.transactionStatus = transactionStatus;
         this.readableRegistry = readableRegistry;
         this.codecRegistry = codecRegistry;
         this.deadlockMonitor = new DeadlockMonitor(transactionIdentifier);
+        this.mBeanServer = mBeanServer;
     }
 
     @Override
@@ -69,7 +76,8 @@ public class DependencyResolverManager implements DependencyResolverFactory, Aut
         DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name);
         if (dependencyResolver == null) {
             transactionStatus.checkNotCommitted();
-            dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry, codecRegistry);
+            dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry,
+                    codecRegistry, transactionIdentifier.getName(), mBeanServer);
             moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
         }
         return dependencyResolver;
index d5d3823ef0e84f5e0d9e0d678d38b2094544a92b..48d7de0e82f200f0dae9a4480d5b317b8e0fe47b 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
 import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo;
 import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
@@ -29,7 +30,7 @@ import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
 
-public class DependencyResolverManagerTest {
+public class DependencyResolverManagerTest extends AbstractLockedPlatformMBeanServerTest {
 
     final ModuleIdentifier apspName = new ModuleIdentifier("apsp", "apsp"); // depends
                                                                             // on:
@@ -45,7 +46,8 @@ public class DependencyResolverManagerTest {
     public void setUp() {
         transactionStatus = mock(TransactionStatus.class);
         ServiceReferenceReadableRegistry mockedRegistry = mock(ServiceReferenceReadableRegistry.class);
-        tested = new DependencyResolverManager(new TransactionIdentifier("txName"), transactionStatus, mockedRegistry, null);
+        tested = new DependencyResolverManager(new TransactionIdentifier("txName"), transactionStatus, mockedRegistry,
+                null, platformMBeanServer);
         doNothing().when(transactionStatus).checkCommitStarted();
         doNothing().when(transactionStatus).checkNotCommitted();
     }
index df6dce124339991a50c0016d30dd87cc76168e88..5c320ae2c159b6bdd132ad6fd1e5a15d4db33bd3 100644 (file)
@@ -7,25 +7,25 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.parallelapsp;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
 import com.google.common.base.Strings;
+import java.io.Closeable;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.annotations.RequireInterface;
 import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolConfigMXBean;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc;
 import org.opendaylight.controller.config.spi.Module;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.management.ObjectName;
-import java.io.Closeable;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
 /**
  * Represents service that has dependency to thread pool.
  */
@@ -102,6 +102,17 @@ public class TestingParallelAPSPModule implements Module,
             checkState("Commit was not triggered".equals(e.getMessage()),
                     e.getMessage());
         }
+
+        // test retrieving dependent module's attribute
+        int threadCount;
+        try {
+            threadCount = (Integer)dependencyResolver.getAttribute(threadPoolON, "ThreadCount");
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+        checkState(threadCount > 0);
+        TestingThreadPoolConfigMXBean proxy = dependencyResolver.newMXBeanProxy(threadPoolON, TestingThreadPoolConfigMXBean.class);
+        checkState(threadCount == proxy.getThreadCount());
     }
 
     @Override
index f42b9559c4bb7e5a562aead7b7a60c0bc692602f..c9810d052149ead1b358d14b42bda64d33c707c9 100644 (file)
@@ -7,6 +7,14 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
 
+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.junit.internal.matchers.StringContains.containsString;
+
+import java.util.Map;
+import javax.management.ObjectName;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -17,20 +25,12 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod
 import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPConfigMXBean;
 import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPImpl;
 import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolConfigMXBean;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 
-import javax.management.ObjectName;
-import java.util.Map;
-
-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.junit.internal.matchers.StringContains.containsString;
-
 public class DependentWiringTest extends AbstractParallelAPSPTest {
     private final String fixed1 = "fixed1";
     private final String apsp1 = "apsp-parallel";
@@ -132,4 +132,17 @@ public class DependentWiringTest extends AbstractParallelAPSPTest {
                 parallelAPSPRuntimeProxy.getMaxNumberOfThreads());
 
     }
+
+    @Test
+    public void testUsingServiceReferences() throws Exception {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        ObjectName threadPoolON = createFixed1(transaction, 10);
+                transaction.lookupConfigBean(getThreadPoolImplementationName(), fixed1);
+        String refName = "ref";
+        ObjectName serviceReferenceON = transaction.saveServiceReference(TestingThreadPoolServiceInterface.QNAME, refName,
+                threadPoolON);
+        createParallelAPSP(transaction, serviceReferenceON);
+        transaction.commit();
+
+    }
 }
index 1414fac2f33999f02ed9f5c7877530b51d47d7ac..377785ac41a21b4013587303cd64c68211baf1ea 100644 (file)
@@ -33,7 +33,6 @@
     <!-- 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 -->
-    <!-- dependencies commented out till we can get them in
     <dependency>
       <groupId>org.apache.karaf.features</groupId>
       <artifactId>standard</artifactId>
       <scope>runtime</scope>
     </dependency>
     <dependency>
+      <!-- scope is compile so all features (there is only one) are installed
+            into startup.properties and the feature repo itself is not installed -->
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>base-features</artifactId>
+      <version>${project.version}</version>
+      <type>kar</type>
+      <scope>runtime</scope>
+    </dependency>
+    <!--<dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>base-features</artifactId>
+      <version>${project.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>-->
+    <!-- <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>controller-features</artifactId>
       <version>${project.version}</version>
index 234e0feb45047ed2ca14e45e2b2e1dd18432834e..c958039b5f0465206626eb009e33385df5b11d2f 100644 (file)
@@ -143,3 +143,9 @@ java.util.logging.config.file=configuration/tomcat-logging.properties
 
 #Hosttracker hostsdb key scheme setting
 hosttracker.keyscheme=IP
+
+# LISP Flow Mapping configuration
+# Map-Register messages overwrite existing RLOC sets in EID-to-RLOC mappings
+lisp.mappingOverwrite = true
+# Enable the Solicit-Map-Request (SMR) mechanism
+lisp.smr = false
index 6d5d0eb82633964f0eeca31cb084063136412298..502bdebca26588cfc481793a0abd69731b6d708b 100644 (file)
@@ -12,8 +12,8 @@
         <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                 <module>
-                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
-                        prefix:toaster-provider-impl
+                    <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+                        toaster:toaster-provider-impl
                     </type>
                     <name>toaster-provider-impl</name>
 
                         <name>binding-rpc-broker</name>
                     </rpc-registry>
 
+                    <data-broker>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                        <name>binding-data-broker</name>
+                    </data-broker>
+                    
                     <notification-service>
                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
                             binding:binding-notification-service
                 </module>
 
                 <module>
-                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl">
-                        prefix:toaster-consumer-impl
+                    <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+                        kitchen:kitchen-service-impl
                     </type>
-                    <name>toaster-consumer-impl</name>
+                    <name>kitchen-service-impl</name>
 
                     <rpc-registry>
                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
                     </notification-service>
                 </module>
             </modules>
-
+            
             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                 <service>
-                    <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider">toaster:toaster-provider</type>
-                    <instance>
-                        <name>toaster-provider</name>
-                        <provider>/modules/module[type='toaster-provider-impl'][name='toaster-provider-impl']</provider>
-                    </instance>
-                </service>
-                <service>
-                    <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer">toaster:toaster-consumer</type>
+                    <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+                        kitchen:kitchen-service
+                    </type>
                     <instance>
-                        <name>toaster-consumer</name>
-                        <provider>/modules/module[type='toaster-consumer-impl'][name='toaster-consumer-impl']</provider>
+                        <name>kitchen-service</name>
+                        <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
                     </instance>
                 </service>
             </services>
     </configuration>
 
     <required-capabilities>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer?module=toaster-consumer&amp;revision=2014-01-31</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl?module=toaster-consumer-impl&amp;revision=2014-01-31</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider?module=toaster-provider&amp;revision=2014-01-31</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&amp;revision=2014-01-31</capability>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&amp;revision=2014-01-31</capability>
     </required-capabilities>
 
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/pom.xml b/opendaylight/md-sal/clustered-data-store/implementation/pom.xml
deleted file mode 100644 (file)
index fe0b516..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-parent</artifactId>
-        <version>1.1-SNAPSHOT</version>
-        <relativePath>../..</relativePath>
-    </parent>
-    <scm>
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
-        <tag>HEAD</tag>
-    </scm>
-
-    <artifactId>clustered-datastore-implementation</artifactId>
-    <version>0.4.1-SNAPSHOT</version>
-    <packaging>bundle</packaging>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                    </instructions>
-                    <manifestLocation>${project.basedir}/META-INF</manifestLocation>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.opendaylight.yangtools</groupId>
-                <artifactId>yang-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>generate-sources</goal>
-                        </goals>
-                        <configuration>
-                            <codeGenerators>
-                                <generator>
-                                    <codeGeneratorClass>
-                                        org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-                                    </codeGeneratorClass>
-                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
-                                    <additionalConfiguration>
-                                        <namespaceToPackage1>
-                                            urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
-                                        </namespaceToPackage1>
-                                    </additionalConfiguration>
-                                </generator>
-                                <generator>
-                                    <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
-                                    <outputBaseDir>target/site/models</outputBaseDir>
-                                </generator>
-                            </codeGenerators>
-                            <inspectDependencies>true</inspectDependencies>
-                        </configuration>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.opendaylight.controller</groupId>
-                        <artifactId>yang-jmx-generator-plugin</artifactId>
-                        <version>0.2.3-SNAPSHOT</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.opendaylight.yangtools</groupId>
-                        <artifactId>maven-sal-api-gen-plugin</artifactId>
-                        <version>${yangtools.version}</version>
-                        <type>jar</type>
-                    </dependency>
-                </dependencies>
-            </plugin>
-        </plugins>
-    </build>
-    <dependencies>
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-core-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-util</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>clustering.services</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-all</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-binding</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-data-api</artifactId>
-        </dependency>
-
-    </dependencies>
-</project>
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/cluster/store/ClusteredDataStoreImplModule.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/cluster/store/ClusteredDataStoreImplModule.java
deleted file mode 100644 (file)
index 5fc2c01..0000000
+++ /dev/null
@@ -1,55 +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
- */
-/**
-* Generated file
-
-* Generated from: yang module name: odl-sal-dom-clustered-store-cfg  yang module local name: dom-clustered-store-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Nov 27 17:09:17 CET 2013
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.controller.config.yang.md.sal.dom.cluster.store;
-
-import org.opendaylight.controller.datastore.internal.ClusteredDataStoreManager;
-import org.osgi.framework.BundleContext;
-
-/**
-*
-*/
-public final class ClusteredDataStoreImplModule extends org.opendaylight.controller.config.yang.md.sal.dom.cluster.store.AbstractClusteredDataStoreImplModule
-{
-
-    private BundleContext bundleContext;
-
-    public ClusteredDataStoreImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-        super(identifier, dependencyResolver);
-    }
-
-    public ClusteredDataStoreImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, ClusteredDataStoreImplModule oldModule, java.lang.AutoCloseable oldInstance) {
-        super(identifier, dependencyResolver, oldModule, oldInstance);
-    }
-
-    @Override
-    public void validate(){
-        super.validate();
-        // Add custom validation for module attributes here.
-    }
-
-    @Override
-    public java.lang.AutoCloseable createInstance() {
-        ClusteredDataStoreManager manager = new ClusteredDataStoreManager();
-        manager.setContext(bundleContext);
-        manager.start();
-        return manager;
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/cluster/store/ClusteredDataStoreImplModuleFactory.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/cluster/store/ClusteredDataStoreImplModuleFactory.java
deleted file mode 100644 (file)
index 40c5587..0000000
+++ /dev/null
@@ -1,47 +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
- */
-/**
-* Generated file
-
-* Generated from: yang module name: odl-sal-dom-clustered-store-cfg  yang module local name: dom-clustered-store-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Nov 27 17:09:17 CET 2013
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.controller.config.yang.md.sal.dom.cluster.store;
-
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
-import org.opendaylight.controller.config.spi.Module;
-import org.osgi.framework.BundleContext;
-
-/**
-*
-*/
-public class ClusteredDataStoreImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.dom.cluster.store.AbstractClusteredDataStoreImplModuleFactory
-{
-
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
-        ClusteredDataStoreImplModule module = 
-        (ClusteredDataStoreImplModule) super.createModule(instanceName, dependencyResolver, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-    
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver,
-            DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
-        ClusteredDataStoreImplModule module = 
-                (ClusteredDataStoreImplModule) super.createModule(instanceName, dependencyResolver, old, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
-}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/ClusteredDataStore.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/ClusteredDataStore.java
deleted file mode 100644 (file)
index 1aecb96..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-
-package org.opendaylight.controller.datastore;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.core.api.data.DataStore;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-public interface ClusteredDataStore extends DataStore {
-
-
-}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java
deleted file mode 100644 (file)
index 0809ba3..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore.internal;
-
-import com.google.common.base.Preconditions;
-
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-import org.opendaylight.controller.datastore.ClusteredDataStore;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-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.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * The ClusteredDataStoreImpl stores global data to be shared across a controller cluster. It uses Clustering Services.
- */
-public class ClusteredDataStoreImpl implements ClusteredDataStore {
-
-
-    public static final String OPERATIONAL_DATA_CACHE = "clustered_data_store.operational_data_cache";
-    public static final String CONFIGURATION_DATA_CACHE = "clustered_data_store.configuration_data_cache";
-
-    private final ConcurrentMap<InstanceIdentifier, CompositeNode> operationalDataCache;
-    private final ConcurrentMap<InstanceIdentifier, CompositeNode> configurationDataCache;
-
-    private Logger logger = LoggerFactory.getLogger(ClusteredDataStoreImpl.class);
-
-    public ClusteredDataStoreImpl(IClusterGlobalServices clusterGlobalServices) throws CacheConfigException {
-        logger.trace("Constructing clustered data store");
-        Preconditions.checkNotNull(clusterGlobalServices, "clusterGlobalServices cannot be null");
-
-        operationalDataCache = getOrCreateCache(clusterGlobalServices, OPERATIONAL_DATA_CACHE);
-
-        Preconditions.checkNotNull(operationalDataCache, "operationalDataCache cannot be null");
-
-        configurationDataCache = getOrCreateCache(clusterGlobalServices, CONFIGURATION_DATA_CACHE);
-
-        Preconditions.checkNotNull(configurationDataCache, "configurationDataCache cannot be null");
-    }
-
-    @Override
-    public DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
-        return new ClusteredDataStoreTransaction(modification);
-    }
-
-    @Override
-    public CompositeNode readOperationalData(InstanceIdentifier path) {
-        Preconditions.checkNotNull(path, "path cannot be null");
-        return operationalDataCache.get(path);
-    }
-
-    @Override
-    public boolean containsConfigurationPath(InstanceIdentifier path) {
-        return configurationDataCache.containsKey(path);
-    }
-
-    @Override
-    public boolean containsOperationalPath(InstanceIdentifier path) {
-        return operationalDataCache.containsKey(path);
-    }
-
-    @Override
-    public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
-        return configurationDataCache.keySet();
-    }
-
-    @Override
-    public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
-        return operationalDataCache.keySet();
-    }
-
-
-
-    @Override
-    public CompositeNode readConfigurationData(InstanceIdentifier path) {
-        Preconditions.checkNotNull(path, "path cannot be null");
-        return configurationDataCache.get(path);
-    }
-
-    private RpcResult<Void> finish(final ClusteredDataStoreTransaction transaction) {
-      final DataModification<InstanceIdentifier,CompositeNode> modification = transaction.getModification();
-
-      this.configurationDataCache.putAll(modification.getUpdatedConfigurationData());
-      this.operationalDataCache.putAll(modification.getUpdatedOperationalData());
-
-      for (final InstanceIdentifier removal : modification.getRemovedConfigurationData()) {
-        this.configurationDataCache.remove(removal);
-      }
-
-      for (final InstanceIdentifier removal : modification.getRemovedOperationalData()) {
-        this.operationalDataCache.remove(removal  );
-      }
-
-      Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
-      return Rpcs.<Void>getRpcResult(true, null, _emptySet);
-    }
-
-    private RpcResult<Void> rollback(final ClusteredDataStoreTransaction transaction) {
-      Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
-      return Rpcs.<Void>getRpcResult(true, null, _emptySet);
-    }
-
-
-    private ConcurrentMap getOrCreateCache(IClusterGlobalServices clusterGlobalServices, String name) throws CacheConfigException {
-        ConcurrentMap cache = clusterGlobalServices.getCache(name);
-
-        if(cache == null) {
-            try {
-                cache = clusterGlobalServices.createCache(name, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-            } catch (CacheExistException e) {
-                cache = clusterGlobalServices.getCache(name);
-            }
-        }
-        return cache;
-    }
-
-    private class ClusteredDataStoreTransaction implements DataCommitTransaction<InstanceIdentifier, CompositeNode> {
-        private final DataModification<InstanceIdentifier,CompositeNode> modification;
-
-        public ClusteredDataStoreTransaction(DataModification<InstanceIdentifier,CompositeNode> modification){
-            Preconditions.checkNotNull(modification, "modification cannot be null");
-
-            this.modification = modification;
-        }
-
-        @Override
-        public DataModification<InstanceIdentifier, CompositeNode> getModification() {
-            return this.modification;
-        }
-
-        @Override
-        public RpcResult<Void> finish() throws IllegalStateException {
-            return ClusteredDataStoreImpl.this.finish(this);
-        }
-
-        @Override
-        public RpcResult<Void> rollback() throws IllegalStateException {
-            return ClusteredDataStoreImpl.this.rollback(this);
-        }
-    }
-}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManager.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManager.java
deleted file mode 100644 (file)
index b0a099f..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore.internal;
-
-import java.util.Hashtable;
-
-import com.google.common.base.Preconditions;
-
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.datastore.ClusteredDataStore;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-public class ClusteredDataStoreManager implements //
-        ClusteredDataStore, //
-        ServiceTrackerCustomizer<IClusterGlobalServices, IClusterGlobalServices>, //
-        AutoCloseable {
-
-    private ClusteredDataStore clusteredDataStore = null;
-    private IClusterGlobalServices clusterGlobalServices = null;
-    private BundleContext context;
-
-    private ServiceReference<IClusterGlobalServices> firstClusterGlobalReference;
-    private ServiceTracker<IClusterGlobalServices, IClusterGlobalServices> clusterTracker;
-
-    @Override
-    public DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
-            DataModification<InstanceIdentifier, CompositeNode> modification) {
-        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
-        return clusteredDataStore.requestCommit(modification);
-    }
-
-    @Override
-    public CompositeNode readOperationalData(InstanceIdentifier path) {
-        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
-        return clusteredDataStore.readOperationalData(path);
-    }
-
-    @Override
-    public CompositeNode readConfigurationData(InstanceIdentifier path) {
-        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
-        return clusteredDataStore.readConfigurationData(path);
-    }
-
-    public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
-        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
-        return clusteredDataStore.getStoredConfigurationPaths();
-    }
-
-    public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
-        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
-        return clusteredDataStore.getStoredOperationalPaths();
-    }
-
-    public boolean containsConfigurationPath(InstanceIdentifier path) {
-        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
-        return clusteredDataStore.containsConfigurationPath(path);
-    }
-
-    public boolean containsOperationalPath(InstanceIdentifier path) {
-        Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
-        return clusteredDataStore.containsOperationalPath(path);
-    }
-
-    public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
-        this.clusterGlobalServices = clusterGlobalServices;
-        try {
-            // Adding creation of the clustered data store in its own method
-            // to make the method unit testable
-            clusteredDataStore = createClusteredDataStore();
-        } catch (CacheConfigException e) {
-            throw new IllegalStateException("could not construct clusteredDataStore");
-        }
-    }
-
-    @Override
-    public IClusterGlobalServices addingService(ServiceReference<IClusterGlobalServices> reference) {
-        if (clusterGlobalServices == null) {
-            setClusterGlobalServices(context.getService(reference));
-            return clusterGlobalServices;
-        }
-        return null;
-    }
-
-    @Override
-    public void modifiedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
-
-    }
-
-    @Override
-    public void removedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
-        if (clusterGlobalServices == service) {
-            clusterGlobalServices = null;
-            clusteredDataStore = null;
-        }
-    }
-
-    public BundleContext getContext() {
-        return context;
-    }
-
-    public void setContext(BundleContext context) {
-        this.context = context;
-    }
-    
-    
-    /**
-     * Function called by the dependency manager when all the required
-     * dependencies are satisfied
-     * 
-     */
-    public void start() {
-        if (context != null) {
-            clusterTracker = new ServiceTracker<>(context, IClusterGlobalServices.class, this);
-            clusterTracker.open();
-            
-            context.registerService(ClusteredDataStore.class, this, new Hashtable<String,Object>());
-        }
-    }
-
-    protected ClusteredDataStore createClusteredDataStore() throws CacheConfigException {
-        return new ClusteredDataStoreImpl(clusterGlobalServices);
-    }
-
-    @Override
-    public void close() throws Exception {
-        clusterTracker.close();
-    }
-}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/yang/odl-sal-dom-clustered-store-cfg.yang b/opendaylight/md-sal/clustered-data-store/implementation/src/main/yang/odl-sal-dom-clustered-store-cfg.yang
deleted file mode 100644 (file)
index 95a26d7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-module odl-sal-dom-clustered-store-cfg {
-       yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:cluster:store";
-    prefix "binding-impl";
-
-       import config { prefix config; revision-date 2013-04-05; }
-       import opendaylight-md-sal-dom {prefix sal;}
-
-    description
-        "Service definition for MD-SAL Clustered Store.";
-    revision "2013-10-28" {
-        description
-            "Initial revision";
-    }
-
-    identity dom-clustered-store-impl {
-        base config:module-type;
-        config:provided-service sal:dom-data-store;
-        config:java-name-prefix ClusteredDataStoreImpl;
-    }
-
-    augment "/config:modules/config:module/config:state" {
-        case dom-clustered-store-impl {
-            when "/config:modules/config:module/config:type = 'dom-clustered-store-impl'";
-        }
-    }
-    
-}
\ No newline at end of file
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java
deleted file mode 100644 (file)
index 4c97b19..0000000
+++ /dev/null
@@ -1,281 +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.datastore.internal;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class ClusteredDataStoreImplTest {
-    @Before
-    public void setUp(){
-
-    }
-
-    @Test
-    public void constructor_WhenPassedANullClusteringServices_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
-        try {
-            new ClusteredDataStoreImpl(null);
-        } catch(NullPointerException npe){
-            assertEquals("clusterGlobalServices cannot be null", npe.getMessage());
-        }
-    }
-
-    @Test
-    public void constructor_WhenClusteringServicesReturnsANullOperationalDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
-        try {
-            new ClusteredDataStoreImpl(mock(IClusterGlobalServices.class));
-        } catch(NullPointerException npe){
-            assertEquals("operationalDataCache cannot be null", npe.getMessage());
-        }
-    }
-
-    @Test
-    public void constructor_WhenClusteringServicesReturnsANullOConfigurationDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
-        // Confused about the following line?
-        // See this http://stackoverflow.com/questions/10952629/a-strange-generics-edge-case-with-mockito-when-and-generic-type-inference
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
-
-
-        try {
-            new ClusteredDataStoreImpl(mockClusterGlobalServices);
-        } catch(NullPointerException npe){
-            assertEquals("configurationDataCache cannot be null", npe.getMessage());
-        }
-    }
-
-    @Test
-    public void constructor_WhenOperationalDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
-
-        new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-    }
-
-    @Test
-    public void constructor_WhenConfigurationDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
-
-        new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-    }
-
-
-    @Test
-    public void constructor_WhenPassedAValidClusteringServices_ShouldNotThrowAnyExceptions() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        new ClusteredDataStoreImpl(mockClusterGlobalServices);
-    }
-
-
-    @Test
-    public void readOperationalData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        try {
-            store.readOperationalData(null);
-        } catch(NullPointerException npe){
-            assertEquals("path cannot be null", npe.getMessage());
-        }
-    }
-
-    @Test
-    public void readOperationalData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
-        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        assertNull(store.readOperationalData(path));
-    }
-
-    @Test
-    public void readOperationalData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
-        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        ConcurrentMap<InstanceIdentifier, CompositeNode> mockOperationalDataCache = mock(ConcurrentMap.class);
-
-        CompositeNode valueObject = mock(CompositeNode.class);
-
-        when(mockOperationalDataCache.get(path)).thenReturn(valueObject);
-
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
-
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        assertEquals(valueObject, store.readOperationalData(path));
-    }
-
-
-
-    @Test
-    public void readConfigurationData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
-
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        try {
-            store.readConfigurationData(null);
-        } catch(NullPointerException npe){
-            assertEquals("path cannot be null", npe.getMessage());
-        }
-    }
-
-
-    @Test
-    public void readConfigurationData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
-        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        assertNull(store.readConfigurationData(path));
-    }
-
-    @Test
-    public void readConfigurationData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
-        InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        ConcurrentMap<InstanceIdentifier, CompositeNode> mockConfigurationDataCache = mock(ConcurrentMap.class);
-
-        CompositeNode valueObject = mock(CompositeNode.class);
-
-        when(mockConfigurationDataCache.get(path)).thenReturn(valueObject);
-
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
-
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        assertEquals(valueObject, store.readConfigurationData(path));
-    }
-
-
-    @Test
-    public void requestCommit_ShouldReturnADataTransaction() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        assertNotNull(store.requestCommit(mock(DataModification.class)));
-
-
-    }
-
-    @Test
-    public void finishingADataTransaction_ShouldUpdateTheUnderlyingCache() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
-        ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
-        ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
-
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        DataModification mockModification = mock(DataModification.class);
-
-        Map configurationData = mock(Map.class);
-        Map operationalData = mock(Map.class);
-
-        when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
-        when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
-
-        DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> transaction = store.requestCommit(mockModification);
-
-        transaction.finish();
-
-        verify(mockConfigurationDataCache).putAll(mockModification.getUpdatedConfigurationData());
-        verify(mockOperationalDataCache).putAll(mockModification.getUpdatedOperationalData());
-    }
-
-
-    @Test
-    public void rollingBackADataTransaction_ShouldDoNothing() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
-        ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
-        ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
-
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
-
-        ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
-        DataModification mockModification = mock(DataModification.class);
-
-        Map configurationData = mock(Map.class);
-        Map operationalData = mock(Map.class);
-
-        when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
-        when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
-
-        DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> transaction = store.requestCommit(mockModification);
-
-        transaction.rollback();
-
-        verify(mockConfigurationDataCache, never()).putAll(mockModification.getUpdatedConfigurationData());
-        verify(mockOperationalDataCache, never()).putAll(mockModification.getUpdatedOperationalData());
-
-    }
-
-
-    private IClusterGlobalServices createClusterGlobalServices() throws CacheExistException, CacheConfigException {
-        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
-        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
-
-        return mockClusterGlobalServices;
-    }
-}
diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java
deleted file mode 100644 (file)
index 10f9622..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore.internal;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.felix.dm.Component;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import static junit.framework.Assert.assertNotNull;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-public class ClusteredDataStoreManagerTest {
-
-    private static ClusteredDataStoreManager clusteredDSMgr = null;
-    private IClusterGlobalServices icClusterGlbServices = mock(IClusterGlobalServices.class);
-
-    @BeforeClass
-    public static void construct() {
-        clusteredDSMgr = new ClusteredDataStoreManager();
-        assertNotNull(clusteredDSMgr);
-    }
-
-    @Test
-    public void construct_OnSetClusterGlobalServices_AssertNoException() {
-        doReturn(new ConcurrentHashMap<InstanceIdentifier, CompositeNode>()).when(icClusterGlbServices).getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE);
-        doReturn(new ConcurrentHashMap<InstanceIdentifier, CompositeNode>()).when(icClusterGlbServices).getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE);
-        clusteredDSMgr.setClusterGlobalServices(icClusterGlbServices);
-    }
-
-    @Test
-    public void construct_init_AssertNoException() throws CacheExistException, CacheConfigException {
-        ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
-        ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
-        doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
-        clusteredDSManager.start();
-    }
-
-
-    @Test
-    public void construct_readOperationalData_AssertNoException() throws CacheExistException, CacheConfigException {
-        ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
-        ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
-        doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
-        Component c = mock(Component.class);
-        
-        clusteredDSManager.start();
-        clusteredDSManager.setClusterGlobalServices(icClusterGlbServices);
-        CompositeNode o = mock(CompositeNode.class);
-
-        when(clusteredDSImpl.readOperationalData(any(InstanceIdentifier.class))).thenReturn(o);
-        assertEquals(o, clusteredDSManager.readOperationalData(any(InstanceIdentifier.class)));
-    }
-
-    @Test
-    public void construct_readConfigurationData_AssertNoException() throws CacheExistException, CacheConfigException {
-        ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
-        ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
-        doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
-        Component c = mock(Component.class);
-
-        clusteredDSManager.start();
-        clusteredDSManager.setClusterGlobalServices(icClusterGlbServices);
-        
-        CompositeNode o = mock(CompositeNode.class);
-
-        when(clusteredDSImpl.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(o);
-        assertEquals(o, clusteredDSManager.readConfigurationData(any(InstanceIdentifier.class)));
-    }
-
-    @Test
-    public void construct_requestCommit_AssertNoException() throws CacheExistException, CacheConfigException {
-        ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
-        ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
-        doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
-        IClusterGlobalServices globalServices = mock(IClusterGlobalServices.class);
-        clusteredDSManager.setClusterGlobalServices(globalServices);
-        clusteredDSManager.start();
-        DataCommitTransaction dataCommitTransaction = mock(DataCommitTransaction.class);
-
-        when(clusteredDSImpl.requestCommit(any(DataModification.class))).thenReturn(dataCommitTransaction);
-        assertEquals(dataCommitTransaction, clusteredDSManager.requestCommit(any(DataModification.class)));
-    }
-}
diff --git a/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml b/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml
deleted file mode 100644 (file)
index 2d68b47..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
-    xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>commons.integrationtest</artifactId>
-        <version>0.5.1-SNAPSHOT</version>
-        <relativePath>../../../commons/integrationtest</relativePath>
-    </parent>
-    <scm>
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
-    </scm>
-
-    <artifactId>clustered-datastore.integrationtest</artifactId>
-    <version>0.4.0-SNAPSHOT</version>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>xml-apis</groupId>
-                <artifactId>xml-apis</artifactId>
-                <version>1.4.01</version>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-it</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>xml-apis</artifactId>
-                    <groupId>xml-apis</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>reflections</artifactId>
-                    <groupId>org.reflections</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal</artifactId>
-            <version>0.7.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>clustering.services</artifactId>
-            <version>0.5.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-binding</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-            <version>4.0</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>protocol_plugins.stub</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal.implementation</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>containermanager</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>containermanager.it.implementation</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>clustering.stub</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>clustered-datastore-implementation</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>xtend-lib-osgi</artifactId>
-            <version>2.4.3</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-container-native</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-junit4</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-netconf-connector</artifactId>
-            <version>${netconf.version}</version>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <artifactId>xml-apis</artifactId>
-                    <groupId>xml-apis</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>logback-config</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-impl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-file-xml-adapter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-impl</artifactId>
-            <version>${netconf.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-client</artifactId>
-            <version>${netconf.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-common</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>concepts</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-data-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-all</artifactId>
-            <version>1.9.5</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-manager</artifactId>
-            <version>0.2.3-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-management</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-            <version>4.0</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>xtend-lib-osgi</artifactId>
-            <version>2.4.3</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-container-native</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-junit4</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-netconf-connector</artifactId>
-            <version>${netconf.version}</version>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-parser-impl</artifactId>
-            <version>${yangtools.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-model-util</artifactId>
-            <version>${yangtools.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>logback-config</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-impl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-impl</artifactId>
-            <version>${netconf.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-client</artifactId>
-            <version>${netconf.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-link-mvn</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <version>1.7.2</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-core</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-service</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-manager</artifactId>
-            <version>0.2.3-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-management</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-            <version>4.0</version>
-        </dependency>
-    </dependencies>
-    <properties>
-        <!-- Sonar jacoco plugin to get integration test coverage info -->
-        <sonar.jacoco.reportPath>../implementation/target/jacoco.exec</sonar.jacoco.reportPath>
-        <sonar.jacoco.itReportPath>../implementaiton/target/jacoco-it.exec</sonar.jacoco.itReportPath>
-    </properties>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.jacoco</groupId>
-                <artifactId>jacoco-maven-plugin</artifactId>
-                <configuration>
-                    <destFile>../implementation/target/jacoco-it.exec</destFile>
-                    <includes><include>org.opendaylight.controller.*</include></includes>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>pre-test</id>
-                        <goals>
-                            <goal>prepare-agent</goal>
-                        </goals>
-                    </execution>
-                    <execution>
-                        <id>post-test</id>
-                        <configuration>
-                            <skip>true</skip>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>
diff --git a/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java b/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java
deleted file mode 100644 (file)
index a1fa9e3..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.test.sal.binding.it.TestHelper;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.util.Filter;
-import org.ops4j.pax.exam.util.PathUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@RunWith(PaxExam.class)
-//@ExamReactorStrategy(PerClass.class)
-public class ClusteredDataStoreIT {
-    private Logger log = LoggerFactory.getLogger(ClusteredDataStoreIT.class);
-    // get the OSGI bundle context
-    @Inject
-    private BundleContext bc;
-    @Inject
-    @Filter(timeout=60*1000)
-    private ClusteredDataStore clusteredDS;
-
-    // Configure the OSGi container
-    @Configuration
-    public Option[] config() {
-        return options(
-                //
-                systemProperty("logback.configurationFile").value(
-                        "file:" + PathUtils.getBaseDir() + "/src/test/resources/logback.xml"),
-                // To start OSGi console for inspection remotely
-                systemProperty("osgi.console").value("2401"),
-                // Set the systemPackages (used by clustering)
-                systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
-                systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"),
-                // List framework bundles
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
-                // List logger bundles
-                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
-                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
-                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
-                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
-                // needed by statisticsmanager
-                mavenBundle("org.opendaylight.controller", "containermanager").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "containermanager.it.implementation").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "clustering.services").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "clustering.stub").versionAsInProject(),
-
-                // List all the bundles on which the test case depends
-                mavenBundle("org.opendaylight.controller", "sal").versionAsInProject(),
-                TestHelper.baseModelBundles(),
-                TestHelper.configMinumumBundles(),
-                TestHelper.bindingIndependentSalBundles(),
-                TestHelper.bindingAwareSalBundles(),
-                TestHelper.mdSalCoreBundles(),
-                mavenBundle("org.opendaylight.controller", "config-api").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "sal.implementation").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "protocol_plugins.stub").versionAsInProject(),
-
-                mavenBundle("org.osgi", "org.osgi.core").versionAsInProject(),
-                // adding new maven bundles
-                mavenBundle("org.mockito", "mockito-all").versionAsInProject(),
-
-                // needed by hosttracker
-                mavenBundle("org.opendaylight.controller", "clustered-datastore-implementation").versionAsInProject(),
-                mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec").versionAsInProject(),
-                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
-                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
-                junitBundles());
-    }
-
-    private String stateToString(int state) {
-        switch (state) {
-        case Bundle.ACTIVE:
-            return "ACTIVE";
-        case Bundle.INSTALLED:
-            return "INSTALLED";
-        case Bundle.RESOLVED:
-            return "RESOLVED";
-        case Bundle.UNINSTALLED:
-            return "UNINSTALLED";
-        default:
-            return "Not CONVERTED";
-        }
-    }
-
-    @Test
-    public void testBundleContextClusteredDS_NotNull() throws Exception {
-        ServiceReference serviceReference = bc.getServiceReference(ClusteredDataStore.class);
-        ClusteredDataStore store = ClusteredDataStore.class.cast(bc.getService(serviceReference));
-        assertNotNull(store);
-    }
-
-    @Test
-    public void testInjected_ClusteredDS_NotNull() {
-        assertNotNull(clusteredDS);
-    }
-
-    @Test
-    public void requestCommit_readConfigurationData_ShouldVerifyDataAndNoException() {
-        DataModification dataModification = mock(DataModification.class);
-        HashMap map = new HashMap();
-        List list = new ArrayList();
-        list.add("key");
-        InstanceIdentifier key = new InstanceIdentifier(list);
-        map.put(key, mock(CompositeNode.class));
-        when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
-        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
-        dataCommitTrans.finish();
-        Object value = clusteredDS.readConfigurationData(key);
-        Assert.assertNotNull(value);
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void requestCommit_ShouldThrowException() {
-        DataModification dataModification = null;
-        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
-        dataCommitTrans.finish();
-    }
-
-    @Test
-    public void requestCommit_readOperationalData_ShouldVerifyDataAndNoException() {
-        DataModification dataModification = mock(DataModification.class);
-        HashMap map = new HashMap();
-        List list = new ArrayList();
-        list.add("key");
-        InstanceIdentifier key = new InstanceIdentifier(list);
-        map.put(key, mock(CompositeNode.class));
-        when(dataModification.getUpdatedOperationalData()).thenReturn(map);
-        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
-        dataCommitTrans.finish();
-        Object value = clusteredDS.readOperationalData(key);
-        Assert.assertNotNull(value);
-    }
-
-    @Test
-    public void requestCommit_readConfigurationData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException() {
-        DataModification dataModification = mock(DataModification.class);
-        HashMap map = new HashMap();
-        List list = new ArrayList();
-        list.add("key");
-        InstanceIdentifier key = new InstanceIdentifier(list);
-        map.put(key, "value");
-        when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
-        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
-        dataCommitTrans.finish();
-        list = new ArrayList();
-        list.add("key1");
-        InstanceIdentifier key1 = new InstanceIdentifier(list);
-
-        Object value = clusteredDS.readConfigurationData(key1);
-        assertNull(value);
-    }
-
-    @Test
-    public void requestCommit_readOperationalData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException() {
-        DataModification dataModification = mock(DataModification.class);
-        HashMap map = new HashMap();
-        List list = new ArrayList();
-        list.add("key");
-        InstanceIdentifier key = new InstanceIdentifier(list);
-        map.put(key, mock(CompositeNode.class));
-        when(dataModification.getUpdatedOperationalData()).thenReturn(map);
-        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
-        dataCommitTrans.finish();
-        list = new ArrayList();
-        list.add("key1");
-        InstanceIdentifier key1 = new InstanceIdentifier(list);
-
-        Object value = clusteredDS.readOperationalData(key1);
-        assertNull(value);
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void requestCommit_readConfigurationData_WithNullPathShouldThrowException() {
-        DataModification dataModification = mock(DataModification.class);
-        HashMap map = new HashMap();
-        List list = new ArrayList();
-        list.add("key");
-        InstanceIdentifier key = new InstanceIdentifier(list);
-        map.put(key, "value");
-        when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
-        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
-        dataCommitTrans.finish();
-        Object value = clusteredDS.readConfigurationData(null);
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void requestCommit_readOperationalData_WithNullPathShouldThrowException() {
-        DataModification dataModification = mock(DataModification.class);
-        HashMap map = new HashMap();
-        List list = new ArrayList();
-        list.add("key");
-        InstanceIdentifier key = new InstanceIdentifier(list);
-        map.put(key, "value");
-        when(dataModification.getOriginalOperationalData()).thenReturn(map);
-        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
-        dataCommitTrans.finish();
-        Object value = clusteredDS.readOperationalData(null);
-    }
-
-}
diff --git a/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/resources/controller.xml b/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/resources/controller.xml
deleted file mode 100644 (file)
index 5f43ddc..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<persisted-snapshots>
-    <snapshots>
-        <snapshot>
-            <required-capabilities>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:cluster:store?module=odl-sal-dom-clustered-store-cfg&amp;revision=2013-10-28
-                </capability>
-            </required-capabilities>
-            <configuration>
-
-                <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-                    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:cluster:store">
-                                prefix:dom-clustered-store-impl
-                            </type>
-                            <name>cluster-data-store</name>
-                        </module>
-                    </modules>
-
-                    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-
-                    </services>
-                </data>
-
-            </configuration>
-        </snapshot>
-    </snapshots>
-</persisted-snapshots>
diff --git a/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/resources/logback.xml b/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 5246f01..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<configuration scan="true">
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-      </pattern>
-    </encoder>
-  </appender>
-
-  <root level="debug">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
index c4c1ee93519cf4276de26115419e0de187655fca..9276238e019542d224b45357fffb48a557decbfe 100644 (file)
@@ -54,10 +54,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
@@ -83,32 +80,20 @@ public final class NodeMapping {
       return  new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, aDNodeId);
   }
 
-  public static NodeId toNodeId(final InstanceIdentifier<? extends Object> node) {
-    Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(node);
-    List<PathArgument> path = node.getPath();
-    Preconditions.<List<PathArgument>>checkNotNull(path);
-    int size = path.size();
-    Preconditions.checkArgument(size >= 2);
-    final PathArgument arg = path.get(1);
-    final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg, IdentifiableItem.class);
-    Identifier<?> key = item.getKey();
-    final NodeKey nodeKey = Arguments.<NodeKey>checkInstanceOf(key, NodeKey.class);
-    return nodeKey.getId();
+  public static NodeId toNodeId(final InstanceIdentifier<?> id) {
+    final NodeKey key = id.firstKeyOf(Node.class, NodeKey.class);
+    Preconditions.checkArgument(key != null, "No node identifier found in %s", id);
+    return key.getId();
   }
 
   public static String toADNodeId(final NodeId nodeId) {
-    Preconditions.<NodeId>checkNotNull(nodeId);
     return nodeId.getValue();
   }
 
   public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorRef source) throws ConstructionException {
-    Preconditions.<NodeConnectorRef>checkNotNull(source);
-    final InstanceIdentifier<?> path = Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(source.getValue());
-    Preconditions.checkArgument(path.getPath().size() >= 3);
-    final PathArgument arg = path.getPath().get(2);
-    final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg,IdentifiableItem.class);
-    final NodeConnectorKey connectorKey = Arguments.<NodeConnectorKey>checkInstanceOf(item.getKey(), NodeConnectorKey.class);
-    return NodeMapping.toADNodeConnector(connectorKey.getId(), NodeMapping.toNodeId(path));
+    final InstanceIdentifier<?> id = Preconditions.checkNotNull(source.getValue());
+    final NodeConnectorKey key = id.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
+    return NodeMapping.toADNodeConnector(key.getId(), NodeMapping.toNodeId(id));
   }
 
   public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) throws ConstructionException {
@@ -161,6 +146,7 @@ public final class NodeMapping {
   public static NodeConnectorRef toNodeConnectorRef(final org.opendaylight.controller.sal.core.NodeConnector nodeConnector) {
 
     final NodeRef node = NodeMapping.toNodeRef(nodeConnector.getNode());
+    @SuppressWarnings("unchecked")
     final InstanceIdentifier<Node> nodePath = ((InstanceIdentifier<Node>) node.getValue());
     NodeConnectorId nodeConnectorId = null;
 
index a13d2bb06f5a4cfd9124ff9526998558d005db8f..94bd0731aaa64b8bed970a2bee7a8fe4aec5f0ce 100644 (file)
@@ -57,8 +57,6 @@
     <!-- Clustering -->
     <module>remoterpc-routingtable/implementation</module>
     <module>sal-remoterpc-connector/implementation</module>
-    <!--module>clustered-data-store/implementation</module>
-        -->
     <!-- Documentation -->
     <module>sal-rest-docgen</module>
 
       <modules>
         <module>sal-binding-it</module>
         <module>sal-binding-dom-it</module>
-        <!--module>clustered-data-store/integrationtest</module -->
-        <!--module>zeromq-routingtable/integrationtest</module -->
-        <!--module>sal-remoterpc-connector/integrationtest</module -->
-        <!--module>test/sal-rest-connector-it</modulei -->
       </modules>
     </profile>
   </profiles>
index fc297261b780f3b173604be2c9c4ca751324e2cc..871abb211710cf52d393398570d83a2ffcd21c59 100644 (file)
@@ -15,7 +15,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerCo
  * component of the controller or application supplies a concrete implementation
  * of this interface.
  * 
- * A user-implemented component (application) which faciliates the SAL and SAL
+ * A user-implemented component (application) which facilitates the SAL and SAL
  * services to access infrastructure services or providers' functionality.
  * 
  * 
index fa4841648409cd80fa868f25ecd7d04c8fbf367e..2a866a94b358ebcc031c5965e16305dcc5930b0f 100644 (file)
@@ -96,8 +96,12 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized
                 .entrySet()) {
             try {
-                Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = getCodec().toBinding(entry);
-                newMap.put(binding.getKey(), binding.getValue());
+                Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(
+                        entry);
+                if (potential.isPresent()) {
+                    Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
+                    newMap.put(binding.getKey(), binding.getValue());
+                }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", entry, e);
             }
@@ -110,8 +114,11 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
         for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath : normalized) {
             try {
-                InstanceIdentifier<? extends DataObject> binding = getCodec().toBinding(normalizedPath);
-                hashSet.add(binding);
+                Optional<InstanceIdentifier<? extends DataObject>> potential = getCodec().toBinding(normalizedPath);
+                if (potential.isPresent()) {
+                    InstanceIdentifier<? extends DataObject> binding = potential.get();
+                    hashSet.add(binding);
+                }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", normalizedPath, e);
             }
@@ -120,7 +127,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     }
 
     protected Optional<DataObject> toBindingData(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> data) {
-        if(path.isWildcarded()) {
+        if (path.isWildcarded()) {
             return Optional.absent();
         }
 
@@ -207,7 +214,11 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public DataObject getOriginalSubtree() {
             if (originalDataCache == null) {
-                originalDataCache = toBindingData(path, domEvent.getOriginalSubtree());
+                if(domEvent.getOriginalSubtree() != null) {
+                    originalDataCache = toBindingData(path, domEvent.getOriginalSubtree());
+                } else {
+                    originalDataCache = Optional.absent();
+                }
             }
             return originalDataCache.orNull();
         }
@@ -215,20 +226,23 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public DataObject getUpdatedSubtree() {
             if (updatedDataCache == null) {
-                updatedDataCache = toBindingData(path, domEvent.getUpdatedSubtree());
+                if(domEvent.getUpdatedSubtree() != null) {
+                    updatedDataCache = toBindingData(path, domEvent.getUpdatedSubtree());
+                } else {
+                    updatedDataCache = Optional.absent();
+                }
             }
-
             return updatedDataCache.orNull();
         }
 
         @Override
         public String toString() {
             return Objects.toStringHelper(TranslatedDataChangeEvent.class) //
-                .add("created", getCreatedData()) //
-                .add("updated", getUpdatedData()) //
-                .add("removed", getRemovedPaths()) //
-                .add("dom", domEvent) //
-                .toString();
+                    .add("created", getCreatedData()) //
+                    .add("updated", getUpdatedData()) //
+                    .add("removed", getRemovedPaths()) //
+                    .add("dom", domEvent) //
+                    .toString();
         }
     }
 
index 6329637dd01cfdad2470345e4c8433a07fe62ebf..3f9d5c78546af7b0f40111b745fe89c8fefc5c91 100644 (file)
@@ -16,6 +16,7 @@ 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;
@@ -42,6 +43,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
@@ -60,7 +62,8 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
     public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalized(
             final InstanceIdentifier<? extends DataObject> binding) {
 
-        // Used instance-identifier codec do not support serialization of last path
+        // Used instance-identifier codec do not support serialization of last
+        // path
         // argument if it is Augmentation (behaviour expected by old datastore)
         // in this case, we explicitly check if last argument is augmentation
         // to process it separately
@@ -103,13 +106,24 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     }
 
-    public InstanceIdentifier<? extends DataObject> toBinding(
+    /**
+     *
+     * Returns a Binding-Aware instance identifier from normalized
+     * instance-identifier if it is possible to create representation.
+     *
+     * Returns Optional.absent for cases where target is mixin node except
+     * augmentation.
+     *
+     */
+    public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
             throws DeserializationException {
 
         PathArgument lastArgument = Iterables.getLast(normalized.getPath());
-        // Used instance-identifier codec do not support serialization of last path
-        // argument if it is AugmentationIdentifier (behaviour expected by old datastore)
+        // Used instance-identifier codec do not support serialization of last
+        // path
+        // argument if it is AugmentationIdentifier (behaviour expected by old
+        // datastore)
         // in this case, we explicitly check if last argument is augmentation
         // to process it separately
         if (lastArgument instanceof AugmentationIdentifier) {
@@ -118,46 +132,96 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return toBindingImpl(normalized);
     }
 
-    private InstanceIdentifier<? extends DataObject> toBindingAugmented(
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) throws DeserializationException {
-        InstanceIdentifier<? extends DataObject> potential = toBindingImpl(normalized);
+    private Optional<InstanceIdentifier<? extends DataObject>> toBindingAugmented(
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+            throws DeserializationException {
+        Optional<InstanceIdentifier<? extends DataObject>> potential = toBindingImpl(normalized);
         // Shorthand check, if codec already supports deserialization
         // of AugmentationIdentifier we will return
-        if(isAugmentationIdentifier(potential)) {
+        if (potential.isPresent() && isAugmentationIdentifier(potential.get())) {
             return potential;
         }
 
+        int normalizedCount = getAugmentationCount(normalized);
         AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPath());
 
-        // Here we employ small trick - Binding-aware Codec injects an pointer to augmentation class
-        // if child is referenced - so we will reference child and then shorten path.
+        // Here we employ small trick - Binding-aware Codec injects an pointer
+        // to augmentation class
+        // if child is referenced - so we will reference child and then shorten
+        // path.
+        LOG.trace("Looking for candidates to match {}", normalized);
         for (QName child : lastArgument.getPossibleChildNames()) {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
-                    ImmutableList.<PathArgument> builder()
-                    .addAll(normalized.getPath()).add(new NodeIdentifier(child)).build());
+                    ImmutableList.<PathArgument> builder().addAll(normalized.getPath()).add(new NodeIdentifier(child))
+                            .build());
             try {
+                if (isNotRepresentable(childPath)) {
+                    LOG.trace("Path {} is not BI-representable, skipping it", childPath);
+                    continue;
+                }
+            } catch (DataNormalizationException e) {
+                LOG.warn("Failed to denormalize path {}, skipping it", childPath, e);
+                continue;
+            }
 
-                InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(toBindingImpl(childPath));
-                return potentialPath;
-            } catch (Exception e) {
-                LOG.trace("Unable to deserialize aug. child path for {}",childPath,e);
+            Optional<InstanceIdentifier<? extends DataObject>> baId = toBindingImpl(childPath);
+            if (!baId.isPresent()) {
+                LOG.debug("No binding-aware identifier found for path {}, skipping it", childPath);
+                continue;
             }
+
+            InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(baId.get());
+            int potentialAugmentCount = getAugmentationCount(potentialPath);
+            if (potentialAugmentCount == normalizedCount) {
+                LOG.trace("Found matching path {}", potentialPath);
+                return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
+            }
+
+            LOG.trace("Skipping mis-matched potential path {}", potentialPath);
         }
-        return toBindingImpl(normalized);
+
+        LOG.trace("Failed to find augmentation matching {}", normalized);
+        return Optional.absent();
     }
 
-    private InstanceIdentifier<? extends DataObject> toBindingImpl(
+    private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
             throws DeserializationException {
         org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath;
+
         try {
+            if (isNotRepresentable(normalized)) {
+                return Optional.absent();
+            }
             legacyPath = legacyToNormalized.toLegacy(normalized);
         } catch (DataNormalizationException e) {
             throw new IllegalStateException("Could not denormalize path.", e);
         }
         LOG.trace("InstanceIdentifier Path Deserialization: Legacy representation {}, Normalized representation: {}",
                 legacyPath, normalized);
-        return bindingToLegacy.fromDataDom(legacyPath);
+        return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
+    }
+
+    private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+            throws DataNormalizationException {
+        DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
+        if( op.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
+            return true;
+        }
+        if(op.isLeaf()) {
+            return true;
+        }
+        return false;
+    }
+
+    private DataNormalizationOperation<?> findNormalizationOperation(
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+            throws DataNormalizationException {
+        DataNormalizationOperation<?> current = legacyToNormalized.getRootOperation();
+        for (PathArgument arg : normalized.getPath()) {
+            current = current.getChild(arg);
+        }
+        return current;
     }
 
     private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toEntry(
@@ -170,7 +234,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
     public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
             throws DeserializationException {
         CompositeNode legacy = null;
-        if(isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) {
+        if (isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) {
             QName augIdentifier = BindingReflections.findQName(path.getTargetType());
             ContainerNode virtualNode = Builders.containerBuilder() //
                     .withNodeIdentifier(new NodeIdentifier(augIdentifier)) //
@@ -188,12 +252,20 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return legacyToNormalized;
     }
 
-    public Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBinding(
+    public Optional<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
             final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
             throws DeserializationException {
-        InstanceIdentifier<? extends DataObject> bindingPath = toBinding(normalized.getKey());
-        DataObject bindingData = toBinding(bindingPath, normalized.getValue());
-        return toEntry(bindingPath, bindingData);
+        Optional<InstanceIdentifier<? extends DataObject>> potentialPath = toBinding(normalized.getKey());
+        if (potentialPath.isPresent()) {
+            InstanceIdentifier<? extends DataObject> bindingPath = potentialPath.get();
+            DataObject bindingData = toBinding(bindingPath, normalized.getValue());
+            if (bindingData == null) {
+                LOG.warn("Failed to deserialize {} to Binding format. Binding path is: {}", normalized, bindingPath);
+            }
+            return Optional.of(toEntry(bindingPath, bindingData));
+        } else {
+            return Optional.absent();
+        }
     }
 
     @Override
@@ -206,14 +278,17 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed = toNormalizedImpl(augPath);
         // If used instance identifier codec added supports for deserialization
         // of last AugmentationIdentifier we will just reuse it
-        if(isAugmentationIdentifier(processed)) {
+        if (isAugmentationIdentifier(processed)) {
             return processed;
         }
-        // Here we employ small trick - DataNormalizer injecst augmentation identifier if child is
-        // also part of the path (since using a child we can safely identify augmentation)
+        // Here we employ small trick - DataNormalizer injects augmentation
+        // identifier if child is
+        // also part of the path (since using a child we can safely identify
+        // augmentation)
         // so, we scan augmentation for children add it to path
         // and use original algorithm, then shorten it to last augmentation
-        for (@SuppressWarnings("rawtypes") Class augChild : getAugmentationChildren(augPath.getTargetType())) {
+        for (@SuppressWarnings("rawtypes")
+        Class augChild : getAugmentationChildren(augPath.getTargetType())) {
             @SuppressWarnings("unchecked")
             InstanceIdentifier<?> childPath = augPath.child(augChild);
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = toNormalizedImpl(childPath);
@@ -225,8 +300,6 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return processed;
     }
 
-
-
     private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier shortenToLastAugmentation(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) {
         int position = 0;
@@ -248,7 +321,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             final InstanceIdentifier<? extends DataObject> binding) {
         int position = 0;
         int foundPosition = -1;
-        for(org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) {
+        for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) {
             position++;
             if (isAugmentation(arg.getType())) {
                 foundPosition = position;
@@ -257,8 +330,6 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return InstanceIdentifier.create(Iterables.limit(binding.getPathArguments(), foundPosition));
     }
 
-
-
     private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalizedImpl(
             final InstanceIdentifier<? extends DataObject> binding) {
         final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath = bindingToLegacy
@@ -294,10 +365,8 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             try {
                 return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
                         new Callable<Class>() {
-
-                            @SuppressWarnings("rawtypes")
                             @Override
-                            public Class call() throws Exception {
+                            public Class call() {
                                 Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
                                         .getGenericReturnType());
                                 if (listResult instanceof Class
@@ -326,16 +395,36 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return InstanceIdentifier.create(wildArgs);
     }
 
-
     private static boolean isAugmentation(final Class<? extends DataObject> type) {
         return Augmentation.class.isAssignableFrom(type);
     }
 
-    private static boolean isAugmentationIdentifier(final InstanceIdentifier<?> path) {
-        return Augmentation.class.isAssignableFrom(path.getTargetType());
+    private static boolean isAugmentationIdentifier(final InstanceIdentifier<?> potential) {
+        return Augmentation.class.isAssignableFrom(potential.getTargetType());
     }
 
     private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed) {
         return Iterables.getLast(processed.getPath()) instanceof AugmentationIdentifier;
     }
+
+    private static int getAugmentationCount(final InstanceIdentifier<?> potential) {
+        int count = 0;
+        for(org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : potential.getPathArguments()) {
+            if(isAugmentation(arg.getType())) {
+                count++;
+            }
+
+        }
+        return count;
+    }
+
+    private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier potential) {
+        int count = 0;
+        for(PathArgument arg : potential.getPath()) {
+            if(arg instanceof AugmentationIdentifier) {
+                count++;
+            }
+        }
+        return count;
+    }
 }
index a398abc75a3254c3160ae685f9d829920f726f6c..b27c80d784e39fce232ae227a752f3dd3b77ab99 100644 (file)
@@ -98,11 +98,8 @@ public class BindingIndependentConnector implements //
         Provider, //
         AutoCloseable {
 
-
-
     private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
 
-
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
             .builder().toInstance();
 
@@ -200,30 +197,30 @@ public class BindingIndependentConnector implements //
     private DataModificationTransaction createBindingToDomTransaction(
             final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
         DataModificationTransaction target = biDataService.beginTransaction();
-        LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier());
+        LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier());
         for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
             target.removeConfigurationData(biEntry);
-            LOG.debug("Delete of Binding Configuration Data {} is translated to {}",entry,biEntry);
+            LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry);
         }
         for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
             target.removeOperationalData(biEntry);
-            LOG.debug("Delete of Binding Operational Data {} is translated to {}",entry,biEntry);
+            LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry);
         }
         for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
                 .entrySet()) {
             Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
                     .toDataDom(entry);
             target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
-            LOG.debug("Update of Binding Configuration Data {} is translated to {}",entry,biEntry);
+            LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry);
         }
         for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
                 .entrySet()) {
             Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
                     .toDataDom(entry);
             target.putOperationalData(biEntry.getKey(), biEntry.getValue());
-            LOG.debug("Update of Binding Operational Data {} is translated to {}",entry,biEntry);
+            LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry);
         }
 
         return target;
@@ -279,7 +276,8 @@ public class BindingIndependentConnector implements //
         return biDataService;
     }
 
-    protected void setDomDataService(final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
+    protected void setDomDataService(
+            final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
         this.biDataService = biDataService;
     }
 
@@ -300,14 +298,14 @@ public class BindingIndependentConnector implements //
     }
 
     public void startDataForwarding() {
-        if(baDataService instanceof AbstractForwardedDataBroker) {
+        if (baDataService instanceof AbstractForwardedDataBroker) {
             dataForwarding = true;
             return;
         }
 
         final DataProviderService baData;
         if (baDataService instanceof BindingMountPointImpl) {
-            baData = ((BindingMountPointImpl)baDataService).getDataBrokerImpl();
+            baData = ((BindingMountPointImpl) baDataService).getDataBrokerImpl();
             LOG.debug("Extracted BA Data provider {} from mount point {}", baData, baDataService);
         } else {
             baData = baDataService;
@@ -478,8 +476,8 @@ public class BindingIndependentConnector implements //
             }
             DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
             BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
-            LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
-                    domTransaction.getIdentifier());
+            LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .",
+                    bindingTransaction.getIdentifier(), domTransaction.getIdentifier());
             return wrapped;
         }
     }
@@ -489,7 +487,8 @@ public class BindingIndependentConnector implements //
             DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
 
         @Override
-        public void onRegister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        public void onRegister(
+                final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
 
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
                     .getPath());
@@ -497,7 +496,8 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public void onUnregister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        public void onUnregister(
+                final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
             // NOOP for now
             // FIXME: do registration based on only active commit handlers.
         }
@@ -531,8 +531,7 @@ public class BindingIndependentConnector implements //
      *
      */
     private class DomToBindingRpcForwardingManager implements
-            RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>,
-            RouterInstantiationListener,
+            RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>, RouterInstantiationListener,
             GlobalRpcRegistrationListener {
 
         private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
@@ -615,7 +614,7 @@ public class BindingIndependentConnector implements //
                 }
 
             } catch (Exception e) {
-                LOG.error("Could not forward Rpcs of type {}", service.getName(),e);
+                LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
             }
             registrations = ImmutableSet.of();
         }
@@ -626,7 +625,8 @@ public class BindingIndependentConnector implements //
          * @param service
          * @param context
          */
-        public DomToBindingRpcForwarder(final Class<? extends RpcService> service, final Class<? extends BaseIdentity> context) {
+        public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
+                final Class<? extends BaseIdentity> context) {
             this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
             this.supportedRpcs = mappingService.getRpcQNamesFor(service);
             Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
@@ -645,8 +645,8 @@ public class BindingIndependentConnector implements //
             registrations = registrationsBuilder.build();
         }
 
-        public void registerPaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
-                final Set<InstanceIdentifier<?>> set) {
+        public void registerPaths(final Class<? extends BaseIdentity> context,
+                final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
             QName ctx = BindingReflections.findQName(context);
             for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
                     toDOMInstanceIdentifier)) {
@@ -656,7 +656,6 @@ public class BindingIndependentConnector implements //
             }
         }
 
-
         @Override
         public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
             if (EQUALS_METHOD.equals(method)) {
@@ -700,7 +699,6 @@ public class BindingIndependentConnector implements //
             }
         }
 
-
         @Override
         public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
             checkArgument(rpc != null);
@@ -748,12 +746,12 @@ public class BindingIndependentConnector implements //
                             strategy = new DefaultInvocationStrategy(rpc, targetMethod, outputClass.get(), inputClass
                                     .get());
                         } else {
-                            strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod);
+                            strategy = new NoInputInvocationStrategy(rpc, targetMethod, outputClass.get());
                         }
-                    } else if(inputClass.isPresent()){
-                        strategy = new NoOutputInvocationStrategy(rpc,targetMethod, inputClass.get());
+                    } else if (inputClass.isPresent()) {
+                        strategy = new NoOutputInvocationStrategy(rpc, targetMethod, inputClass.get());
                     } else {
-                        strategy = new NoInputNoOutputInvocationStrategy(rpc,targetMethod);
+                        strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod);
                     }
                     return strategy;
                 }
@@ -777,7 +775,8 @@ public class BindingIndependentConnector implements //
         public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
                 throws Exception;
 
-        public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+        public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput)
+                throws Exception {
             return uncheckedInvoke(rpcService, domInput);
         }
     }
@@ -800,7 +799,8 @@ public class BindingIndependentConnector implements //
 
         @SuppressWarnings("unchecked")
         @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+        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) {
@@ -809,31 +809,84 @@ public class BindingIndependentConnector implements //
             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());
+                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) {
+            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(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());
-                }
-            });
+            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));
+            }
         }
     }
 
@@ -844,7 +897,8 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+        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();
@@ -859,20 +913,19 @@ public class BindingIndependentConnector implements //
 
     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);
+            super(rpc, targetMethod);
             this.inputClass = new WeakReference(inputClass);
         }
 
-
         @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+        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) {
@@ -884,19 +937,20 @@ public class BindingIndependentConnector implements //
 
         @Override
         public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if(biRpcRegistry == null) {
+            if (biRpcRegistry == null) {
                 return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
             }
 
             CompositeNode xml = mappingService.toDataDom(input);
-            CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
+            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(RpcResult<CompositeNode> input) {
-                    return Rpcs.<Void>getRpcResult(input.isSuccessful(), null, input.getErrors());
-                }
-            });
+            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());
+                        }
+                    });
         }
     }
 
diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java
new file mode 100644 (file)
index 0000000..c1eba3e
--- /dev/null
@@ -0,0 +1,96 @@
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import static org.junit.Assert.assertFalse;
+
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+public class DeleteNestedAugmentationListenParentTest extends AbstractDataServiceTest {
+
+    private static final NodeKey NODE_KEY = new NodeKey(new NodeId("foo"));
+
+    private static final TableKey TABLE_KEY = new TableKey((short) 0);
+
+    private static final FlowKey FLOW_KEY = new FlowKey(new FlowId("100"));
+
+    private static final InstanceIdentifier<FlowCapableNode> LISTENER_PATH = InstanceIdentifier.builder(Nodes.class) //
+            .child(Node.class)
+            .augmentation(FlowCapableNode.class).build();
+
+
+    private static final InstanceIdentifier<FlowCapableNode> NODE_AUGMENT_PATH = InstanceIdentifier.builder(Nodes.class)
+            .child(Node.class,NODE_KEY)
+            .augmentation(FlowCapableNode.class)
+            .build();
+
+    private static final InstanceIdentifier<Flow> FLOW_PATH = NODE_AUGMENT_PATH.builder()
+            .child(Table.class,TABLE_KEY)
+            .child(Flow.class,FLOW_KEY)
+            .build();
+
+
+    @Test
+    public void deleteChildListenParent() throws InterruptedException, ExecutionException {
+        DataModificationTransaction initTx = baDataService.beginTransaction();
+
+        initTx.putOperationalData(FLOW_PATH, flow());
+        initTx.commit().get();
+
+        final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> event = SettableFuture.create();
+
+        ListenerRegistration<DataChangeListener> listenerReg = baDataService.registerDataChangeListener(FLOW_PATH, new DataChangeListener() {
+
+            @Override
+            public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+                event.set(change);
+            }
+        });
+
+        DataModificationTransaction deleteTx = baDataService.beginTransaction();
+        deleteTx.removeOperationalData(FLOW_PATH.augmentation(FlowStatisticsData.class));
+        deleteTx.commit().get();
+
+        DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedEvent = event.get();
+        assertFalse(receivedEvent.getRemovedOperationalData().contains(NODE_AUGMENT_PATH));
+    }
+
+    private Flow flow() {
+        FlowBuilder builder = new FlowBuilder()
+            .setKey(FLOW_KEY)
+            .addAugmentation(FlowStatisticsData.class,new FlowStatisticsDataBuilder()
+                    .setFlowStatistics(new FlowStatisticsBuilder()
+                        .setBarrier(true)
+                        .setMatch(new MatchBuilder()
+                            .build())
+                        .build())
+                    .build())
+        ;//.build();
+        return builder.build();
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-spi/pom.xml b/opendaylight/md-sal/sal-binding-spi/pom.xml
deleted file mode 100644 (file)
index 22397a8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-parent</artifactId>
-        <version>1.0-SNAPSHOT</version>
-    </parent>
-    <artifactId>sal-binding-spi</artifactId>
-    <scm>
-      <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-      <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-    </scm>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-core-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>concepts-lang</artifactId>
-            <version>0.5-SNAPSHOT</version>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/DataDomToJavaTransformer.java b/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/DataDomToJavaTransformer.java
deleted file mode 100644 (file)
index bdcb2c2..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import org.opendaylight.controller.concepts.lang.Transformer;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-public interface DataDomToJavaTransformer<P extends DataObject> extends Transformer<CompositeNode, P> {
-
-    /**
-     * Returns a QName of valid input composite node.
-     * 
-     * @return
-     */
-    QName getQName();
-}
diff --git a/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/JavaToDataDomTransformer.java b/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/JavaToDataDomTransformer.java
deleted file mode 100644 (file)
index 21154b4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import org.opendaylight.controller.concepts.lang.InputClassBasedTransformer;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-public interface JavaToDataDomTransformer<I extends DataObject> extends
-        InputClassBasedTransformer<DataObject, I, CompositeNode> {
-}
diff --git a/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/Mapper.java b/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/Mapper.java
deleted file mode 100644 (file)
index 44ca27e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-/**
- * Translator between Binding-Independent format and generated Binding Data Objects
- * 
- * 
- * 
- * 
- * @param <T> Result Type 
- */
-public interface Mapper<T extends DataObject> {
-
-    QName getQName();
-    Class<T> getDataObjectClass();    
-    T objectFromDom(CompositeNode object);
-    
-    /**
-     * 
-     * @param obj
-     * @return
-     * @throws IllegalArgumentException 
-     */
-    CompositeNode domFromObject(DataObject obj) throws IllegalArgumentException;
-
-}
diff --git a/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/MappingProvider.java b/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/MappingProvider.java
deleted file mode 100644 (file)
index b3eded9..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-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.data.api.CompositeNode;
-
-public interface MappingProvider {
-
-    <T extends DataObject> Mapper<T> mapperForClass(Class<T> type);
-    Mapper<DataObject> mapperForQName(QName name);
-    
-    /**
-     * Returns {@link RpcMapper} associated to class
-     * 
-     * @param type Class for which RpcMapper should provide mapping
-     * @return
-     */
-    <T extends RpcService> RpcMapper<T> rpcMapperForClass(Class<T> type);
-    
-    /**
-     * Returns {@link RpcMapper} associated to the {@link RpcService} proxy.
-     * 
-     * @param proxy
-     * @return
-     */
-    RpcMapper<? extends RpcService> rpcMapperForProxy(RpcService proxy);
-    
-    /**
-     * 
-     * 
-     * @param rpc
-     * @param inputNode
-     * @return
-     */
-    RpcMapper<? extends RpcService> rpcMapperForData(QName rpc,
-            CompositeNode inputNode);
-
-    <T extends MappingExtension> MappingExtensionFactory<T> getExtensionFactory(Class<T> cls);
-
-    public interface MappingExtension {
-
-    }
-    
-    public interface MappingExtensionFactory<T> {
-        T forClass(Class<?> obj);
-    }
-
-
-
-}
diff --git a/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcMapper.java b/opendaylight/md-sal/sal-binding-spi/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcMapper.java
deleted file mode 100644 (file)
index 3e32ebc..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import java.util.Set;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-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.RpcResult;
-
-public interface RpcMapper<T extends RpcService> {
-    
-    Set<QName> getRpcQNames();
-    
-    /**
-     * Returns a class object representing subinterface
-     * to whom, this mapper is assigned.
-     * 
-     * @return
-     */
-    Class<T> getServiceClass();
-    
-    /**
-     * Returns a Binding Mapper for Rpc Input Data
-     * @return
-     */
-    Mapper<?> getInputMapper();
-    /**
-     * Returns a Binding Mapper for Rpc Output Data
-     * 
-     * @return
-     */
-    Mapper<?> getOutputMapper();
-    
-    /**
-     * Returns a consumer proxy, which is responsible
-     * for invoking the rpc functionality of {@link BindingAwareBroker} implementation.
-     * 
-     * @return Proxy of {@link RpcService} assigned to this mapper.
-     */
-    T getConsumerProxy(RpcProxyInvocationHandler handler);
-    
-    /**
-     * Invokes the method of RpcService representing the supplied rpc.
-     * 
-     * @param rpc QName of Rpc
-     * @param impl Implementation of RpcService on which the method should be invoked
-     * @param baInput Input Data to RPC method
-     * @return Result of RPC invocation.
-     */
-    RpcResult<? extends DataObject> invokeRpcImplementation(QName rpc,
-            RpcService impl, DataObject baInput);
-    
-    public interface RpcProxyInvocationHandler {
-        
-        Future<RpcResult<? extends DataObject>> invokeRpc(RpcService proxy, QName rpc, DataObject input);
-    }
-}
index a36d984fa75c88e50360b7da64a8c8bbb7dcd832..f869254dcf1efa2832f792005c7f22f02d9be033 100644 (file)
@@ -45,6 +45,7 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -82,6 +83,8 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
 
     public abstract NormalizedNode<?, ?> normalize(Node<?> legacyData);
 
+    public abstract boolean isLeaf();
+
     private static abstract class SimpleTypeNormalization<T extends PathArgument> extends DataNormalizationOperation<T> {
 
         protected SimpleTypeNormalization(final T identifier) {
@@ -112,6 +115,11 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
             return null;
         }
 
+        @Override
+        public boolean isLeaf() {
+            return true;
+        }
+
     }
 
     private static final class LeafNormalization extends SimpleTypeNormalization<NodeIdentifier> {
@@ -198,6 +206,11 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
             return builder.build();
         }
 
+        @Override
+        public boolean isLeaf() {
+            return false;
+        }
+
         @SuppressWarnings("rawtypes")
         protected abstract NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode);
 
@@ -223,20 +236,32 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
             if (potential != null) {
                 return potential;
             }
-            potential = fromSchema(schema, child);
+            potential = fromLocalSchema(child);
             return register(potential);
         }
 
+        private DataNormalizationOperation<?> fromLocalSchema(final PathArgument child) throws DataNormalizationException {
+            if (child instanceof AugmentationIdentifier) {
+                return fromSchemaAndQNameChecked(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
+                        .iterator().next());
+            }
+            return fromSchemaAndQNameChecked(schema, child.getNodeType());
+        }
+
         @Override
         public DataNormalizationOperation<?> getChild(final QName child) throws DataNormalizationException {
             DataNormalizationOperation<?> potential = byQName.get(child);
             if (potential != null) {
                 return potential;
             }
-            potential = fromSchemaAndPathArgument(schema, child);
+            potential = fromLocalSchemaAndQName(schema, child);
             return register(potential);
         }
 
+        protected DataNormalizationOperation<?> fromLocalSchemaAndQName(final DataNodeContainer schema2, final QName child) throws DataNormalizationException {
+            return fromSchemaAndQNameChecked(schema2, child);
+        }
+
         private DataNormalizationOperation<?> register(final DataNormalizationOperation<?> potential) {
             if (potential != null) {
                 byArg.put(potential.getIdentifier(), potential);
@@ -398,38 +423,34 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
     }
 
-    private static final class AugmentationNormalization extends MixinNormalizationOp<AugmentationIdentifier> {
-
-        private final Map<QName, DataNormalizationOperation<?>> byQName;
-        private final Map<PathArgument, DataNormalizationOperation<?>> byArg;
+    private static final class AugmentationNormalization extends DataContainerNormalizationOperation<AugmentationIdentifier> {
 
         public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
-            super(augmentationIdentifierFrom(augmentation));
-
-            ImmutableMap.Builder<QName, DataNormalizationOperation<?>> byQNameBuilder = ImmutableMap.builder();
-            ImmutableMap.Builder<PathArgument, DataNormalizationOperation<?>> byArgBuilder = ImmutableMap.builder();
-
-            for (DataSchemaNode augNode : augmentation.getChildNodes()) {
-                DataSchemaNode resolvedNode = schema.getDataChildByName(augNode.getQName());
-                DataNormalizationOperation<?> resolvedOp = fromDataSchemaNode(resolvedNode);
-                byArgBuilder.put(resolvedOp.getIdentifier(), resolvedOp);
-                for (QName resQName : resolvedOp.getQNameIdentifiers()) {
-                    byQNameBuilder.put(resQName, resolvedOp);
-                }
-            }
-            byQName = byQNameBuilder.build();
-            byArg = byArgBuilder.build();
-
+            //super();
+            super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation,schema));
         }
 
         @Override
-        public DataNormalizationOperation<?> getChild(final PathArgument child) {
-            return byArg.get(child);
+        public boolean isMixin() {
+            return true;
         }
 
+
+
         @Override
-        public DataNormalizationOperation<?> getChild(final QName child) {
-            return byQName.get(child);
+        protected DataNormalizationOperation<?> fromLocalSchemaAndQName(final DataNodeContainer schema, final QName child)
+                throws DataNormalizationException {
+            Optional<DataSchemaNode> potential = findChildSchemaNode(schema, child);
+            if (!potential.isPresent()) {
+                return null;
+            }
+
+            DataSchemaNode result = potential.get();
+            // We try to look up if this node was added by augmentation
+            if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+                return fromAugmentation(schema, (AugmentationTarget) schema, result);
+            }
+            return fromDataSchemaNode(result);
         }
 
         @Override
@@ -591,23 +612,30 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
     }
 
-    private static DataNormalizationOperation<?> fromSchemaAndPathArgument(final DataNodeContainer schema,
-            final QName child) throws DataNormalizationException {
-        DataSchemaNode potential = schema.getDataChildByName(child);
+    private static final Optional<DataSchemaNode> findChildSchemaNode(final DataNodeContainer parent,final QName child) {
+        DataSchemaNode potential = parent.getDataChildByName(child);
         if (potential == null) {
             Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices = FluentIterable.from(
-                    schema.getChildNodes()).filter(org.opendaylight.yangtools.yang.model.api.ChoiceNode.class);
+                    parent.getChildNodes()).filter(org.opendaylight.yangtools.yang.model.api.ChoiceNode.class);
             potential = findChoice(choices, child);
         }
+        return Optional.fromNullable(potential);
+    }
 
-        if (potential == null) {
+    private static DataNormalizationOperation<?> fromSchemaAndQNameChecked(final DataNodeContainer schema,
+            final QName child) throws DataNormalizationException {
+
+        Optional<DataSchemaNode> potential = findChildSchemaNode(schema, child);
+        if (!potential.isPresent()) {
             throw new DataNormalizationException(String.format("Supplied QName %s is not valid according to schema %s, potential children nodes: %s", child, schema,schema.getChildNodes()));
         }
 
-        if ((schema instanceof DataSchemaNode) && !((DataSchemaNode) schema).isAugmenting() && potential.isAugmenting()) {
-            return fromAugmentation(schema, (AugmentationTarget) schema, potential);
+        DataSchemaNode result = potential.get();
+        // We try to look up if this node was added by augmentation
+        if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+            return fromAugmentation(schema, (AugmentationTarget) schema, result);
         }
-        return fromDataSchemaNode(potential);
+        return fromDataSchemaNode(result);
     }
 
     private static org.opendaylight.yangtools.yang.model.api.ChoiceNode findChoice(
@@ -615,7 +643,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         org.opendaylight.yangtools.yang.model.api.ChoiceNode foundChoice = null;
         choiceLoop: for (org.opendaylight.yangtools.yang.model.api.ChoiceNode choice : choices) {
             for (ChoiceCaseNode caze : choice.getCases()) {
-                if (caze.getDataChildByName(child) != null) {
+                if (findChildSchemaNode(caze, child).isPresent()) {
                     foundChoice = choice;
                     break choiceLoop;
                 }
@@ -632,30 +660,44 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         return new AugmentationIdentifier(null, potentialChildren.build());
     }
 
-    private static AugmentationNormalization fromAugmentation(final DataNodeContainer schema,
-            final AugmentationTarget augments, final DataSchemaNode potential) {
+    private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) {
+        Set<DataSchemaNode> children = new HashSet<>();
+        for (DataSchemaNode augNode : augmentation.getChildNodes()) {
+            children.add(schema.getDataChildByName(augNode.getQName()));
+        }
+        return new DataSchemaContainerProxy(children);
+    }
+
+    /**
+     * Returns a DataNormalizationOperation for provided child node
+     *
+     * If supplied child is added by Augmentation this operation returns
+     * a DataNormalizationOperation for augmentation,
+     * otherwise returns a DataNormalizationOperation for child as
+     * call for {@link #fromDataSchemaNode(DataSchemaNode)}.
+     *
+     *
+     * @param parent
+     * @param parentAug
+     * @param child
+     * @return
+     */
+    private static DataNormalizationOperation<?> fromAugmentation(final DataNodeContainer parent,
+            final AugmentationTarget parentAug, final DataSchemaNode child) {
         AugmentationSchema augmentation = null;
-        for (AugmentationSchema aug : augments.getAvailableAugmentations()) {
-            DataSchemaNode child = aug.getDataChildByName(potential.getQName());
-            if (child != null) {
+        for (AugmentationSchema aug : parentAug.getAvailableAugmentations()) {
+            DataSchemaNode potential = aug.getDataChildByName(child.getQName());
+            if (potential != null) {
                 augmentation = aug;
                 break;
             }
 
         }
         if (augmentation != null) {
-            return new AugmentationNormalization(augmentation, schema);
+            return new AugmentationNormalization(augmentation, parent);
         } else {
-            return null;
-        }
-    }
-
-    private static DataNormalizationOperation<?> fromSchema(final DataNodeContainer schema, final PathArgument child) throws DataNormalizationException {
-        if (child instanceof AugmentationIdentifier) {
-            return fromSchemaAndPathArgument(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
-                    .iterator().next());
+            return fromDataSchemaNode(child);
         }
-        return fromSchemaAndPathArgument(schema, child.getNodeType());
     }
 
     public static DataNormalizationOperation<?> fromDataSchemaNode(final DataSchemaNode potential) {
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataSchemaContainerProxy.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataSchemaContainerProxy.java
new file mode 100644 (file)
index 0000000..d243c88
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.common.impl.util.compat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+
+class DataSchemaContainerProxy implements DataNodeContainer {
+
+    private final Set<DataSchemaNode> realChildSchemas;
+    private final Map<QName, DataSchemaNode> mappedChildSchemas;
+
+    public DataSchemaContainerProxy(final Set<DataSchemaNode> realChildSchema) {
+        realChildSchemas = realChildSchema;
+        mappedChildSchemas = new HashMap<QName, DataSchemaNode>();
+        for(DataSchemaNode schema : realChildSchemas) {
+            mappedChildSchemas.put(schema.getQName(),schema);
+        }
+    }
+
+    @Override
+    public DataSchemaNode getDataChildByName(final QName name) {
+        return mappedChildSchemas.get(name);
+    }
+
+    @Override
+    public Set<DataSchemaNode> getChildNodes() {
+        return realChildSchemas;
+    }
+
+    @Override
+    public DataSchemaNode getDataChildByName(final String arg0) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<GroupingDefinition> getGroupings() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<TypeDefinition<?>> getTypeDefinitions() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<UsesNode> getUses() {
+        return Collections.emptySet();
+    }
+
+}
index 902665d1a6fa137d41d7f1bc89cf8116fbb52ee1..a4017c23a89df0b4099f193e6cef4f44c2f281f9 100644 (file)
@@ -7,16 +7,16 @@
  */
 package org.opendaylight.controller.sal.common.util;
 
-public class Arguments {
+public final class Arguments {
 
     private Arguments() {
         throw new UnsupportedOperationException("Utility class");
     }
-    
+
     /**
      * Checks if value is instance of provided class
-     * 
-     * 
+     *
+     *
      * @param value Value to check
      * @param type Type to check
      * @return Reference which was checked
@@ -24,7 +24,7 @@ public class Arguments {
     @SuppressWarnings("unchecked")
     public static <T> T checkInstanceOf(Object value, Class<T> type) {
         if(!type.isInstance(value))
-            throw new IllegalArgumentException();
+            throw new IllegalArgumentException(String.format("Value %s is not of type %s", value, type));
         return (T) value;
     }
 }
diff --git a/opendaylight/md-sal/sal-data-api/pom.xml b/opendaylight/md-sal/sal-data-api/pom.xml
deleted file mode 100644 (file)
index 6b73e29..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
-  <modelVersion>4.0.0</modelVersion>\r
-  <parent>\r
-    <groupId>org.opendaylight.controller</groupId>\r
-    <artifactId>sal-parent</artifactId>\r
-    <version>1.0-SNAPSHOT</version>\r
-  </parent>\r
-   <artifactId>sal-data-api</artifactId>\r
-   <scm>\r
-     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
-     <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
-     <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
-   </scm>\r
-\r
-</project>\r
index 0006953542bb698cff7bd06fe4c85133012da047..3127df521f72547a0567f00f60e07101c247f5dc 100644 (file)
@@ -17,7 +17,7 @@ import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
  * component of the controller or application supplies a concrete implementation
  * of this interface.
  * 
- * A user-implemented component (application) which faciliates the SAL and SAL
+ * A user-implemented component (application) which facilitates the SAL and SAL
  * services to access infrastructure services or providers' functionality.
  * 
  * 
index e2df70baeac05a3a1fc113de6205a0ccc504206c..fef8618b2c450d4a4a6f095d35d7939d2edfd70e 100644 (file)
@@ -18,7 +18,7 @@ import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
  * of this interface.
  * 
  * <p>
- * A user-implemented component (application) which faciliates the SAL and SAL
+ * A user-implemented component (application) which facilitates the SAL and SAL
  * services to access infrastructure services and to provide functionality to
  * {@link Consumer}s and other providers.
  * 
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java
deleted file mode 100644 (file)
index 11028dc..0000000
+++ /dev/null
@@ -1,92 +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.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-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.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;
-
-import com.google.common.base.Optional;
-
-class DataAndMetadataSnapshot {
-
-    private final StoreMetadataNode metadataTree;
-    private final Optional<SchemaContext> schemaContext;
-
-    private DataAndMetadataSnapshot(final StoreMetadataNode metadataTree, final Optional<SchemaContext> schemaCtx) {
-        this.metadataTree = metadataTree;
-        this.schemaContext = schemaCtx;
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static DataAndMetadataSnapshot createEmpty() {
-        return createEmpty(new NodeIdentifier(SchemaContext.NAME));
-    }
-
-
-    public static DataAndMetadataSnapshot createEmpty(final NodeIdentifier rootNode) {
-        NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(rootNode).build();
-        StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data);
-        return new DataAndMetadataSnapshot(metadata,Optional.<SchemaContext>absent());
-    }
-
-    public static DataAndMetadataSnapshot createEmpty(final SchemaContext ctx) {
-        NodeIdentifier rootNodeIdentifier = new NodeIdentifier(ctx.getQName());
-        NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(rootNodeIdentifier).build();
-        StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data);
-        return new DataAndMetadataSnapshot(metadata, Optional.of(ctx));
-    }
-
-    public Optional<SchemaContext> getSchemaContext() {
-        return schemaContext;
-    }
-
-    public NormalizedNode<?, ?> getDataTree() {
-        return metadataTree.getData();
-    }
-
-    public StoreMetadataNode getMetadataTree() {
-        return metadataTree;
-    }
-
-    public Optional<StoreMetadataNode> read(final InstanceIdentifier path) {
-        return TreeNodeUtils.findNode(metadataTree, path);
-    }
-
-    public static class Builder {
-        private NormalizedNode<?, ?> dataTree;
-        private StoreMetadataNode metadataTree;
-        private SchemaContext schemaContext;
-
-        public NormalizedNode<?, ?> getDataTree() {
-            return dataTree;
-        }
-
-        public Builder setMetadataTree(final StoreMetadataNode metadataTree) {
-            this.metadataTree = metadataTree;
-            return this;
-        }
-
-        public Builder setSchemaContext(final SchemaContext schemaContext) {
-            this.schemaContext = schemaContext;
-            return this;
-        }
-
-        public DataAndMetadataSnapshot build() {
-            return new DataAndMetadataSnapshot(metadataTree, Optional.fromNullable(schemaContext));
-        }
-
-    }
-}
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
new file mode 100644 (file)
index 0000000..6baf764
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..3124199
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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 0a2b66c2d0112a35e4173d11ac8c7e06de1f73c2..7d2ff30b1fe64f96d89619894e83d26880f8bd73 100644 (file)
@@ -14,7 +14,6 @@ import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.incre
 import java.util.Collections;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
@@ -34,7 +33,6 @@ 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.data.impl.schema.NormalizedNodeUtils;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
@@ -54,23 +52,16 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
     private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
 
-
     private final ListeningExecutorService executor;
     private final String name;
     private final AtomicLong txCounter = new AtomicLong(0);
-    private final ListenerTree listenerTree;
-    private final AtomicReference<DataAndMetadataSnapshot> snapshot;
-
-    private ModificationApplyOperation operationTree;
-
-    private SchemaContext schemaContext;
+    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);
         this.executor = Preconditions.checkNotNull(executor);
-        this.listenerTree = ListenerTree.create();
-        this.snapshot = new AtomicReference<DataAndMetadataSnapshot>(DataAndMetadataSnapshot.createEmpty());
-        this.operationTree = new AlwaysFailOperation();
     }
 
     @Override
@@ -80,23 +71,30 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        return new SnapshotBackedReadTransaction(nextIdentifier(), snapshot.get());
+        return new SnapshotBackedReadTransaction(nextIdentifier(), dataTree.takeSnapshot());
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        return new SnapshotBackedReadWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
+        return new SnapshotBackedReadWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new SnapshotBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
+        return new SnapshotBackedWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree);
     }
 
     @Override
     public synchronized void onGlobalContextUpdated(final SchemaContext ctx) {
-        operationTree = SchemaAwareApplyOperationRoot.from(ctx);
-        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
@@ -104,21 +102,21 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
             final InstanceIdentifier path, final L listener, final DataChangeScope scope) {
 
         /*
-         * Make sure commit is not occurring right now. Listener has to be registered and its
-         * state capture enqueued at a consistent point.
+         * Make sure commit is not occurring right now. Listener has to be
+         * registered and its state capture enqueued at a consistent point.
          *
-         * FIXME: improve this to read-write lock, such that multiple listener registrations
-         *        can occur simultaneously
+         * FIXME: improve this to read-write lock, such that multiple listener
+         * registrations can occur simultaneously
          */
         final DataChangeListenerRegistration<L> reg;
         synchronized (this) {
-            LOG.debug("{}: Registering data change listener {} for {}",name,listener,path);
+            LOG.debug("{}: Registering data change listener {} for {}", name, listener, path);
 
             reg = listenerTree.registerDataChangeListener(path, listener, scope);
 
-            Optional<StoreMetadataNode> currentState = snapshot.get().read(path);
+            Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(path);
             if (currentState.isPresent()) {
-                final NormalizedNode<?, ?> data = currentState.get().getData();
+                final NormalizedNode<?, ?> data = currentState.get();
 
                 final DOMImmutableDataChangeEvent event = DOMImmutableDataChangeEvent.builder(DataChangeScope.BASE) //
                         .setAfter(data) //
@@ -138,9 +136,8 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         };
     }
 
-    private synchronized DOMStoreThreePhaseCommitCohort submit(
-            final SnapshotBackedWriteTransaction writeTx) {
-        LOG.debug("Tx: {} is submitted. Modifications: {}",writeTx.getIdentifier(),writeTx.getMutatedView());
+    private synchronized DOMStoreThreePhaseCommitCohort submit(final SnapshotBackedWriteTransaction writeTx) {
+        LOG.debug("Tx: {} is submitted. Modifications: {}", writeTx.getIdentifier(), writeTx.getMutatedView());
         return new ThreePhaseCommitImpl(writeTx);
     }
 
@@ -148,28 +145,23 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         return name + "-" + txCounter.getAndIncrement();
     }
 
-    private void commit(final DataAndMetadataSnapshot currentSnapshot,
-            final StoreMetadataNode newDataTree, final ResolveDataChangeEventsTask listenerResolver) {
-        LOG.debug("Updating Store snaphot version: {} with version:{}",currentSnapshot.getMetadataTree().getSubtreeVersion(),newDataTree.getSubtreeVersion());
+    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));
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Data Tree is {}", StoreUtils.toStringTree(newDataTree.getData()));
         }
 
-        final DataAndMetadataSnapshot newSnapshot = DataAndMetadataSnapshot.builder() //
-                .setMetadataTree(newDataTree) //
-                .setSchemaContext(schemaContext) //
-                .build();
-
         /*
-         * The commit has to occur atomically with regard to listener registrations.
+         * The commit has to occur atomically with regard to listener
+         * registrations.
          */
         synchronized (this) {
-            final boolean success = snapshot.compareAndSet(currentSnapshot, newSnapshot);
-            checkState(success, "Store snapshot and transaction snapshot differ. This should never happen.");
+            dataTree.commitSnapshot(currentSnapshot, newDataTree);
 
             for (ChangeListenerNotifyTask task : listenerResolver.call()) {
-                LOG.trace("Scheduling invocation of listeners: {}",task);
+                LOG.trace("Scheduling invocation of listeners: {}", task);
                 executor.submit(task);
             }
         }
@@ -195,7 +187,8 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         /**
          * Add class-specific toString attributes.
          *
-         * @param toStringHelper ToStringHelper instance
+         * @param toStringHelper
+         *            ToStringHelper instance
          * @return ToStringHelper instance which was passed in
          */
         protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
@@ -203,13 +196,14 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         }
     }
 
-    private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements DOMStoreReadTransaction {
-        private DataAndMetadataSnapshot stableSnapshot;
+    private static final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
+            DOMStoreReadTransaction {
+        private DataTree.Snapshot stableSnapshot;
 
-        public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) {
+        public SnapshotBackedReadTransaction(final Object identifier, final DataTree.Snapshot snapshot) {
             super(identifier);
             this.stableSnapshot = Preconditions.checkNotNull(snapshot);
-            LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree().getSubtreeVersion());
+            LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot);
         }
 
         @Override
@@ -222,21 +216,22 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
             checkNotNull(path, "Path must not be null.");
             checkState(stableSnapshot != null, "Transaction is closed");
-            return Futures.immediateFuture(NormalizedNodeUtils.findNode(stableSnapshot.getDataTree(), path));
+            return Futures.immediateFuture(stableSnapshot.readNode(path));
         }
     }
 
-    private static class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements DOMStoreWriteTransaction {
+    private static class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements
+            DOMStoreWriteTransaction {
         private MutableDataTree mutableTree;
         private InMemoryDOMDataStore store;
         private boolean ready = false;
 
-        public SnapshotBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
+        public SnapshotBackedWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot,
                 final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
             super(identifier);
             mutableTree = MutableDataTree.from(snapshot, applyOper);
             this.store = store;
-            LOG.debug("Write Tx: {} allocated with snapshot {}",identifier,snapshot.getMetadataTree().getSubtreeVersion());
+            LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot);
         }
 
         @Override
@@ -250,11 +245,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
             checkNotReady();
             try {
-                LOG.trace("Tx: {} Write: {}:{}",getIdentifier(),path,data);
+                LOG.trace("Tx: {} Write: {}:{}", getIdentifier(), path, data);
                 mutableTree.write(path, data);
-              // FIXME: Add checked exception
+                // FIXME: Add checked exception
             } catch (Exception e) {
-                LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e);
+                LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e);
             }
         }
 
@@ -262,11 +257,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
             checkNotReady();
             try {
-                LOG.trace("Tx: {} Merge: {}:{}",getIdentifier(),path,data);
+                LOG.trace("Tx: {} Merge: {}:{}", getIdentifier(), path, data);
                 mutableTree.merge(path, data);
-              // FIXME: Add checked exception
+                // FIXME: Add checked exception
             } catch (Exception e) {
-                LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e);
+                LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e);
             }
         }
 
@@ -274,11 +269,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         public void delete(final InstanceIdentifier path) {
             checkNotReady();
             try {
-                LOG.trace("Tx: {} Delete: {}",getIdentifier(),path);
+                LOG.trace("Tx: {} Delete: {}", getIdentifier(), path);
                 mutableTree.delete(path);
-             // FIXME: Add checked exception
+                // FIXME: Add checked exception
             } catch (Exception e) {
-                LOG.error("Tx: {}, failed to delete {} in {}",getIdentifier(),path,mutableTree,e);
+                LOG.error("Tx: {}, failed to delete {} in {}", getIdentifier(), path, mutableTree, e);
             }
         }
 
@@ -313,18 +308,18 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     private static class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements
             DOMStoreReadWriteTransaction {
 
-        protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
+        protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot,
                 final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
             super(identifier, snapshot, store, applyOper);
         }
 
         @Override
         public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
-            LOG.trace("Tx: {} Read: {}",getIdentifier(),path);
+            LOG.trace("Tx: {} Read: {}", getIdentifier(), path);
             try {
                 return Futures.immediateFuture(getMutatedView().read(path));
             } catch (Exception e) {
-                LOG.error("Tx: {} Failed Read of {}",getIdentifier(),path,e);
+                LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
                 throw e;
             }
         }
@@ -335,7 +330,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         private final SnapshotBackedWriteTransaction transaction;
         private final NodeModification modification;
 
-        private DataAndMetadataSnapshot storeSnapshot;
+        private DataTree.Snapshot storeSnapshot;
         private Optional<StoreMetadataNode> proposedSubtree;
         private ResolveDataChangeEventsTask listenerResolver;
 
@@ -346,16 +341,23 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
         @Override
         public ListenableFuture<Boolean> canCommit() {
-            final DataAndMetadataSnapshot snapshotCapture = snapshot.get();
+            final DataTree.Snapshot snapshotCapture = dataTree.takeSnapshot();
             final ModificationApplyOperation snapshotOperation = operationTree;
 
             return executor.submit(new Callable<Boolean>() {
 
                 @Override
                 public Boolean call() throws Exception {
-                    boolean applicable = snapshotOperation.isApplicable(modification,
-                            Optional.of(snapshotCapture.getMetadataTree()));
-                    LOG.debug("Store Transcation: {} : canCommit : {}", transaction.getIdentifier(), applicable);
+                    Boolean applicable = false;
+                    try {
+                        snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification,
+                            Optional.of(snapshotCapture.getRootNode()));
+                        applicable = true;
+                    } catch (DataPreconditionFailedException e) {
+                        LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e);
+                        applicable = false;
+                    }
+                    LOG.debug("Store Transaction: {} : canCommit : {}", transaction.getIdentifier(), applicable);
                     return applicable;
                 }
             });
@@ -363,17 +365,15 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
         @Override
         public ListenableFuture<Void> preCommit() {
-            storeSnapshot = snapshot.get();
-            if(modification.getModificationType() == ModificationType.UNMODIFIED) {
+            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.getMetadataTree();
+                    StoreMetadataNode metadataTree = storeSnapshot.getRootNode();
 
                     proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
                             increase(metadataTree.getSubtreeVersion()));
@@ -399,14 +399,14 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
         @Override
         public ListenableFuture<Void> commit() {
-            if(modification.getModificationType() == ModificationType.UNMODIFIED) {
+            if (modification.getModificationType() == ModificationType.UNMODIFIED) {
                 return Futures.immediateFuture(null);
             }
 
-            checkState(proposedSubtree != null,"Proposed subtree must be computed");
-            checkState(storeSnapshot != null,"Proposed subtree must be computed");
+            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);
+            InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(), listenerResolver);
             return Futures.<Void> immediateFuture(null);
         }
 
@@ -421,7 +421,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         }
 
         @Override
-        public boolean isApplicable(final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
+        public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
             throw new IllegalStateException("Schema Context is not available.");
         }
 
index 838afe31c6cf15ce52cb46b3b735d9270dc55452..361be6800c41d22a4b02f9ed9441c1018b126c98 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 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.StoreTreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 
 import com.google.common.base.Optional;
@@ -59,17 +60,6 @@ public interface ModificationApplyOperation extends StoreTreeNode<ModificationAp
      */
     Optional<StoreMetadataNode> apply(NodeModification modification, Optional<StoreMetadataNode> storeMeta, UnsignedLong subtreeVersion);
 
-    /**
-     *
-     * 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
-     */
-    boolean isApplicable(NodeModification modification, Optional<StoreMetadataNode> current);
-
     /**
      *
      * Performs structural verification of NodeModification, such as writen values / types
@@ -88,4 +78,16 @@ public interface ModificationApplyOperation extends StoreTreeNode<ModificationAp
      */
     @Override
     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
+     * @throws DataPreconditionFailedException
+    */
+    void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
 }
index b711163b465d3ca07914da3d3472347ab854533e..1002cd54b51b9afab310ec0e28d949c2fb2584a5 100644 (file)
@@ -34,13 +34,13 @@ class MutableDataTree {
     private static final Logger LOG = LoggerFactory.getLogger(MutableDataTree.class);
     private final AtomicBoolean sealed = new AtomicBoolean();
     private final ModificationApplyOperation strategyTree;
-    private final DataAndMetadataSnapshot snapshot;
     private final NodeModification rootModification;
+    private final DataTree.Snapshot snapshot;
 
-    private MutableDataTree(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation strategyTree) {
-        this.snapshot = snapshot;
-        this.strategyTree = strategyTree;
-        this.rootModification = NodeModification.createUnmodified(snapshot.getMetadataTree());
+    private MutableDataTree(final DataTree.Snapshot snapshot, final ModificationApplyOperation strategyTree) {
+        this.snapshot = Preconditions.checkNotNull(snapshot);
+        this.strategyTree = Preconditions.checkNotNull(strategyTree);
+        this.rootModification = NodeModification.createUnmodified(snapshot.getRootNode());
     }
 
     public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
@@ -97,7 +97,7 @@ class MutableDataTree {
                 return potentialSnapshot.get();
             }
             return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
-                    StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion()));
+                    StoreUtils.increase(snapshot.getRootNode().getSubtreeVersion()));
         } catch (Exception e) {
             LOG.error("Could not create snapshot for {}:{}", path,modification,e);
             throw e;
@@ -119,7 +119,7 @@ class MutableDataTree {
         return OperationWithModification.from(operation, modification);
     }
 
-    public static MutableDataTree from(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation resolver) {
+    public static MutableDataTree from(final DataTree.Snapshot snapshot, final ModificationApplyOperation resolver) {
         return new MutableDataTree(snapshot, resolver);
     }
 
index 8aefb925e7a44e24446778e4f91c6b04d995be8d..780291e70f3b1399be48648a8d2a451a8608a134 100644 (file)
@@ -45,10 +45,6 @@ public class OperationWithModification {
         return applyOperation;
     }
 
-    public boolean isApplicable(final Optional<StoreMetadataNode> data) {
-        return applyOperation.isApplicable(modification, data);
-    }
-
     public Optional<StoreMetadataNode> apply(final Optional<StoreMetadataNode> data, final UnsignedLong subtreeVersion) {
         return applyOperation.apply(modification, data, subtreeVersion);
     }
index e74ba958915d2809b6cac4dc927ea329840652fa..44d50166af21df772f478d057fa479d879e0b829 100644 (file)
@@ -327,12 +327,12 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
             final Collection<Node> listeners, final NormalizedNode<?, ?> beforeData,
             final NormalizedNode<?, ?> afterData) {
 
-        if (beforeData instanceof NormalizedNodeContainer<?, ?, ?> && !listeners.isEmpty()) {
+        if (beforeData instanceof NormalizedNodeContainer<?, ?, ?>) {
             // Node is container (contains child) and we have interested
             // listeners registered for it, that means we need to do
             // resolution of changes on children level and can not
             // shortcut resolution.
-
+            LOG.trace("Resolving subtree replace event for {} before {}, after {}",path,beforeData,afterData);
             @SuppressWarnings("unchecked")
             NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) beforeData;
             @SuppressWarnings("unchecked")
@@ -342,7 +342,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
             // Node is either of Leaf type (does not contain child nodes)
             // or we do not have listeners, so normal equals method is
             // sufficient for determining change.
-
+            LOG.trace("Resolving leaf replace event for {} , before {}, after {}",path,beforeData,afterData);
             DOMImmutableDataChangeEvent event = builder(DataChangeScope.BASE).setBefore(beforeData).setAfter(afterData)
                     .addUpdated(path, beforeData, afterData).build();
             addPartialTask(listeners, event);
@@ -447,12 +447,13 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
     private DOMImmutableDataChangeEvent resolveSameEventRecursivelly(final InstanceIdentifier path,
             final Collection<Node> listeners, final NormalizedNode<PathArgument, ?> node,
             final SimpleEventFactory eventFactory) {
-
         final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
         DOMImmutableDataChangeEvent propagateEvent = event;
-            // We have listeners for this node or it's children, so we will try
+        // We have listeners for this node or it's children, so we will try
             // to do additional processing
         if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+            LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory);
+
             Builder eventBuilder = builder(DataChangeScope.BASE);
             eventBuilder.merge(event);
             eventBuilder.setBefore(event.getOriginalSubtree());
@@ -464,6 +465,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
             NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
             for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
                 PathArgument childId = child.getIdentifier();
+                LOG.trace("Resolving event for child {}", childId);
                 Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
                 eventBuilder.merge(resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory));
             }
@@ -473,7 +475,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
             propagateEvent = builder(DataChangeScope.BASE).build();
         }
         if (!listeners.isEmpty()) {
-            addPartialTask(listeners, event);
+            addPartialTask(listeners, propagateEvent);
         }
         return propagateEvent;
     }
@@ -521,9 +523,9 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
 
     private DOMImmutableDataChangeEvent addPartialTask(final Collection<ListenerTree.Node> listeners,
             final DOMImmutableDataChangeEvent event) {
-
         for (ListenerTree.Node listenerNode : listeners) {
             if (!listenerNode.getListeners().isEmpty()) {
+                LOG.trace("Adding event {} for listeners {}",event,listenerNode);
                 events.put(listenerNode, event);
             }
         }
index 4bb5aed20c72d9a8424063818cf0c84e31630b47..afe9653394ec4a3363d34a48d9cd937b73363de1 100644 (file)
@@ -20,6 +20,7 @@ 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.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
@@ -141,55 +142,61 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
     protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
 
     @Override
-    public boolean isApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+    public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
         switch (modification.getModificationType()) {
         case DELETE:
-            return isDeleteApplicable(modification, current);
+            checkDeleteApplicable(modification, current);
         case SUBTREE_MODIFIED:
-            return isSubtreeModificationApplicable(modification, current);
+            checkSubtreeModificationApplicable(path,modification, current);
+            return;
         case WRITE:
-            return isWriteApplicable(modification, current);
+            checkWriteApplicable(path,modification, current);
+            return;
         case MERGE:
-            return isMergeApplicable(modification,current);
+            checkMergeApplicable(path,modification,current);
+            return;
         case UNMODIFIED:
-            return true;
+            return;
         default:
-            return false;
+            throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
         }
+
     }
 
-    private boolean isMergeApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+    protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
         Optional<StoreMetadataNode> original = modification.getOriginal();
         if (original.isPresent() && current.isPresent()) {
-            return isNotConflicting(original.get(), current.get());
-        } else if (current.isPresent()) {
-            return true;
+            /*
+             * We need to do conflict detection only and only if the value of leaf changed
+             * before two transactions. If value of leaf is unchanged between two transactions
+             * it should not cause transaction to fail, since result of this merge
+             * leads to same data.
+             */
+            if(!original.get().getData().equals(current.get().getData())) {
+
+                checkNotConflicting(path,original.get(), current.get());
+            }
         }
-        return true;
     }
 
-    protected boolean isWriteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+    protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
         Optional<StoreMetadataNode> original = modification.getOriginal();
         if (original.isPresent() && current.isPresent()) {
-            return isNotConflicting(original.get(), current.get());
-        } else if (current.isPresent()) {
-            return false;
+            checkNotConflicting(path,original.get(), current.get());
+        } else if(original.isPresent()) {
+            throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
         }
-        return true;
-
     }
 
-    protected final boolean isNotConflicting(final StoreMetadataNode original, final StoreMetadataNode current) {
-        return original.getNodeVersion().equals(current.getNodeVersion())
-                && original.getSubtreeVersion().equals(current.getSubtreeVersion());
+    protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException {
+        checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction.");
+        checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction");
     }
 
-    protected abstract boolean isSubtreeModificationApplicable(final NodeModification modification,
-            final Optional<StoreMetadataNode> current);
+    protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
+            final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
 
-    private boolean isDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
-        // FiXME: Add delete conflict detection.
-        return true;
+    private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
     }
 
     @Override
@@ -271,9 +278,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
 
         @Override
-        protected boolean isSubtreeModificationApplicable(final NodeModification modification,
-                final Optional<StoreMetadataNode> current) {
-            return false;
+        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
+                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+            throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
         }
 
     }
@@ -312,6 +319,14 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
             }
         }
 
+        @Override
+        protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
+                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+            // FIXME: Implement proper write check for replacement of node container
+            //        prerequisite is to have transaction chain available for clients
+            //        otherwise this will break chained writes to same node.
+        }
+
         @SuppressWarnings("rawtypes")
         @Override
         protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
@@ -392,19 +407,29 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
 
         @Override
-        protected boolean isSubtreeModificationApplicable(final NodeModification modification,
-                final Optional<StoreMetadataNode> current) {
-            if (false == current.isPresent()) {
-                return false;
-            }
-            boolean result = true;
+        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
+                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+            checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction.");
+            checkChildPreconditions(path,modification,current);
+
+        }
+
+        private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
             StoreMetadataNode currentMeta = current.get();
             for (NodeModification childMod : modification.getModifications()) {
                 PathArgument childId = childMod.getIdentifier();
                 Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
-                result &= resolveChildOperation(childId).isApplicable(childMod, childMeta);
+                InstanceIdentifier childPath = StoreUtils.append(path, childId);
+                resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta);
+            }
+        }
+
+        @Override
+        protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
+                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+            if(current.isPresent()) {
+                checkChildPreconditions(path,modification,current);
             }
-            return result;
         }
 
         @SuppressWarnings("rawtypes")
@@ -497,8 +522,6 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
 
         protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
             super(createAugmentProxy(schema,resolved), AugmentationNode.class);
-            // FIXME: Use resolved children instead of unresolved.
-
         }
 
         @Override
@@ -647,9 +670,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         }
 
         @Override
-        protected boolean isSubtreeModificationApplicable(final NodeModification modification,
-                final Optional<StoreMetadataNode> current) {
-            return false;
+        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
+                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+            throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
         }
 
     }
@@ -726,4 +749,11 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper
         return new AugmentationSchemaProxy(schema, realChildSchemas);
     }
 
+    public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
+        if(!condition) {
+            throw new DataPreconditionFailedException(path, message);
+        }
+        return condition;
+    }
+
 }
index 0f77ac504a3f5a647f9a184e88b7ecc569332c6f..e1da9a738140c073fa26f4cf5d25d84d6d58c63a 100644 (file)
@@ -7,12 +7,8 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import java.util.Collections;
-import java.util.Map;
 import java.util.Set;
 
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
@@ -25,10 +21,10 @@ import com.google.common.base.Function;
 import com.google.common.base.Strings;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.primitives.UnsignedLong;
 
 public final class StoreUtils {
+    private static final int STRINGTREE_INDENT = 4;
 
     private final static Function<Identifiable<Object>, Object> EXTRACT_IDENTIFIER = new Function<Identifiable<Object>, Object>() {
         @Override
@@ -37,18 +33,8 @@ public final class StoreUtils {
         }
     };
 
-    public static final UnsignedLong increase(final UnsignedLong original) {
-        return original.plus(UnsignedLong.ONE);
-    }
-
-    public static final InstanceIdentifier append(final InstanceIdentifier parent, final PathArgument arg) {
-
-        return new InstanceIdentifier(ImmutableList.<PathArgument> builder().addAll(parent.getPath()).add(arg).build());
-    }
-
-    public static AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> initialChangeEvent(
-            final InstanceIdentifier path, final StoreMetadataNode data) {
-        return new InitialDataChangeEvent(path, data.getData());
+    private StoreUtils() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
     }
 
     /*
@@ -61,70 +47,39 @@ public final class StoreUtils {
         return (Function) EXTRACT_IDENTIFIER;
     }
 
-    private static final class InitialDataChangeEvent implements
-            AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> {
-
-        private final ImmutableMap<InstanceIdentifier, NormalizedNode<?, ?>> payload;
-        private final NormalizedNode<?, ?> data;
-
-        public InitialDataChangeEvent(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
-            payload = ImmutableMap.<InstanceIdentifier, NormalizedNode<?, ?>> of(path, data);
-            this.data = data;
-        }
-
-        @Override
-        public Map<InstanceIdentifier, NormalizedNode<?, ?>> getCreatedData() {
-            return payload;
-        }
-
-        @Override
-        public Map<InstanceIdentifier, ? extends NormalizedNode<?, ?>> getOriginalData() {
-            return Collections.emptyMap();
-        }
-
-        @Override
-        public NormalizedNode<?, ?> getOriginalSubtree() {
-            return null;
-        }
-
-        @Override
-        public Set<InstanceIdentifier> getRemovedPaths() {
-            return Collections.emptySet();
-        }
-
-        @Override
-        public Map<InstanceIdentifier, NormalizedNode<?, ?>> getUpdatedData() {
-            return payload;
-        }
+    public static final UnsignedLong increase(final UnsignedLong original) {
+        return original.plus(UnsignedLong.ONE);
+    }
 
-        @Override
-        public NormalizedNode<?, ?> getUpdatedSubtree() {
-            return data;
-        }
+    public static final InstanceIdentifier append(final InstanceIdentifier parent, final PathArgument arg) {
+        return new InstanceIdentifier(ImmutableList.<PathArgument> builder().addAll(parent.getPath()).add(arg).build());
     }
 
     public static <V> Set<V> toIdentifierSet(final Iterable<? extends Identifiable<V>> children) {
         return FluentIterable.from(children).transform(StoreUtils.<V> identifierExtractor()).toSet();
     }
 
-    public static String toStringTree(final StoreMetadataNode metaNode) {
+    public static String toStringTree(final NormalizedNode<?, ?> node) {
         StringBuilder builder = new StringBuilder();
-        toStringTree(builder, metaNode, 0);
+        toStringTree(builder, node, 0);
         return builder.toString();
     }
 
-    private static void toStringTree(final StringBuilder builder, final StoreMetadataNode metaNode, final int offset) {
-        String prefix = Strings.repeat(" ", offset);
-        builder.append(prefix).append(toStringTree(metaNode.getIdentifier()));
-        NormalizedNode<?, ?> dataNode = metaNode.getData();
-        if (dataNode instanceof NormalizedNodeContainer<?, ?, ?>) {
+    private static void toStringTree(final StringBuilder builder, final NormalizedNode<?, ?> node, final int offset) {
+        final String prefix = Strings.repeat(" ", offset);
+
+        builder.append(prefix).append(toStringTree(node.getIdentifier()));
+        if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+            final NormalizedNodeContainer<?, ?, ?> container = (NormalizedNodeContainer<?, ?, ?>) node;
+
             builder.append(" {\n");
-            for (StoreMetadataNode child : metaNode.getChildren()) {
-                toStringTree(builder, child, offset + 4);
+            for (NormalizedNode<?, ?> child : container.getValue()) {
+                toStringTree(builder, child, offset + STRINGTREE_INDENT);
             }
+
             builder.append(prefix).append('}');
         } else {
-            builder.append(' ').append(dataNode.getValue());
+            builder.append(' ').append(node.getValue());
         }
         builder.append('\n');
     }
index 455777b7fb9a1b315c036c6a5d9d6482473e0fa7..b8ad7368b5ea6acebc126b630e1b73bcfdd75404 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree;
 import static com.google.common.base.Preconditions.checkState;
 
 import java.util.Collections;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
 import java.util.Map;
 
 import org.opendaylight.yangtools.concepts.Identifiable;
@@ -21,7 +21,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
 import com.google.common.primitives.UnsignedLong;
 
 public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
@@ -82,10 +81,6 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
         return this.data;
     }
 
-    public Iterable<StoreMetadataNode> getChildren() {
-        return Iterables.unmodifiableIterable(children.values());
-    }
-
     @Override
     public Optional<StoreMetadataNode> getChild(final PathArgument key) {
         return Optional.fromNullable(children.get(key));
@@ -137,11 +132,11 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
         private boolean dirty = false;
 
         private Builder() {
-            children = new LinkedHashMap<>();
+            children = new HashMap<>();
         }
 
         public Builder(StoreMetadataNode node) {
-            children = new LinkedHashMap<>(node.children);
+            children = new HashMap<>(node.children);
         }
 
         public UnsignedLong getVersion() {
@@ -166,7 +161,7 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
 
         public Builder add(final StoreMetadataNode node) {
             if (dirty) {
-                children = new LinkedHashMap<>(children);
+                children = new HashMap<>(children);
                 dirty = false;
             }
             children.put(node.getIdentifier(), node);
@@ -175,7 +170,7 @@ public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>,
 
         public Builder remove(final PathArgument id) {
             if (dirty) {
-                children = new LinkedHashMap<>(children);
+                children = new HashMap<>(children);
                 dirty = false;
             }
             children.remove(id);
index 5a43c7b21885270d6b6a277ea82ad42381009f6e..c0f0a35565db16558354096d27ea75189cd60873 100644 (file)
@@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue;
 import java.util.concurrent.ExecutionException;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
@@ -119,6 +120,7 @@ public class InMemoryDataStoreTest {
     }
 
     @Test
+    @Ignore
     public void testTransactionConflict() throws InterruptedException, ExecutionException {
         DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
         DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
index e14699311bd33da365e923c6d76a66c4c6d17009..0445c47c6bcb29fa3825f9971bd8e50a8b7f9d45 100644 (file)
@@ -137,11 +137,9 @@ public class ModificationMetadataTreeTest {
 
     @Test
     public void basicReadWrites() {
-        MutableDataTree modificationTree = MutableDataTree.from(
-                DataAndMetadataSnapshot.builder() //
-                        .setMetadataTree(StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))) //
-                        .setSchemaContext(schemaContext) //
-                        .build(), new SchemaAwareApplyOperationRoot(schemaContext));
+        MutableDataTree modificationTree = MutableDataTree.from(new DataTree.Snapshot(schemaContext,
+                StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))),
+                new SchemaAwareApplyOperationRoot(schemaContext));
         Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.read(OUTER_LIST_2_PATH);
         assertTrue(originalBarNode.isPresent());
         assertSame(BAR_NODE, originalBarNode.get());
@@ -166,7 +164,7 @@ public class ModificationMetadataTreeTest {
         /**
          * Creates empty Snapshot with associated schema context.
          */
-        DataAndMetadataSnapshot emptySnapshot = DataAndMetadataSnapshot.createEmpty(schemaContext);
+        DataTree t = DataTree.create(schemaContext);
 
         /**
          *
@@ -174,7 +172,7 @@ public class ModificationMetadataTreeTest {
          * context.
          *
          */
-        MutableDataTree modificationTree = MutableDataTree.from(emptySnapshot, new SchemaAwareApplyOperationRoot(
+        MutableDataTree modificationTree = MutableDataTree.from(t.takeSnapshot(), new SchemaAwareApplyOperationRoot(
                 schemaContext));
         return modificationTree;
     }
diff --git a/opendaylight/md-sal/sal-dom-demo/pom.xml b/opendaylight/md-sal/sal-dom-demo/pom.xml
deleted file mode 100644 (file)
index 322bad7..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
-    <modelVersion>4.0.0</modelVersion>\r
-    <parent>\r
-        <groupId>org.opendaylight.controller</groupId>\r
-        <artifactId>sal-parent</artifactId>\r
-        <version>1.0-SNAPSHOT</version>\r
-    </parent>\r
-    <artifactId>sal-core-demo</artifactId>\r
-    <scm>\r
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
-    </scm>\r
-\r
-    <dependencies>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-broker-impl</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>yang-data-util</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.slf4j</groupId>\r
-            <artifactId>slf4j-simple</artifactId>\r
-            <version>1.7.2</version>\r
-            <scope>runtime</scope>\r
-        </dependency>\r
-    </dependencies>\r
-    <build>\r
-        <plugins>\r
-            <plugin>\r
-                <artifactId>maven-assembly-plugin</artifactId>\r
-                <version>2.4</version>\r
-                <configuration>\r
-                    <descriptorRefs>\r
-                        <descriptorRef>jar-with-dependencies</descriptorRef>\r
-                    </descriptorRefs>\r
-                    <archive>\r
-                        <manifest>\r
-                            <mainClass>org.opendaylight.controller.sal.demo.SALDemo</mainClass>\r
-                        </manifest>\r
-                    </archive>\r
-                </configuration>\r
-                <executions>\r
-                    <execution>\r
-                        <id>make-assembly</id>\r
-                        <phase>package</phase>\r
-                        <goals>\r
-                            <goal>single</goal>\r
-                        </goals>\r
-                    </execution>\r
-                </executions>\r
-            </plugin>\r
-\r
-        </plugins>\r
-\r
-    </build>\r
-</project>\r
diff --git a/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoConsumerImpl.java b/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoConsumerImpl.java
deleted file mode 100644 (file)
index e0752dc..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.sal.demo;\r
-\r
-import java.util.Collection;\r
-import java.util.HashSet;\r
-import java.util.Set;\r
-\r
-import org.opendaylight.controller.sal.core.api.Consumer;\r
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;\r
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;\r
-import org.opendaylight.controller.sal.core.api.notify.NotificationService;\r
-import org.opendaylight.controller.yang.common.QName;\r
-import org.opendaylight.controller.yang.data.api.CompositeNode;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-\r
-public class DemoConsumerImpl implements Consumer {\r
-\r
-    private ConsumerSession session;\r
-    private NotificationService notificationService;\r
-    private final String name;\r
-    private static Logger log = LoggerFactory.getLogger("AlertLogger");\r
-\r
-    private boolean changeAware;\r
-\r
-    public DemoConsumerImpl(String name) {\r
-        this.name = name;\r
-    }\r
-\r
-    private NotificationListener alertLogger = new NotificationListener() {\r
-\r
-        @Override\r
-        public void onNotification(CompositeNode notification) {\r
-            System.out.println(name\r
-                    + ": Received alert: "\r
-                    + notification.getFirstSimpleByName(\r
-                            DemoUtils.contentNodeName).getValue());\r
-            log.info("AlertLogger: Received notification: " + notification);\r
-        }\r
-\r
-        @Override\r
-        public Set<QName> getSupportedNotifications() {\r
-            Set<QName> supported = new HashSet<QName>();\r
-            supported.add(DemoUtils.alertNotification);\r
-            return supported;\r
-        }\r
-    };\r
-\r
-    private NotificationListener changeLogger = new NotificationListener() {\r
-\r
-        @Override\r
-        public void onNotification(CompositeNode notification) {\r
-            System.out.println(name\r
-                    + ": Received change: "\r
-                    + notification.getFirstSimpleByName(\r
-                            DemoUtils.contentNodeName).getValue());\r
-            log.info("ChangeLogger: Received notification: " + notification);\r
-        }\r
-\r
-        @Override\r
-        public Set<QName> getSupportedNotifications() {\r
-            Set<QName> supported = new HashSet<QName>();\r
-            supported.add(DemoUtils.alertNotification);\r
-            return supported;\r
-        }\r
-    };\r
-\r
-    @Override\r
-    public void onSessionInitiated(ConsumerSession session) {\r
-        this.session = session;\r
-        this.notificationService = session\r
-                .getService(NotificationService.class);\r
-        notificationService.addNotificationListener(\r
-                DemoUtils.alertNotification, alertLogger);\r
-        if (isChangeAware()) {\r
-            notificationService.addNotificationListener(\r
-                    DemoUtils.changeNotification, changeLogger);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public Collection<ConsumerFunctionality> getConsumerFunctionality() {\r
-        Set<ConsumerFunctionality> func = new HashSet<ConsumerFunctionality>();\r
-        func.add(alertLogger);\r
-        return func;\r
-    }\r
-\r
-    public void closeSession() {\r
-        session.close();\r
-    }\r
-\r
-    public boolean isChangeAware() {\r
-        return changeAware;\r
-    }\r
-\r
-    public void setChangeAware(boolean changeAware) {\r
-        this.changeAware = changeAware;\r
-    }\r
-\r
-}\r
diff --git a/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoProviderImpl.java b/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoProviderImpl.java
deleted file mode 100644 (file)
index 8a393be..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.demo;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.notify.NotificationProviderService;
-import org.opendaylight.controller.yang.data.api.Node;
-import org.opendaylight.controller.yang.data.util.Nodes;
-
-
-public class DemoProviderImpl implements
-        org.opendaylight.controller.sal.core.api.Provider {
-
-    private ProviderSession session;
-    private NotificationProviderService notifier;
-
-    @Override
-    public void onSessionInitiated(ProviderSession session) {
-        this.session = session;
-        notifier = session.getService(NotificationProviderService.class);
-    }
-
-    @Override
-    public Collection<ProviderFunctionality> getProviderFunctionality() {
-        return Collections.emptySet();
-    }
-
-    public void sendAlertNotification(String content) {
-        List<Node<?>> nodes = new ArrayList<Node<?>>();
-        nodes.add(DemoUtils.contentNode(content));
-
-        if (notifier == null) {
-            System.out.println("Provider: Error: Session not available");
-            System.out
-                    .println("                 Notification Service not available");
-            return;
-        }
-        notifier.sendNotification(Nodes.containerNode(
-                DemoUtils.alertNotification, nodes));
-    }
-
-    public void sendChangeNotification(String content) {
-        List<Node<?>> nodes = new ArrayList<Node<?>>();
-        nodes.add(DemoUtils.contentNode(content));
-
-        if (notifier == null) {
-            System.out.println("Provider: Error: Session not available");
-            System.out
-                    .println("                 Notification Service not available");
-            return;
-        }
-        notifier.sendNotification(Nodes.containerNode(
-                DemoUtils.changeNotification, nodes));
-    }
-
-    public void closeSession() {
-        session.close();
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoUtils.java b/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoUtils.java
deleted file mode 100644 (file)
index 3b04309..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.demo;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Date;
-
-import org.opendaylight.controller.yang.common.QName;
-import org.opendaylight.controller.yang.data.api.Node;
-import org.opendaylight.controller.yang.data.util.Nodes;
-
-
-public class DemoUtils {
-
-    public static final URI namespace = uri("urn:cisco:prototype:sal:demo");
-    public static final Date revision = new Date();
-
-    public static final QName alertNotification = qName("alert");
-    public static final QName changeNotification = qName("change");
-
-    public static final QName contentNodeName = qName("content");
-
-    public static URI uri(String str) {
-        try {
-            return new URI(str);
-        } catch (URISyntaxException e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    public static QName qName(String str) {
-        return new QName(namespace, revision, str);
-    }
-
-    public static Node<?> contentNode(String content) {
-        return Nodes.leafNode(contentNodeName, content);
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/SALDemo.java b/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/SALDemo.java
deleted file mode 100644 (file)
index 9e50059..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.sal.demo;\r
-\r
-import java.io.BufferedReader;\r
-import java.io.IOException;\r
-import java.io.InputStreamReader;\r
-\r
-import org.opendaylight.controller.sal.core.impl.BrokerImpl;\r
-import org.opendaylight.controller.sal.core.impl.NotificationModule;\r
-\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class SALDemo {\r
-    protected static final Logger logger = LoggerFactory\r
-        .getLogger(SALDemo.class);\r
-\r
-    static BrokerImpl broker;\r
-    static DemoProviderImpl provider;\r
-    static DemoConsumerImpl consumer1;\r
-    static DemoConsumerImpl consumer2;\r
-\r
-    public static void main(String[] args) {\r
-\r
-        initialize();\r
-        initializeProvider();\r
-        displayHelp();\r
-\r
-        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));\r
-        String s;\r
-        try {\r
-            while (true) {\r
-\r
-                System.out.print("\nEnter your choice (0 - list): ");\r
-                s = in.readLine();\r
-                int choice = Integer.parseInt(s.trim());\r
-                try {\r
-                    switch (choice) {\r
-                    case 0:\r
-                        displayHelp();\r
-                        break;\r
-                    case 1:\r
-                        registerProvider();\r
-                        break;\r
-                    case 2:\r
-                        registerConsumer1();\r
-                        break;\r
-                    case 3:\r
-                        registerConsumer2();\r
-                        break;\r
-                    case 4:\r
-                        sendAlert(in);\r
-                        break;\r
-                    case 5:\r
-                        sendChange(in);\r
-                        break;\r
-                    case 6:\r
-                        unregisterConsumer1();\r
-                        break;\r
-                    case 7:\r
-                        unregisterConsumer2();\r
-                        break;\r
-                    case 8:\r
-                        unregisterProvider();\r
-                        break;\r
-                    case 9:\r
-                        return;\r
-                    default:\r
-                        System.out.println("Please enter valid input.");\r
-                        break;\r
-                    }\r
-                } catch (Exception e) {\r
-                    System.out\r
-                            .println("Operation failed. Reason exception raised: "\r
-                                    + e.getClass().getSimpleName());\r
-                    System.out.println("   Message: " + e.getMessage());\r
-                }\r
-\r
-            }\r
-        } catch (IOException e) {\r
-\r
-            logger.error("",e);\r
-        }\r
-    }\r
-\r
-    private static void registerConsumer1() {\r
-        broker.registerConsumer(consumer1);\r
-    }\r
-\r
-    private static void registerConsumer2() {\r
-        broker.registerConsumer(consumer2);\r
-    }\r
-\r
-    private static void sendAlert(BufferedReader in) throws IOException {\r
-        System.out.print("Please enter notification content:");\r
-        String content = in.readLine();\r
-        provider.sendAlertNotification(content);\r
-    }\r
-\r
-    private static void sendChange(BufferedReader in) throws IOException {\r
-        System.out.print("Please enter notification content:");\r
-        String content = in.readLine();\r
-        provider.sendChangeNotification(content);\r
-    }\r
-\r
-    private static void unregisterConsumer1() {\r
-        consumer1.closeSession();\r
-    }\r
-\r
-    private static void unregisterConsumer2() {\r
-        consumer2.closeSession();\r
-    }\r
-\r
-    private static void unregisterProvider() {\r
-        provider.closeSession();\r
-    }\r
-\r
-    private static void displayHelp() {\r
-        System.out.println("Usage: ");\r
-        System.out.println("  0) Display Help");\r
-        System.out.println("  1) Register Provider");\r
-        System.out.println("  2) Register Consumer 1 (listening on alert)");\r
-        System.out\r
-                .println("  3) Register Consumer 2 (listening on alert,change)");\r
-        System.out.println("  4) Send Alert Notification");\r
-        System.out.println("  5) Send Change Notification");\r
-        System.out.println("  6) Unregister Consumer 1");\r
-        System.out.println("  7) Unregister Consumer 2");\r
-        System.out.println("  8) Unregister Provider");\r
-        System.out.println("  9) Exit");\r
-\r
-    }\r
-\r
-    private static void initializeProvider() {\r
-        provider = new DemoProviderImpl();\r
-    }\r
-\r
-    private static void initialize() {\r
-        System.out.println("Initializing broker");\r
-        broker = new BrokerImpl();\r
-        NotificationModule notifyModule = new NotificationModule();\r
-        broker.addModule(notifyModule);\r
-\r
-        consumer1 = new DemoConsumerImpl("Consumer 1");\r
-        consumer2 = new DemoConsumerImpl("Consumer 2");\r
-        consumer2.setChangeAware(true);\r
-    }\r
-\r
-    private static void registerProvider() {\r
-        broker.registerProvider(provider);\r
-    }\r
-}\r
diff --git a/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/package-info.java b/opendaylight/md-sal/sal-dom-demo/src/main/java/org/opendaylight/controller/sal/demo/package-info.java
deleted file mode 100644 (file)
index 09d4bfb..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.sal.demo;
\ No newline at end of file
index 7bf8ee860dd7fdc0be63a55b07f316702659e38d..de3c18db699e3edb42ed1fd1b49e6b54a44db91a 100644 (file)
@@ -23,11 +23,14 @@ import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
+import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
 import org.opendaylight.controller.netconf.util.handler.ssh.authentication.LoginPassword;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@@ -141,12 +144,12 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         this.bundleContext = bundleContext;
     }
 
-    public NetconfClientConfiguration getClientConfig(final NetconfDevice device) {
+    public NetconfReconnectingClientConfiguration getClientConfig(final NetconfDevice device) {
         InetSocketAddress socketAddress = getSocketAddress();
         ReconnectStrategy strategy = getReconnectStrategy();
         long clientConnectionTimeoutMillis = getConnectionTimeoutMillis();
 
-        return NetconfClientConfigurationBuilder.create()
+        return NetconfReconnectingClientConfigurationBuilder.create()
         .withAddress(socketAddress)
         .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
         .withReconnectStrategy(strategy)
@@ -155,6 +158,12 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         .withProtocol(getTcpOnly() ?
                 NetconfClientConfiguration.NetconfClientProtocol.TCP :
                 NetconfClientConfiguration.NetconfClientProtocol.SSH)
+        .withConnectStrategyFactory(new ReconnectStrategyFactory() {
+            @Override
+            public ReconnectStrategy createReconnectStrategy() {
+                return getReconnectStrategy();
+            }
+        })
         .build();
     }
 
@@ -166,7 +175,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
             logger.trace("Setting {} on {} to infinity", maxConnectionAttemptsJmxAttribute, this);
             connectionAttempts = null;
         }
-        double sleepFactor = 1.0;
+        double sleepFactor = 1.5;
         int minSleep = 1000;
         Long maxSleep = null;
         Long deadline = null;
index 54242cf26da315643d16cb350be9d4a60f300de1..94beaed0dfc61aeb0c5f260c24a1a689ec9fd7a1 100644 (file)
@@ -40,6 +40,7 @@ import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
@@ -126,7 +127,7 @@ public class NetconfDevice implements Provider, //
 
     private boolean rollbackSupported;
 
-    private NetconfClientConfiguration clientConfig;
+    private NetconfReconnectingClientConfiguration clientConfig;
     private volatile DataProviderService dataProviderService;
 
     public NetconfDevice(String name) {
@@ -146,7 +147,7 @@ public class NetconfDevice implements Provider, //
 
         logger.info("Starting NETCONF Client {} for address {}", name, socketAddress);
 
-        dispatcher.createClient(clientConfig);
+        dispatcher.createReconnectingClient(clientConfig);
     }
 
     Optional<SchemaContext> getSchemaContext() {
@@ -491,7 +492,7 @@ public class NetconfDevice implements Provider, //
         this.dispatcher = dispatcher;
     }
 
-    public void setClientConfig(final NetconfClientConfiguration clientConfig) {
+    public void setClientConfig(final NetconfReconnectingClientConfiguration clientConfig) {
         this.clientConfig = clientConfig;
     }
 
index d6ec2fd74dfe12cbc72b003f64ef6e36de6b8c46..fe00ab1836dbf7326d2a3352b86c018b4cce139d 100644 (file)
       <groupId>io.netty</groupId>
       <artifactId>netty-codec-http</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.eclipse.xtend</groupId>
-      <artifactId>org.eclipse.xtend.lib</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-remote</artifactId>
           <instructions>
             <Bundle-Name>MD SAL Restconf Connector</Bundle-Name>
             <Private-Package>org.opendaylight.controller.sal.rest.*,
-              org.opendaylight.controller.sal.restconf.impl,
-              org.eclipse.xtend2.lib,
-              org.eclipse.xtend.lib,
-              org.eclipse.xtext.xbase.*,</Private-Package>
+              org.opendaylight.controller.sal.restconf.impl,</Private-Package>
             <Import-Package>*,
             com.sun.jersey.spi.container.servlet</Import-Package>
             <Bundle-Activator>org.opendaylight.controller.sal.rest.impl.RestconfProvider</Bundle-Activator>
           </instructions>
         </configuration>
       </plugin>
-      <plugin>
-        <groupId>org.eclipse.xtend</groupId>
-        <artifactId>xtend-maven-plugin</artifactId>
-      </plugin>
     </plugins>
   </build>
   <scm>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java
new file mode 100644 (file)
index 0000000..1cc1f78
--- /dev/null
@@ -0,0 +1,201 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.util.concurrent.Future;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+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.mount.MountInstance;
+import org.opendaylight.controller.sal.rest.impl.RestconfProvider;
+import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
+    private final static Logger LOG = LoggerFactory.getLogger( BrokerFacade.class );
+
+    private final static BrokerFacade INSTANCE = new BrokerFacade();
+
+    private volatile DataBrokerService dataService;
+    private volatile ConsumerSession context;
+
+    private BrokerFacade() {
+    }
+
+    public void setContext( final ConsumerSession context ) {
+        this.context = context;
+    }
+
+    public void setDataService( final DataBrokerService dataService ) {
+        this.dataService = dataService;
+    }
+
+    public static BrokerFacade getInstance() {
+        return BrokerFacade.INSTANCE;
+    }
+
+    private void checkPreconditions() {
+        if( context == null || dataService == null ) {
+            ResponseException _responseException = new ResponseException( Status.SERVICE_UNAVAILABLE,
+                    RestconfProvider.NOT_INITALIZED_MSG );
+            throw _responseException;
+        }
+    }
+
+    @Override
+    public CompositeNode readConfigurationData( final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        LOG.trace( "Read Configuration via Restconf: {}", path );
+
+        return dataService.readConfigurationData( path );
+    }
+
+    public CompositeNode readConfigurationDataBehindMountPoint( final MountInstance mountPoint,
+                                                                final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        LOG.trace( "Read Configuration via Restconf: {}", path );
+
+        return mountPoint.readConfigurationData( path );
+    }
+
+    @Override
+    public CompositeNode readOperationalData( final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        BrokerFacade.LOG.trace( "Read Operational via Restconf: {}", path );
+
+        return dataService.readOperationalData( path );
+    }
+
+    public CompositeNode readOperationalDataBehindMountPoint( final MountInstance mountPoint,
+                                                              final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        BrokerFacade.LOG.trace( "Read Operational via Restconf: {}", path );
+
+        return mountPoint.readOperationalData( path );
+    }
+
+    public RpcResult<CompositeNode> invokeRpc( final QName type, final CompositeNode payload ) {
+        this.checkPreconditions();
+
+        final Future<RpcResult<CompositeNode>> future = context.rpc( type, payload );
+
+        try {
+            return future.get();
+        }
+        catch( Exception e ) {
+            throw new ResponseException( e, "Error invoking RPC " + type );
+        }
+    }
+
+    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut( final InstanceIdentifier path,
+                                                                            final CompositeNode payload ) {
+        this.checkPreconditions();
+
+        final DataModificationTransaction transaction = dataService.beginTransaction();
+        BrokerFacade.LOG.trace( "Put Configuration via Restconf: {}", path );
+        transaction.putConfigurationData( path, payload );
+        return transaction.commit();
+    }
+
+    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPutBehindMountPoint(
+            final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload ) {
+        this.checkPreconditions();
+
+        final DataModificationTransaction transaction = mountPoint.beginTransaction();
+        BrokerFacade.LOG.trace( "Put Configuration via Restconf: {}", path );
+        transaction.putConfigurationData( path, payload );
+        return transaction.commit();
+    }
+
+    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPost( final InstanceIdentifier path,
+                                                                             final CompositeNode payload) {
+        this.checkPreconditions();
+
+        final DataModificationTransaction transaction = dataService.beginTransaction();
+        /* check for available Node in Configuration DataStore by path */
+        CompositeNode availableNode = transaction.readConfigurationData( path );
+        if (availableNode != null) {
+            String errMsg = "Post Configuration via Restconf was not executed because data already exists";
+            BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
+            // FIXME: return correct ietf-restconf:errors -> follow specification
+            // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
+            throw new ResponseException(Status.CONFLICT, errMsg);
+        }
+        BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
+        transaction.putConfigurationData( path, payload );
+        return transaction.commit();
+    }
+
+    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPostBehindMountPoint(
+            final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload ) {
+        this.checkPreconditions();
+
+        final DataModificationTransaction transaction = mountPoint.beginTransaction();
+        /* check for available Node in Configuration DataStore by path */
+        CompositeNode availableNode = transaction.readConfigurationData( path );
+        if (availableNode != null) {
+            String errMsg = "Post Configuration via Restconf was not executed because data already exists";
+            BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
+            // FIXME: return correct ietf-restconf:errors -> follow specification
+            // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
+            throw new ResponseException(Status.CONFLICT, errMsg);
+        }
+        BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
+        transaction.putConfigurationData( path, payload );
+        return transaction.commit();
+    }
+
+    public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete( final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        final DataModificationTransaction transaction = dataService.beginTransaction();
+        LOG.info( "Delete Configuration via Restconf: {}", path );
+        transaction.removeConfigurationData( path );
+        return transaction.commit();
+    }
+
+    public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
+                                          final MountInstance mountPoint, final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        final DataModificationTransaction transaction = mountPoint.beginTransaction();
+        LOG.info( "Delete Configuration via Restconf: {}", path );
+        transaction.removeConfigurationData( path );
+        return transaction.commit();
+    }
+
+    public void registerToListenDataChanges( final ListenerAdapter listener ) {
+        this.checkPreconditions();
+
+        if( listener.isListening() ) {
+            return;
+        }
+
+        InstanceIdentifier path = listener.getPath();
+        final ListenerRegistration<DataChangeListener> registration =
+                                             dataService.registerDataChangeListener( path, listener );
+
+        listener.setRegistration( registration );
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend
deleted file mode 100644 (file)
index d305006..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.restconf.impl
-
-import javax.ws.rs.core.Response
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.core.api.mount.MountInstance
-import org.opendaylight.controller.sal.rest.impl.RestconfProvider
-import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.slf4j.LoggerFactory
-
-class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
-
-
-    val static LOG = LoggerFactory.getLogger(BrokerFacade)
-    val static BrokerFacade INSTANCE = new BrokerFacade
-
-    @Property
-    private ConsumerSession context;
-
-    @Property
-    private DataBrokerService dataService;
-    
-    private new() {
-        if (INSTANCE !== null) {
-            throw new IllegalStateException("Already instantiated");
-        }
-    }
-
-    def static BrokerFacade getInstance() {
-        return INSTANCE
-    }
-
-    private def void checkPreconditions() {
-        if (context === null || dataService === null) {
-            throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
-        }
-    }
-
-    override readConfigurationData(InstanceIdentifier path) {
-        checkPreconditions
-        LOG.trace("Read Configuration via Restconf: {}", path)
-        return dataService.readConfigurationData(path);
-    }
-    
-    def readConfigurationDataBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path) {
-        checkPreconditions
-        LOG.trace("Read Configuration via Restconf: {}", path)
-        return mountPoint.readConfigurationData(path);
-    }
-
-    override readOperationalData(InstanceIdentifier path) {
-        checkPreconditions
-        LOG.trace("Read Operational via Restconf: {}", path)
-        return dataService.readOperationalData(path);
-    }
-    
-    def readOperationalDataBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path) {
-        checkPreconditions
-        LOG.trace("Read Operational via Restconf: {}", path)
-        return mountPoint.readOperationalData(path);
-    }
-
-    def RpcResult<CompositeNode> invokeRpc(QName type, CompositeNode payload) {
-        checkPreconditions
-        val future = context.rpc(type, payload);
-        return future.get;
-    }
-
-    def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
-        checkPreconditions
-        val transaction = dataService.beginTransaction;
-        LOG.trace("Put Configuration via Restconf: {}", path)
-        transaction.putConfigurationData(path, payload);
-        return transaction.commit
-    }
-    
-    def commitConfigurationDataPutBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path, CompositeNode payload) {
-        checkPreconditions
-        val transaction = mountPoint.beginTransaction;
-        LOG.trace("Put Configuration via Restconf: {}", path)
-        transaction.putConfigurationData(path, payload);
-        return transaction.commit
-    }
-
-    def commitConfigurationDataPost(InstanceIdentifier path, CompositeNode payload) {
-        checkPreconditions
-        val transaction = dataService.beginTransaction;
-        transaction.putConfigurationData(path, payload);
-        if (payload == transaction.createdConfigurationData.get(path)) {
-            LOG.trace("Post Configuration via Restconf: {}", path)
-            return transaction.commit
-        }
-        LOG.trace("Post Configuration via Restconf was not executed because data already exists: {}", path)
-        return null;
-    }
-    
-    def commitConfigurationDataPostBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path, CompositeNode payload) {
-        checkPreconditions
-        val transaction = mountPoint.beginTransaction;
-        transaction.putConfigurationData(path, payload);
-        if (payload == transaction.createdConfigurationData.get(path)) {
-            LOG.trace("Post Configuration via Restconf: {}", path)
-            return transaction.commit
-        }
-        LOG.trace("Post Configuration via Restconf was not executed because data already exists: {}", path)
-        return null;
-    }
-
-    def commitConfigurationDataDelete(InstanceIdentifier path) {
-        checkPreconditions
-        val transaction = dataService.beginTransaction;
-        LOG.info("Delete Configuration via Restconf: {}", path)
-        transaction.removeConfigurationData(path)
-        return transaction.commit
-    }
-    
-    def commitConfigurationDataDeleteBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path) {
-        checkPreconditions
-        val transaction = mountPoint.beginTransaction;
-        LOG.info("Delete Configuration via Restconf: {}", path)
-        transaction.removeConfigurationData(path)
-        return transaction.commit
-    }
-
-    def registerToListenDataChanges(ListenerAdapter listener) {
-        checkPreconditions
-        if (listener.listening) {
-            return;
-        }
-        val registration = dataService.registerDataChangeListener(listener.path, listener)
-        listener.setRegistration(registration)
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java
new file mode 100644 (file)
index 0000000..1c076d1
--- /dev/null
@@ -0,0 +1,912 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.restconf.impl;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.rest.impl.RestUtil;
+import org.opendaylight.controller.sal.rest.impl.RestconfProvider;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestCodec;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ControllerContext implements SchemaContextListener {
+    private final static Logger LOG = LoggerFactory.getLogger( ControllerContext.class );
+
+    private final static ControllerContext INSTANCE = new ControllerContext();
+
+    private final static String NULL_VALUE = "null";
+
+    private final static String MOUNT_MODULE = "yang-ext";
+
+    private final static String MOUNT_NODE = "mount";
+
+    public final static String MOUNT = "yang-ext:mount";
+
+    private final static String URI_ENCODING_CHAR_SET = "ISO-8859-1";
+
+    private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
+
+    private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
+
+    private final Map<QName, RpcDefinition> qnameToRpc = new ConcurrentHashMap<>();
+
+    private volatile SchemaContext globalSchema;
+    private volatile MountService mountService;
+
+    public void setGlobalSchema( final SchemaContext globalSchema ) {
+        this.globalSchema = globalSchema;
+    }
+
+    public void setMountService( final MountService mountService ) {
+        this.mountService = mountService;
+    }
+
+    private ControllerContext() {
+    }
+
+    public static ControllerContext getInstance() {
+        return ControllerContext.INSTANCE;
+    }
+
+    private void checkPreconditions() {
+        if( globalSchema == null ) {
+            throw new ResponseException( Status.SERVICE_UNAVAILABLE, RestconfProvider.NOT_INITALIZED_MSG );
+        }
+    }
+
+    public void setSchemas( final SchemaContext schemas ) {
+        this.onGlobalContextUpdated( schemas );
+    }
+
+    public InstanceIdWithSchemaNode toInstanceIdentifier( final String restconfInstance ) {
+        return this.toIdentifier( restconfInstance, false );
+    }
+
+    public InstanceIdWithSchemaNode toMountPointIdentifier( final String restconfInstance ) {
+        return this.toIdentifier( restconfInstance, true );
+    }
+
+    private InstanceIdWithSchemaNode toIdentifier( final String restconfInstance,
+                                                   final boolean toMountPointIdentifier ) {
+        this.checkPreconditions();
+
+        Iterable<String> split = Splitter.on( "/" ).split( restconfInstance );
+        final ArrayList<String> encodedPathArgs = Lists.<String> newArrayList( split );
+        final List<String> pathArgs = this.urlPathArgsDecode( encodedPathArgs );
+        this.omitFirstAndLastEmptyString( pathArgs );
+        if( pathArgs.isEmpty() ) {
+            return null;
+        }
+
+        String first = pathArgs.iterator().next();
+        final String startModule = ControllerContext.toModuleName( first );
+        if( startModule == null ) {
+            throw new ResponseException( Status.BAD_REQUEST,
+                    "First node in URI has to be in format \"moduleName:nodeName\"" );
+        }
+
+        InstanceIdentifierBuilder builder = InstanceIdentifier.builder();
+        Module latestModule = this.getLatestModule( globalSchema, startModule );
+        InstanceIdWithSchemaNode iiWithSchemaNode = this.collectPathArguments( builder, pathArgs,
+                                                           latestModule, null, toMountPointIdentifier );
+
+        if( iiWithSchemaNode == null ) {
+            throw new ResponseException( Status.BAD_REQUEST, "URI has bad format" );
+        }
+
+        return iiWithSchemaNode;
+    }
+
+    private List<String> omitFirstAndLastEmptyString( final List<String> list ) {
+        if( list.isEmpty() ) {
+            return list;
+        }
+
+        String head = list.iterator().next();
+        if( head.isEmpty() ) {
+            list.remove( 0 );
+        }
+
+        if( list.isEmpty() ) {
+            return list;
+        }
+
+        String last = list.get( list.size() - 1 );
+        if( last.isEmpty() ) {
+            list.remove( list.size() - 1 );
+        }
+
+        return list;
+    }
+
+    private Module getLatestModule( final SchemaContext schema, final String moduleName ) {
+        Preconditions.checkArgument( schema != null );
+        Preconditions.checkArgument( moduleName != null && !moduleName.isEmpty() );
+
+        Predicate<Module> filter = new Predicate<Module>() {
+            @Override
+            public boolean apply( Module m ) {
+                return Objects.equal( m.getName(), moduleName );
+            }
+        };
+
+        Iterable<Module> modules = Iterables.filter( schema.getModules(), filter );
+        return this.filterLatestModule( modules );
+    }
+
+    private Module filterLatestModule( final Iterable<Module> modules ) {
+        Module latestModule = modules.iterator().hasNext() ? modules.iterator().next() : null;
+        for( final Module module : modules ) {
+            if( module.getRevision().after( latestModule.getRevision() ) ) {
+                latestModule = module;
+            }
+        }
+        return latestModule;
+    }
+
+    public Module findModuleByName( final String moduleName ) {
+        this.checkPreconditions();
+        Preconditions.checkArgument( moduleName != null && !moduleName.isEmpty() );
+        return this.getLatestModule( globalSchema, moduleName );
+    }
+
+    public Module findModuleByName( final MountInstance mountPoint, final String moduleName ) {
+        Preconditions.checkArgument( moduleName != null && mountPoint != null );
+
+        final SchemaContext mountPointSchema = mountPoint.getSchemaContext();
+        return mountPointSchema == null ? null : this.getLatestModule( mountPointSchema, moduleName );
+    }
+
+    public Module findModuleByNamespace( final URI namespace ) {
+        this.checkPreconditions();
+        Preconditions.checkArgument( namespace != null );
+
+        final Set<Module> moduleSchemas = globalSchema.findModuleByNamespace( namespace );
+        return moduleSchemas == null ? null : this.filterLatestModule( moduleSchemas );
+    }
+
+    public Module findModuleByNamespace( final MountInstance mountPoint, final URI namespace ) {
+        Preconditions.checkArgument( namespace != null && mountPoint != null );
+
+        final SchemaContext mountPointSchema = mountPoint.getSchemaContext();
+        Set<Module> moduleSchemas = mountPointSchema == null ? null :
+                                                mountPointSchema.findModuleByNamespace( namespace );
+        return moduleSchemas == null ? null : this.filterLatestModule( moduleSchemas );
+    }
+
+    public Module findModuleByNameAndRevision( final QName module ) {
+        this.checkPreconditions();
+        Preconditions.checkArgument( module != null && module.getLocalName() != null &&
+                                     module.getRevision() != null );
+
+        return globalSchema.findModuleByName( module.getLocalName(), module.getRevision() );
+    }
+
+    public Module findModuleByNameAndRevision( final MountInstance mountPoint, final QName module ) {
+        this.checkPreconditions();
+        Preconditions.checkArgument( module != null && module.getLocalName() != null &&
+                                     module.getRevision() != null && mountPoint != null );
+
+        SchemaContext schemaContext = mountPoint.getSchemaContext();
+        return schemaContext == null ? null :
+                       schemaContext.findModuleByName( module.getLocalName(), module.getRevision() );
+    }
+
+    public DataNodeContainer getDataNodeContainerFor( final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        final List<PathArgument> elements = path.getPath();
+        PathArgument head = elements.iterator().next();
+        final QName startQName = head.getNodeType();
+        final Module initialModule = globalSchema.findModuleByNamespaceAndRevision(
+                startQName.getNamespace(), startQName.getRevision() );
+        DataNodeContainer node = initialModule;
+        for( final PathArgument element : elements ) {
+            QName _nodeType = element.getNodeType();
+            final DataSchemaNode potentialNode = ControllerContext.childByQName( node, _nodeType );
+            if( potentialNode == null || !this.isListOrContainer( potentialNode ) ) {
+                return null;
+            }
+            node = (DataNodeContainer) potentialNode;
+        }
+
+        return node;
+    }
+
+    public String toFullRestconfIdentifier( final InstanceIdentifier path ) {
+        this.checkPreconditions();
+
+        final List<PathArgument> elements = path.getPath();
+        final StringBuilder builder = new StringBuilder();
+        PathArgument head = elements.iterator().next();
+        final QName startQName = head.getNodeType();
+        final Module initialModule = globalSchema.findModuleByNamespaceAndRevision(
+                startQName.getNamespace(), startQName.getRevision() );
+        DataNodeContainer node = initialModule;
+        for( final PathArgument element : elements ) {
+            QName _nodeType = element.getNodeType();
+            final DataSchemaNode potentialNode = ControllerContext.childByQName( node, _nodeType );
+            if( !this.isListOrContainer( potentialNode ) ) {
+                return null;
+            }
+            node = ((DataNodeContainer) potentialNode);
+            builder.append( this.convertToRestconfIdentifier( element, node ) );
+        }
+
+        return builder.toString();
+    }
+
+    public String findModuleNameByNamespace( final URI namespace ) {
+        this.checkPreconditions();
+
+        String moduleName = this.uriToModuleName.get( namespace );
+        if( moduleName == null ) {
+            final Module module = this.findModuleByNamespace( namespace );
+            if( module != null ) {
+                moduleName = module.getName();
+                this.uriToModuleName.put( namespace, moduleName );
+            }
+        }
+
+        return moduleName;
+    }
+
+    public String findModuleNameByNamespace( final MountInstance mountPoint, final URI namespace ) {
+        final Module module = this.findModuleByNamespace( mountPoint, namespace );
+        return module == null ? null : module.getName();
+    }
+
+    public URI findNamespaceByModuleName( final String moduleName ) {
+        URI namespace = this.moduleNameToUri.get( moduleName );
+        if( namespace == null ) {
+            Module module = this.findModuleByName( moduleName );
+            if( module != null ) {
+                URI _namespace = module.getNamespace();
+                namespace = _namespace;
+                this.uriToModuleName.put( namespace, moduleName );
+            }
+        }
+        return namespace;
+    }
+
+    public URI findNamespaceByModuleName( final MountInstance mountPoint, final String moduleName ) {
+        final Module module = this.findModuleByName( mountPoint, moduleName );
+        return module == null ? null : module.getNamespace();
+    }
+
+    public Set<Module> getAllModules( final MountInstance mountPoint ) {
+        this.checkPreconditions();
+
+        SchemaContext schemaContext = mountPoint == null ? null : mountPoint.getSchemaContext();
+        return schemaContext == null ? null : schemaContext.getModules();
+    }
+
+    public Set<Module> getAllModules() {
+        this.checkPreconditions();
+        return globalSchema.getModules();
+    }
+
+    public CharSequence toRestconfIdentifier( final QName qname ) {
+        this.checkPreconditions();
+
+        String module = this.uriToModuleName.get( qname.getNamespace() );
+        if( module == null ) {
+            final Module moduleSchema = globalSchema.findModuleByNamespaceAndRevision(
+                                                       qname.getNamespace(), qname.getRevision() );
+            if( moduleSchema == null ) {
+                return null;
+            }
+
+            this.uriToModuleName.put( qname.getNamespace(), moduleSchema.getName() );
+            module = moduleSchema.getName();
+        }
+
+        StringBuilder builder = new StringBuilder();
+        builder.append( module );
+        builder.append( ":" );
+        builder.append( qname.getLocalName() );
+        return builder.toString();
+    }
+
+    public CharSequence toRestconfIdentifier( final MountInstance mountPoint, final QName qname ) {
+        if( mountPoint == null ) {
+            return null;
+        }
+
+        SchemaContext schemaContext = mountPoint.getSchemaContext();
+
+        final Module moduleSchema = schemaContext.findModuleByNamespaceAndRevision(
+                                                       qname.getNamespace(), qname.getRevision() );
+        if( moduleSchema == null ) {
+            return null;
+        }
+
+        StringBuilder builder = new StringBuilder();
+        builder.append( moduleSchema.getName() );
+        builder.append( ":" );
+        builder.append( qname.getLocalName() );
+        return builder.toString();
+    }
+
+    private static DataSchemaNode childByQName( final ChoiceNode container, final QName name ) {
+        for( final ChoiceCaseNode caze : container.getCases() ) {
+            final DataSchemaNode ret = ControllerContext.childByQName( caze, name );
+            if( ret != null ) {
+                return ret;
+            }
+        }
+
+        return null;
+    }
+
+    private static DataSchemaNode childByQName( final ChoiceCaseNode container, final QName name ) {
+        return container.getDataChildByName( name );
+    }
+
+    private static DataSchemaNode childByQName( final ContainerSchemaNode container, final QName name ) {
+        return ControllerContext.dataNodeChildByQName( container, name );
+    }
+
+    private static DataSchemaNode childByQName( final ListSchemaNode container, final QName name ) {
+        return ControllerContext.dataNodeChildByQName( container, name );
+    }
+
+    private static DataSchemaNode childByQName( final Module container, final QName name ) {
+        return ControllerContext.dataNodeChildByQName( container, name );
+    }
+
+    private static DataSchemaNode childByQName( final DataSchemaNode container, final QName name ) {
+        return null;
+    }
+
+    private static DataSchemaNode dataNodeChildByQName( final DataNodeContainer container, final QName name ) {
+        DataSchemaNode ret = container.getDataChildByName( name );
+        if( ret == null ) {
+            for( final DataSchemaNode node : container.getChildNodes() ) {
+                if( (node instanceof ChoiceCaseNode) ) {
+                    final ChoiceCaseNode caseNode = ((ChoiceCaseNode) node);
+                    DataSchemaNode childByQName = ControllerContext.childByQName( caseNode, name );
+                    if( childByQName != null ) {
+                        return childByQName;
+                    }
+                }
+            }
+        }
+        return ret;
+    }
+
+    private String toUriString( final Object object ) throws UnsupportedEncodingException {
+        return object == null ? "" :
+                       URLEncoder.encode( object.toString(), ControllerContext.URI_ENCODING_CHAR_SET );
+    }
+
+    private InstanceIdWithSchemaNode collectPathArguments( final InstanceIdentifierBuilder builder,
+            final List<String> strings, final DataNodeContainer parentNode, final MountInstance mountPoint,
+            final boolean returnJustMountPoint ) {
+        Preconditions.<List<String>> checkNotNull( strings );
+
+        if( parentNode == null ) {
+            return null;
+        }
+
+        if( strings.isEmpty() ) {
+            return new InstanceIdWithSchemaNode( builder.toInstance(),
+                                                 ((DataSchemaNode) parentNode), mountPoint );
+        }
+
+        String head = strings.iterator().next();
+        final String nodeName = this.toNodeName( head );
+        final String moduleName = ControllerContext.toModuleName( head );
+
+        DataSchemaNode targetNode = null;
+        if( !Strings.isNullOrEmpty( moduleName ) ) {
+            if( Objects.equal( moduleName, ControllerContext.MOUNT_MODULE ) &&
+                Objects.equal( nodeName, ControllerContext.MOUNT_NODE ) ) {
+                if( mountPoint != null ) {
+                    throw new ResponseException( Status.BAD_REQUEST,
+                                         "Restconf supports just one mount point in URI." );
+                }
+
+                if( mountService == null ) {
+                    throw new ResponseException( Status.SERVICE_UNAVAILABLE,
+                                "MountService was not found. Finding behind mount points does not work." );
+                }
+
+                final InstanceIdentifier partialPath = builder.toInstance();
+                final MountInstance mount = mountService.getMountPoint( partialPath );
+                if( mount == null ) {
+                    LOG.debug( "Instance identifier to missing mount point: {}", partialPath );
+                    throw new ResponseException( Status.BAD_REQUEST,
+                                                 "Mount point does not exist." );
+                }
+
+                final SchemaContext mountPointSchema = mount.getSchemaContext();
+                if( mountPointSchema == null ) {
+                    throw new ResponseException( Status.BAD_REQUEST,
+                                       "Mount point does not contain any schema with modules." );
+                }
+
+                if( returnJustMountPoint ) {
+                    InstanceIdentifier instance = InstanceIdentifier.builder().toInstance();
+                    return new InstanceIdWithSchemaNode( instance, mountPointSchema, mount );
+                }
+
+                if( strings.size() == 1 ) {
+                    InstanceIdentifier instance = InstanceIdentifier.builder().toInstance();
+                    return new InstanceIdWithSchemaNode( instance, mountPointSchema, mount );
+                }
+
+                final String moduleNameBehindMountPoint = toModuleName(  strings.get( 1 ) );
+                if( moduleNameBehindMountPoint == null ) {
+                    throw new ResponseException( Status.BAD_REQUEST,
+                            "First node after mount point in URI has to be in format \"moduleName:nodeName\"" );
+                }
+
+                final Module moduleBehindMountPoint = this.getLatestModule( mountPointSchema,
+                                                                            moduleNameBehindMountPoint );
+                if( moduleBehindMountPoint == null ) {
+                    throw new ResponseException( Status.BAD_REQUEST,
+                                                 "URI has bad format. \"" + moduleName +
+                                                 "\" module does not exist in mount point." );
+                }
+
+                List<String> subList = strings.subList( 1, strings.size() );
+                return this.collectPathArguments( InstanceIdentifier.builder(), subList, moduleBehindMountPoint,
+                                                  mount, returnJustMountPoint );
+            }
+
+            Module module = null;
+            if( mountPoint == null ) {
+                module = this.getLatestModule( globalSchema, moduleName );
+                if( module == null ) {
+                    throw new ResponseException( Status.BAD_REQUEST,
+                            "URI has bad format. \"" + moduleName + "\" module does not exist." );
+                }
+            }
+            else {
+                SchemaContext schemaContext = mountPoint.getSchemaContext();
+                module = schemaContext == null ? null :
+                                          this.getLatestModule( schemaContext, moduleName );
+                if( module == null ) {
+                    throw new ResponseException( Status.BAD_REQUEST,
+                                        "URI has bad format. \"" + moduleName +
+                                        "\" module does not exist in mount point." );
+                }
+            }
+
+            targetNode = this.findInstanceDataChildByNameAndNamespace(
+                                          parentNode, nodeName, module.getNamespace() );;
+            if( targetNode == null ) {
+                throw new ResponseException( Status.BAD_REQUEST,
+                            "URI has bad format. Possible reasons:\n" +
+                            "1. \"" + head + "\" was not found in parent data node.\n" +
+                            "2. \"" + head + "\" is behind mount point. Then it should be in format \"/" +
+                            MOUNT + "/" + head + "\"." );
+            }
+        } else {
+            final List<DataSchemaNode> potentialSchemaNodes =
+                                          this.findInstanceDataChildrenByName( parentNode, nodeName );
+            if( potentialSchemaNodes.size() > 1 ) {
+                final StringBuilder strBuilder = new StringBuilder();
+                for( final DataSchemaNode potentialNodeSchema : potentialSchemaNodes ) {
+                    strBuilder.append( "   " )
+                              .append( potentialNodeSchema.getQName().getNamespace() )
+                              .append( "\n" );
+                }
+
+                throw new ResponseException( Status.BAD_REQUEST,
+                        "URI has bad format. Node \"" + nodeName +
+                        "\" is added as augment from more than one module. " +
+                        "Therefore the node must have module name and it has to be in format \"moduleName:nodeName\"." +
+                        "\nThe node is added as augment from modules with namespaces:\n" +
+                        strBuilder.toString() );
+            }
+
+            if( potentialSchemaNodes.isEmpty() ) {
+                throw new ResponseException( Status.BAD_REQUEST, "URI has bad format. \"" + nodeName +
+                                             "\" was not found in parent data node.\n" );
+            }
+
+            targetNode = potentialSchemaNodes.iterator().next();
+        }
+
+        if( !this.isListOrContainer( targetNode ) ) {
+            throw new ResponseException( Status.BAD_REQUEST,
+                                         "URI has bad format. Node \"" + head +
+                                         "\" must be Container or List yang type." );
+        }
+
+        int consumed = 1;
+        if( (targetNode instanceof ListSchemaNode) ) {
+            final ListSchemaNode listNode = ((ListSchemaNode) targetNode);
+            final int keysSize = listNode.getKeyDefinition().size();
+            if( (strings.size() - consumed) < keysSize ) {
+                throw new ResponseException( Status.BAD_REQUEST, "Missing key for list \"" +
+                                             listNode.getQName().getLocalName() + "\"." );
+            }
+
+            final List<String> uriKeyValues = strings.subList( consumed, consumed + keysSize );
+            final HashMap<QName, Object> keyValues = new HashMap<QName, Object>();
+            int i = 0;
+            for( final QName key : listNode.getKeyDefinition() ) {
+                {
+                    final String uriKeyValue = uriKeyValues.get( i );
+                    if( uriKeyValue.equals( NULL_VALUE ) ) {
+                        throw new ResponseException( Status.BAD_REQUEST,
+                                    "URI has bad format. List \"" + listNode.getQName().getLocalName() +
+                                    "\" cannot contain \"null\" value as a key." );
+                    }
+
+                    this.addKeyValue( keyValues, listNode.getDataChildByName( key ),
+                                      uriKeyValue, mountPoint );
+                    i++;
+                }
+            }
+
+            consumed = consumed + i;
+            builder.nodeWithKey( targetNode.getQName(), keyValues );
+        }
+        else {
+            builder.node( targetNode.getQName() );
+        }
+
+        if( (targetNode instanceof DataNodeContainer) ) {
+            final List<String> remaining = strings.subList( consumed, strings.size() );
+            return this.collectPathArguments( builder, remaining,
+                              ((DataNodeContainer) targetNode), mountPoint, returnJustMountPoint );
+        }
+
+        return new InstanceIdWithSchemaNode( builder.toInstance(), targetNode, mountPoint );
+    }
+
+    public DataSchemaNode findInstanceDataChildByNameAndNamespace( final DataNodeContainer container,
+            final String name, final URI namespace ) {
+        Preconditions.<URI> checkNotNull( namespace );
+
+        final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName( container, name );
+
+        Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
+            @Override
+            public boolean apply( DataSchemaNode node ) {
+                return Objects.equal( node.getQName().getNamespace(), namespace );
+            }
+        };
+
+        Iterable<DataSchemaNode> result = Iterables.filter( potentialSchemaNodes, filter );
+        return Iterables.getFirst( result, null );
+    }
+
+    public List<DataSchemaNode> findInstanceDataChildrenByName( final DataNodeContainer container,
+                                                                final String name ) {
+        Preconditions.<DataNodeContainer> checkNotNull( container );
+        Preconditions.<String> checkNotNull( name );
+
+        List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<DataSchemaNode>();
+        this.collectInstanceDataNodeContainers( instantiatedDataNodeContainers, container, name );
+        return instantiatedDataNodeContainers;
+    }
+
+    private void collectInstanceDataNodeContainers( final List<DataSchemaNode> potentialSchemaNodes,
+            final DataNodeContainer container, final String name ) {
+
+        Set<DataSchemaNode> childNodes = container.getChildNodes();
+
+        Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
+            @Override
+            public boolean apply( DataSchemaNode node ) {
+                return Objects.equal( node.getQName().getLocalName(), name );
+            }
+        };
+
+        Iterable<DataSchemaNode> nodes = Iterables.filter( childNodes, filter );
+
+        // Can't combine this loop with the filter above because the filter is lazily-applied
+        // by Iterables.filter.
+        for( final DataSchemaNode potentialNode : nodes ) {
+            if( this.isInstantiatedDataSchema( potentialNode ) ) {
+                potentialSchemaNodes.add( potentialNode );
+            }
+        }
+
+        Iterable<ChoiceNode> choiceNodes = Iterables.<ChoiceNode> filter( container.getChildNodes(),
+                                                                          ChoiceNode.class );
+
+        final Function<ChoiceNode, Set<ChoiceCaseNode>> choiceFunction =
+                new Function<ChoiceNode, Set<ChoiceCaseNode>>() {
+            @Override
+            public Set<ChoiceCaseNode> apply( final ChoiceNode node ) {
+                return node.getCases();
+            }
+        };
+
+        Iterable<Set<ChoiceCaseNode>> map = Iterables.<ChoiceNode, Set<ChoiceCaseNode>> transform(
+                                                                           choiceNodes, choiceFunction );
+
+        final Iterable<ChoiceCaseNode> allCases = Iterables.<ChoiceCaseNode> concat( map );
+        for( final ChoiceCaseNode caze : allCases ) {
+            this.collectInstanceDataNodeContainers( potentialSchemaNodes, caze, name );
+        }
+    }
+
+    public boolean isInstantiatedDataSchema( final DataSchemaNode node ) {
+        return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode ||
+               node instanceof ContainerSchemaNode || node instanceof ListSchemaNode;
+    }
+
+    private void addKeyValue( final HashMap<QName, Object> map, final DataSchemaNode node,
+                              final String uriValue, final MountInstance mountPoint ) {
+        Preconditions.<String> checkNotNull( uriValue );
+        Preconditions.checkArgument( (node instanceof LeafSchemaNode) );
+
+        final String urlDecoded = urlPathArgDecode( uriValue );
+        final TypeDefinition<? extends Object> typedef = ((LeafSchemaNode) node).getType();
+        Codec<Object, Object> codec = RestCodec.from( typedef, mountPoint );
+
+        Object decoded = codec == null ? null : codec.deserialize( urlDecoded );
+        String additionalInfo = "";
+        if( decoded == null ) {
+            TypeDefinition<? extends Object> baseType = RestUtil.resolveBaseTypeFrom( typedef );
+            if( (baseType instanceof IdentityrefTypeDefinition) ) {
+                decoded = this.toQName( urlDecoded );
+                additionalInfo = "For key which is of type identityref it should be in format module_name:identity_name.";
+            }
+        }
+
+        if( decoded == null ) {
+            throw new ResponseException( Status.BAD_REQUEST, uriValue + " from URI can\'t be resolved. " +
+                                         additionalInfo );
+        }
+
+        map.put( node.getQName(), decoded );
+    }
+
+    private static String toModuleName( final String str ) {
+        Preconditions.<String> checkNotNull( str );
+        if( str.contains( ":" ) ) {
+            final String[] args = str.split( ":" );
+            if( args.length == 2 ) {
+                return args[0];
+            }
+        }
+        return null;
+    }
+
+    private String toNodeName( final String str ) {
+        if( str.contains( ":" ) ) {
+            final String[] args = str.split( ":" );
+            if( args.length == 2 ) {
+                return args[1];
+            }
+        }
+        return str;
+    }
+
+    private QName toQName( final String name ) {
+        final String module = toModuleName( name );
+        final String node = this.toNodeName( name );
+        Set<Module> modules = globalSchema.getModules();
+
+        final Comparator<Module> comparator = new Comparator<Module>() {
+            @Override
+            public int compare( final Module o1, final Module o2 ) {
+                return o1.getRevision().compareTo( o2.getRevision() );
+            }
+        };
+
+        List<Module> sorted = new ArrayList<Module>( modules );
+        Collections.<Module> sort( new ArrayList<Module>( modules ), comparator );
+
+        final Function<Module, QName> transform = new Function<Module, QName>() {
+            @Override
+            public QName apply( final Module m ) {
+                return QName.create( m.getNamespace(), m.getRevision(), m.getName() );
+            }
+        };
+
+        final Predicate<QName> findFirst = new Predicate<QName>() {
+            @Override
+            public boolean apply( final QName qn ) {
+                return Objects.equal( module, qn.getLocalName() );
+            }
+        };
+
+        Optional<QName> namespace = FluentIterable.from( sorted )
+                                                  .transform( transform )
+                                                  .firstMatch( findFirst );
+        return namespace.isPresent() ? QName.create( namespace.get(), node ) : null;
+    }
+
+    private boolean isListOrContainer( final DataSchemaNode node ) {
+        return node instanceof ListSchemaNode || node instanceof ContainerSchemaNode;
+    }
+
+    public RpcDefinition getRpcDefinition( final String name ) {
+        final QName validName = this.toQName( name );
+        return validName == null ? null : this.qnameToRpc.get( validName );
+    }
+
+    @Override
+    public void onGlobalContextUpdated( final SchemaContext context ) {
+        if( context != null ) {
+            this.qnameToRpc.clear();
+            this.setGlobalSchema( context );
+            Set<RpcDefinition> _operations = context.getOperations();
+            for( final RpcDefinition operation : _operations ) {
+                {
+                    this.qnameToRpc.put( operation.getQName(), operation );
+                }
+            }
+        }
+    }
+
+    public List<String> urlPathArgsDecode( final List<String> strings ) {
+        try {
+            List<String> decodedPathArgs = new ArrayList<String>();
+            for( final String pathArg : strings ) {
+                String _decode = URLDecoder.decode( pathArg, URI_ENCODING_CHAR_SET );
+                decodedPathArgs.add( _decode );
+            }
+            return decodedPathArgs;
+        }
+        catch( UnsupportedEncodingException e ) {
+            throw new ResponseException( Status.BAD_REQUEST,
+                    "Invalid URL path '" + strings + "': " + e.getMessage() );
+        }
+    }
+
+    public String urlPathArgDecode( final String pathArg ) {
+        if( pathArg != null ) {
+            try {
+                return URLDecoder.decode( pathArg, URI_ENCODING_CHAR_SET );
+            }
+            catch( UnsupportedEncodingException e ) {
+                throw new ResponseException( Status.BAD_REQUEST,
+                        "Invalid URL path arg '" + pathArg + "': " + e.getMessage() );
+            }
+        }
+
+        return null;
+    }
+
+    private CharSequence convertToRestconfIdentifier( final PathArgument argument,
+                                                      final DataNodeContainer node ) {
+        if( argument instanceof NodeIdentifier && node instanceof ContainerSchemaNode ) {
+            return convertToRestconfIdentifier( (NodeIdentifier) argument, (ContainerSchemaNode) node );
+        }
+        else if( argument instanceof NodeIdentifierWithPredicates && node instanceof ListSchemaNode ) {
+            return convertToRestconfIdentifier( (NodeIdentifierWithPredicates) argument, (ListSchemaNode) node );
+        }
+        else if( argument != null && node != null ) {
+            throw new IllegalArgumentException(
+                                     "Conversion of generic path argument is not supported" );
+        }
+        else {
+            throw new IllegalArgumentException( "Unhandled parameter types: "
+                    + Arrays.<Object> asList( argument, node ).toString() );
+        }
+    }
+
+    private CharSequence convertToRestconfIdentifier( final NodeIdentifier argument,
+                                                      final ContainerSchemaNode node ) {
+        StringBuilder builder = new StringBuilder();
+        builder.append( "/" );
+        QName nodeType = argument.getNodeType();
+        builder.append( this.toRestconfIdentifier( nodeType ) );
+        return builder.toString();
+    }
+
+    private CharSequence convertToRestconfIdentifier( final NodeIdentifierWithPredicates argument,
+                                                      final ListSchemaNode node ) {
+        QName nodeType = argument.getNodeType();
+        final CharSequence nodeIdentifier = this.toRestconfIdentifier( nodeType );
+        final Map<QName, Object> keyValues = argument.getKeyValues();
+
+        StringBuilder builder = new StringBuilder();
+        builder.append( "/" );
+        builder.append( nodeIdentifier );
+        builder.append( "/" );
+
+        List<QName> keyDefinition = node.getKeyDefinition();
+        boolean hasElements = false;
+        for( final QName key : keyDefinition ) {
+            if( !hasElements ) {
+                hasElements = true;
+            }
+            else {
+                builder.append( "/" );
+            }
+
+            try {
+                builder.append( this.toUriString( keyValues.get( key ) ) );
+            } catch( UnsupportedEncodingException e ) {
+                LOG.error( "Error parsing URI: " + keyValues.get( key ), e );
+                return null;
+            }
+        }
+
+        return builder.toString();
+    }
+
+    private static DataSchemaNode childByQName( final Object container, final QName name ) {
+        if( container instanceof ChoiceCaseNode ) {
+            return childByQName( (ChoiceCaseNode) container, name );
+        }
+        else if( container instanceof ChoiceNode ) {
+            return childByQName( (ChoiceNode) container, name );
+        }
+        else if( container instanceof ContainerSchemaNode ) {
+            return childByQName( (ContainerSchemaNode) container, name );
+        }
+        else if( container instanceof ListSchemaNode ) {
+            return childByQName( (ListSchemaNode) container, name );
+        }
+        else if( container instanceof DataSchemaNode ) {
+            return childByQName( (DataSchemaNode) container, name );
+        }
+        else if( container instanceof Module ) {
+            return childByQName( (Module) container, name );
+        }
+        else {
+            throw new IllegalArgumentException( "Unhandled parameter types: "
+                    + Arrays.<Object> asList( container, name ).toString() );
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
deleted file mode 100644 (file)
index cb02fc8..0000000
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.restconf.impl
-
-import com.google.common.base.Preconditions
-import com.google.common.base.Splitter
-import com.google.common.collect.BiMap
-import com.google.common.collect.FluentIterable
-import com.google.common.collect.HashBiMap
-import com.google.common.collect.Lists
-import java.net.URI
-import java.net.URLDecoder
-import java.net.URLEncoder
-import java.util.ArrayList
-import java.util.HashMap
-import java.util.List
-import java.util.Map
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.controller.sal.core.api.mount.MountInstance
-import org.opendaylight.controller.sal.core.api.mount.MountService
-import org.opendaylight.controller.sal.rest.impl.RestUtil
-import org.opendaylight.controller.sal.rest.impl.RestconfProvider
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.Module
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
-import org.slf4j.LoggerFactory
-
-import static com.google.common.base.Preconditions.*
-import static javax.ws.rs.core.Response.Status.*
-
-class ControllerContext implements SchemaContextListener {
-    val static LOG = LoggerFactory.getLogger(ControllerContext)
-    val static ControllerContext INSTANCE = new ControllerContext
-    val static NULL_VALUE = "null"
-    val static MOUNT_MODULE = "yang-ext"
-    val static MOUNT_NODE = "mount"
-    public val static MOUNT = "yang-ext:mount"
-    val static URI_ENCODING_CHAR_SET = "ISO-8859-1"
-    val static URI_SLASH_PLACEHOLDER = "%2F";
-
-    @Property
-    var SchemaContext globalSchema;
-    
-    @Property
-    var MountService mountService;
-
-    private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
-    private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
-    private val Map<QName, RpcDefinition> qnameToRpc = new ConcurrentHashMap();
-
-    private new() {
-        if (INSTANCE !== null) {
-            throw new IllegalStateException("Already instantiated");
-        }
-    }
-
-    static def getInstance() {
-        return INSTANCE
-    }
-
-    private def void checkPreconditions() {
-        if (globalSchema === null) {
-            throw new ResponseException(SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
-        }
-    }
-
-    def setSchemas(SchemaContext schemas) {
-        onGlobalContextUpdated(schemas)
-    }
-
-    def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) {
-        return restconfInstance.toIdentifier(false)
-    }
-
-    def InstanceIdWithSchemaNode toMountPointIdentifier(String restconfInstance) {
-        return restconfInstance.toIdentifier(true)
-    }
-
-    private def InstanceIdWithSchemaNode toIdentifier(String restconfInstance, boolean toMountPointIdentifier) {
-        checkPreconditions
-        val encodedPathArgs = Lists.newArrayList(Splitter.on("/").split(restconfInstance))
-        val pathArgs = urlPathArgsDecode(encodedPathArgs)
-        pathArgs.omitFirstAndLastEmptyString
-        if (pathArgs.empty) {
-            return null;
-        }
-        val startModule = pathArgs.head.toModuleName();
-        if (startModule === null) {
-            throw new ResponseException(BAD_REQUEST, "First node in URI has to be in format \"moduleName:nodeName\"")
-        }
-        var InstanceIdWithSchemaNode iiWithSchemaNode = null;
-        if (toMountPointIdentifier) {
-            iiWithSchemaNode = collectPathArguments(InstanceIdentifier.builder(), pathArgs,
-            globalSchema.getLatestModule(startModule), null, true);
-        } else {
-            iiWithSchemaNode = collectPathArguments(InstanceIdentifier.builder(), pathArgs,
-            globalSchema.getLatestModule(startModule), null, false);
-        }
-        if (iiWithSchemaNode === null) {
-            throw new ResponseException(BAD_REQUEST, "URI has bad format")
-        }
-        return iiWithSchemaNode
-    }
-
-    private def omitFirstAndLastEmptyString(List<String> list) {
-        if (list.empty) {
-            return list;
-        }
-        if (list.head.empty) {
-            list.remove(0)
-        }
-        if (list.empty) {
-            return list;
-        }
-        if (list.last.empty) {
-            list.remove(list.indexOf(list.last))
-        }
-        return list;
-    }
-
-    private def getLatestModule(SchemaContext schema, String moduleName) {
-        checkArgument(schema !== null);
-        checkArgument(moduleName !== null && !moduleName.empty)
-        val modules = schema.modules.filter[m|m.name == moduleName]
-        return modules.filterLatestModule
-    }
-    
-    private def filterLatestModule(Iterable<Module> modules) {
-        var latestModule = modules.head
-        for (module : modules) {
-            if (module.revision.after(latestModule.revision)) {
-                latestModule = module
-            }
-        }
-        return latestModule
-    }
-    
-    def findModuleByName(String moduleName) {
-        checkPreconditions
-        checkArgument(moduleName !== null && !moduleName.empty)
-        return globalSchema.getLatestModule(moduleName)
-    }
-    
-    def findModuleByName(MountInstance mountPoint, String moduleName) {
-        checkArgument(moduleName !== null && mountPoint !== null)
-        val mountPointSchema = mountPoint.schemaContext;
-        return mountPointSchema?.getLatestModule(moduleName);
-    }
-    
-    def findModuleByNamespace(URI namespace) {
-        checkPreconditions
-        checkArgument(namespace !== null)
-        val moduleSchemas = globalSchema.findModuleByNamespace(namespace)
-        return moduleSchemas?.filterLatestModule
-    }
-    
-    def findModuleByNamespace(MountInstance mountPoint, URI namespace) {
-        checkArgument(namespace !== null && mountPoint !== null)
-        val mountPointSchema = mountPoint.schemaContext;
-        val moduleSchemas = mountPointSchema?.findModuleByNamespace(namespace)
-        return moduleSchemas?.filterLatestModule
-    }
-
-    def findModuleByNameAndRevision(QName module) {
-        checkPreconditions
-        checkArgument(module !== null && module.localName !== null && module.revision !== null)
-        return globalSchema.findModuleByName(module.localName, module.revision)
-    }
-
-    def findModuleByNameAndRevision(MountInstance mountPoint, QName module) {
-        checkPreconditions
-        checkArgument(module !== null && module.localName !== null && module.revision !== null && mountPoint !== null)
-        return mountPoint.schemaContext?.findModuleByName(module.localName, module.revision)
-    }
-
-    def getDataNodeContainerFor(InstanceIdentifier path) {
-        checkPreconditions
-        val elements = path.path;
-        val startQName = elements.head.nodeType;
-        val initialModule = globalSchema.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision)
-        var node = initialModule as DataNodeContainer;
-        for (element : elements) {
-            val potentialNode = node.childByQName(element.nodeType);
-            if (potentialNode === null || !potentialNode.listOrContainer) {
-                return null
-            }
-            node = potentialNode as DataNodeContainer
-        }
-        return node
-    }
-
-    def String toFullRestconfIdentifier(InstanceIdentifier path) {
-        checkPreconditions
-        val elements = path.path;
-        val ret = new StringBuilder();
-        val startQName = elements.head.nodeType;
-        val initialModule = globalSchema.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision)
-        var node = initialModule as DataNodeContainer;
-        for (element : elements) {
-            val potentialNode = node.childByQName(element.nodeType);
-            if (!potentialNode.listOrContainer) {
-                return null
-            }
-            node = potentialNode as DataNodeContainer
-            ret.append(element.convertToRestconfIdentifier(node));
-        }
-        return ret.toString
-    }
-
-    private def dispatch CharSequence convertToRestconfIdentifier(NodeIdentifier argument, ContainerSchemaNode node) {
-        '''/«argument.nodeType.toRestconfIdentifier()»'''
-    }
-
-    private def dispatch CharSequence convertToRestconfIdentifier(NodeIdentifierWithPredicates argument, ListSchemaNode node) {
-        val nodeIdentifier = argument.nodeType.toRestconfIdentifier();
-        val keyValues = argument.keyValues;
-        return '''/«nodeIdentifier»/«FOR key : node.keyDefinition SEPARATOR "/"»«keyValues.get(key).toUriString»«ENDFOR»'''
-    }
-
-    private def dispatch CharSequence convertToRestconfIdentifier(PathArgument argument, DataNodeContainer node) {
-        throw new IllegalArgumentException("Conversion of generic path argument is not supported");
-    }
-
-    def findModuleNameByNamespace(URI namespace) {
-        checkPreconditions
-        var moduleName = uriToModuleName.get(namespace)
-        if (moduleName === null) {
-            val module = findModuleByNamespace(namespace)
-            if (module === null) return null
-            moduleName = module.name
-            uriToModuleName.put(namespace, moduleName)
-        }
-        return moduleName
-    }
-    
-    def findModuleNameByNamespace(MountInstance mountPoint, URI namespace) {
-        val module = mountPoint.findModuleByNamespace(namespace);
-        return module?.name
-    }
-
-    def findNamespaceByModuleName(String moduleName) {
-        var namespace = moduleNameToUri.get(moduleName)
-        if (namespace === null) {
-            var module = findModuleByName(moduleName)
-            if(module === null) return null
-            namespace = module.namespace
-            uriToModuleName.put(namespace, moduleName)
-        }
-        return namespace
-    }
-    
-    def findNamespaceByModuleName(MountInstance mountPoint, String moduleName) {
-        val module = mountPoint.findModuleByName(moduleName)
-        return module?.namespace
-    }
-
-    def getAllModules(MountInstance mountPoint) {
-        checkPreconditions
-        return mountPoint?.schemaContext?.modules
-    }
-    
-    def getAllModules() {
-        checkPreconditions
-        return globalSchema.modules
-    }
-
-    def CharSequence toRestconfIdentifier(QName qname) {
-        checkPreconditions
-        var module = uriToModuleName.get(qname.namespace)
-        if (module === null) {
-            val moduleSchema = globalSchema.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
-            if(moduleSchema === null) return null
-            uriToModuleName.put(qname.namespace, moduleSchema.name)
-            module = moduleSchema.name;
-        }
-        return '''«module»:«qname.localName»''';
-    }
-
-    def CharSequence toRestconfIdentifier(MountInstance mountPoint, QName qname) {
-        val moduleSchema = mountPoint?.schemaContext.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
-        if(moduleSchema === null) return null
-        val module = moduleSchema.name;
-        return '''«module»:«qname.localName»''';
-    }
-
-    private static dispatch def DataSchemaNode childByQName(ChoiceNode container, QName name) {
-        for (caze : container.cases) {
-            val ret = caze.childByQName(name)
-            if (ret !== null) {
-                return ret;
-            }
-        }
-        return null;
-    }
-
-    private static dispatch def DataSchemaNode childByQName(ChoiceCaseNode container, QName name) {
-        val ret = container.getDataChildByName(name);
-        return ret;
-    }
-
-    private static dispatch def DataSchemaNode childByQName(ContainerSchemaNode container, QName name) {
-        return container.dataNodeChildByQName(name);
-    }
-
-    private static dispatch def DataSchemaNode childByQName(ListSchemaNode container, QName name) {
-        return container.dataNodeChildByQName(name);
-    }
-
-    private static dispatch def DataSchemaNode childByQName(Module container, QName name) {
-        return container.dataNodeChildByQName(name);
-    }
-
-    private static dispatch def DataSchemaNode childByQName(DataSchemaNode container, QName name) {
-        return null;
-    }
-
-    private static def DataSchemaNode dataNodeChildByQName(DataNodeContainer container, QName name) {
-        var ret = container.getDataChildByName(name);
-        if (ret === null) {
-
-            // Find in Choice Cases
-            for (node : container.childNodes) {
-                if (node instanceof ChoiceCaseNode) {
-                    val caseNode = (node as ChoiceCaseNode);
-                    ret = caseNode.childByQName(name);
-                    if (ret !== null) {
-                        return ret;
-                    }
-                }
-            }
-        }
-        return ret;
-    }
-
-    private def toUriString(Object object) {
-        if(object === null) return "";
-        return URLEncoder.encode(object.toString,URI_ENCODING_CHAR_SET)        
-    }
-    
-    private def InstanceIdWithSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
-        DataNodeContainer parentNode, MountInstance mountPoint, boolean returnJustMountPoint) {
-        checkNotNull(strings)
-        if (parentNode === null) {
-            return null;
-        }
-        if (strings.empty) {
-            return new InstanceIdWithSchemaNode(builder.toInstance, parentNode as DataSchemaNode, mountPoint)
-        }
-        
-        val nodeName = strings.head.toNodeName
-        val moduleName = strings.head.toModuleName
-        var DataSchemaNode targetNode = null
-        if (!moduleName.nullOrEmpty) {
-            // if it is mount point
-            if (moduleName == MOUNT_MODULE && nodeName == MOUNT_NODE) {
-                if (mountPoint !== null) {
-                    throw new ResponseException(BAD_REQUEST, "Restconf supports just one mount point in URI.")
-                }
-                
-                if (mountService === null) {
-                    throw new ResponseException(SERVICE_UNAVAILABLE, "MountService was not found. " 
-                        + "Finding behind mount points does not work."
-                    )
-                }
-                
-                val partialPath = builder.toInstance;
-                val mount = mountService.getMountPoint(partialPath)
-                if (mount === null) {
-                    LOG.debug("Instance identifier to missing mount point: {}", partialPath)
-                    throw new ResponseException(BAD_REQUEST, "Mount point does not exist.")
-                }
-                
-                val mountPointSchema = mount.schemaContext;
-                if (mountPointSchema === null) {
-                    throw new ResponseException(BAD_REQUEST, "Mount point does not contain any schema with modules.")
-                }
-                
-                if (returnJustMountPoint) {
-                    return new InstanceIdWithSchemaNode(InstanceIdentifier.builder().toInstance, mountPointSchema, mount)
-                }
-                
-                if (strings.size == 1) { // any data node is not behind mount point
-                    return new InstanceIdWithSchemaNode(InstanceIdentifier.builder().toInstance, mountPointSchema, mount)
-                }
-                
-                val moduleNameBehindMountPoint = strings.get(1).toModuleName()
-                if (moduleNameBehindMountPoint === null) {
-                    throw new ResponseException(BAD_REQUEST,
-                        "First node after mount point in URI has to be in format \"moduleName:nodeName\"")
-                }
-                
-                val moduleBehindMountPoint = mountPointSchema.getLatestModule(moduleNameBehindMountPoint)
-                if (moduleBehindMountPoint === null) {
-                    throw new ResponseException(BAD_REQUEST,
-                        "URI has bad format. \"" + moduleName + "\" module does not exist in mount point.")
-                }
-                
-                return collectPathArguments(InstanceIdentifier.builder(), strings.subList(1, strings.size),
-                    moduleBehindMountPoint, mount, returnJustMountPoint);
-            }
-            
-            var Module module = null;
-            if (mountPoint === null) {
-                module = globalSchema.getLatestModule(moduleName)
-                if (module === null) {
-                    throw new ResponseException(BAD_REQUEST,
-                        "URI has bad format. \"" + moduleName + "\" module does not exist.")
-                }
-            } else {
-                module = mountPoint.schemaContext?.getLatestModule(moduleName)
-                if (module === null) {
-                    throw new ResponseException(BAD_REQUEST,
-                        "URI has bad format. \"" + moduleName + "\" module does not exist in mount point.")
-                }
-            }
-            targetNode = parentNode.findInstanceDataChildByNameAndNamespace(nodeName, module.namespace)
-            if (targetNode === null) {
-                throw new ResponseException(BAD_REQUEST, "URI has bad format. Possible reasons:\n" + 
-                    "1. \"" + strings.head + "\" was not found in parent data node.\n" + 
-                    "2. \"" + strings.head + "\" is behind mount point. Then it should be in format \"/" + MOUNT + "/" + strings.head + "\".")
-            }
-        } else { // string without module name
-            val potentialSchemaNodes = parentNode.findInstanceDataChildrenByName(nodeName)
-            if (potentialSchemaNodes.size > 1) {
-                val StringBuilder namespacesOfPotentialModules = new StringBuilder;
-                for (potentialNodeSchema : potentialSchemaNodes) {
-                    namespacesOfPotentialModules.append("   ").append(potentialNodeSchema.QName.namespace.toString).append("\n")
-                }
-                throw new ResponseException(BAD_REQUEST, "URI has bad format. Node \"" + nodeName + "\" is added as augment from more than one module. " 
-                        + "Therefore the node must have module name and it has to be in format \"moduleName:nodeName\"."
-                        + "\nThe node is added as augment from modules with namespaces:\n" + namespacesOfPotentialModules)
-            }
-            targetNode = potentialSchemaNodes.head
-            if (targetNode === null) {
-                throw new ResponseException(BAD_REQUEST, "URI has bad format. \"" + nodeName + "\" was not found in parent data node.\n")
-            }
-        }
-        
-        if (!targetNode.isListOrContainer) {
-            throw new ResponseException(BAD_REQUEST,"URI has bad format. Node \"" + strings.head + "\" must be Container or List yang type.")
-        }
-        // Number of consumed elements
-        var consumed = 1;
-        if (targetNode instanceof ListSchemaNode) {
-            val listNode = targetNode as ListSchemaNode;
-            val keysSize = listNode.keyDefinition.size
-
-            // every key has to be filled
-            if ((strings.length - consumed) < keysSize) {
-                throw new ResponseException(BAD_REQUEST,"Missing key for list \"" + listNode.QName.localName + "\".")
-            }
-            val uriKeyValues = strings.subList(consumed, consumed + keysSize);
-            val keyValues = new HashMap<QName, Object>();
-            var i = 0;
-            for (key : listNode.keyDefinition) {
-                val uriKeyValue = uriKeyValues.get(i);
-
-                // key value cannot be NULL
-                if (uriKeyValue.equals(NULL_VALUE)) {
-                    throw new ResponseException(BAD_REQUEST, "URI has bad format. List \"" + listNode.QName.localName 
-                        + "\" cannot contain \"null\" value as a key."
-                    )
-                }
-                keyValues.addKeyValue(listNode.getDataChildByName(key), uriKeyValue, mountPoint);
-                i = i + 1;
-            }
-            consumed = consumed + i;
-            builder.nodeWithKey(targetNode.QName, keyValues);
-        } else {
-
-            // Only one instance of node is allowed
-            builder.node(targetNode.QName);
-        }
-        if (targetNode instanceof DataNodeContainer) {
-            val remaining = strings.subList(consumed, strings.length);
-            val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer, mountPoint, returnJustMountPoint);
-            return result
-        }
-
-        return new InstanceIdWithSchemaNode(builder.toInstance, targetNode, mountPoint)
-    }
-
-    def DataSchemaNode findInstanceDataChildByNameAndNamespace(DataNodeContainer container,
-        String name, URI namespace) {
-        Preconditions.checkNotNull(namespace)
-        val potentialSchemaNodes = container.findInstanceDataChildrenByName(name)
-        return potentialSchemaNodes.filter[n|n.QName.namespace == namespace].head
-    }
-    
-    def List<DataSchemaNode> findInstanceDataChildrenByName(DataNodeContainer container, String name) {
-        Preconditions.checkNotNull(container)
-        Preconditions.checkNotNull(name)
-        val instantiatedDataNodeContainers = new ArrayList
-        instantiatedDataNodeContainers.collectInstanceDataNodeContainers(container, name)
-        return instantiatedDataNodeContainers
-    }
-    
-    private def void collectInstanceDataNodeContainers(List<DataSchemaNode> potentialSchemaNodes, DataNodeContainer container,
-        String name) {
-        val nodes = container.childNodes.filter[n|n.QName.localName == name]
-        for (potentialNode : nodes) {
-            if (potentialNode.isInstantiatedDataSchema) {
-                potentialSchemaNodes.add(potentialNode)
-            }
-        }
-        val allCases = container.childNodes.filter(ChoiceNode).map[cases].flatten
-        for (caze : allCases) {
-            collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name)
-        }
-    }
-    
-    def boolean isInstantiatedDataSchema(DataSchemaNode node) {
-        switch node {
-            LeafSchemaNode: return true
-            LeafListSchemaNode: return true
-            ContainerSchemaNode: return true
-            ListSchemaNode: return true
-            default: return false
-        }
-    }
-    
-    private def void addKeyValue(HashMap<QName, Object> map, DataSchemaNode node, String uriValue, MountInstance mountPoint) {
-        checkNotNull(uriValue);
-        checkArgument(node instanceof LeafSchemaNode);
-        val urlDecoded = URLDecoder.decode(uriValue);
-        val typedef = (node as LeafSchemaNode).type;
-        
-        var decoded = RestCodec.from(typedef, mountPoint)?.deserialize(urlDecoded)
-        var additionalInfo = ""
-        if(decoded === null) {
-            var baseType = RestUtil.resolveBaseTypeFrom(typedef)
-            if(baseType instanceof IdentityrefTypeDefinition) {
-                decoded = toQName(urlDecoded)
-                additionalInfo = "For key which is of type identityref it should be in format module_name:identity_name."
-            }
-        }
-        if (decoded === null) {
-            throw new ResponseException(BAD_REQUEST, uriValue + " from URI can't be resolved. "+  additionalInfo )
-        }                
-        
-        map.put(node.QName, decoded);
-    }
-
-    private static def String toModuleName(String str) {
-        checkNotNull(str)
-        if (str.contains(":")) {
-            val args = str.split(":");
-            if (args.size === 2) {
-                return args.get(0);
-            }
-        }
-        return null;
-    }
-
-    private def String toNodeName(String str) {
-        if (str.contains(":")) {
-            val args = str.split(":");
-            if (args.size === 2) {
-                return args.get(1);
-            }
-        }
-        return str;
-    }
-
-    private def QName toQName(String name) {
-        val module = name.toModuleName;
-        val node = name.toNodeName;
-        val namespace = FluentIterable.from(globalSchema.modules.sort[o1,o2 | o1.revision.compareTo(o2.revision)])
-            .transform[QName.create(namespace,revision,it.name)].findFirst[module == localName]
-        if (namespace === null) {
-            return null
-        }
-        return QName.create(namespace, node);
-    }
-
-    private def boolean isListOrContainer(DataSchemaNode node) {
-        return ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode))
-    }
-
-    def getRpcDefinition(String name) {
-        val validName = name.toQName
-        if (validName === null) {
-            return null
-        }
-        return qnameToRpc.get(validName)
-    }
-
-    override onGlobalContextUpdated(SchemaContext context) {
-        if (context !== null) {
-            qnameToRpc.clear
-            this.globalSchema = context;
-            for (operation : context.operations) {
-                val qname = operation.QName;
-                qnameToRpc.put(qname, operation);
-            }
-        }
-    }
-
-
-    def urlPathArgsDecode(List<String> strings) {
-        val List<String> decodedPathArgs = new ArrayList();
-        for (pathArg : strings) {
-            decodedPathArgs.add(URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET))
-        }
-        return decodedPathArgs
-    }
-
-    def urlPathArgDecode(String pathArg) {
-        if (pathArg !== null) {
-            return URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET)
-        }
-        return null
-    }    
-
-}
index b08126b5de96b3063b0f8d187a45aca294cab156..007fb8eabfd97ee39cf8214abb7d22f8da3be93b 100644 (file)
@@ -19,4 +19,9 @@ public class ResponseException extends WebApplicationException {
     public ResponseException(Status status, String msg) {
         super(Response.status(status).type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
     }
+
+    public ResponseException(Throwable cause, String msg) {
+        super(cause, Response.status(Status.INTERNAL_SERVER_ERROR).
+                                         type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
+    }
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
new file mode 100644 (file)
index 0000000..0b7b693
--- /dev/null
@@ -0,0 +1,1161 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
+import org.opendaylight.controller.sal.streams.listeners.Notificator;
+import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.EmptyType;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+@SuppressWarnings("all")
+public class RestconfImpl implements RestconfService {
+    private final static RestconfImpl INSTANCE = new RestconfImpl();
+
+    private final static String MOUNT_POINT_MODULE_NAME = "ietf-netconf";
+
+    private final static SimpleDateFormat REVISION_FORMAT =  new SimpleDateFormat("yyyy-MM-dd");
+
+    private final static String RESTCONF_MODULE_DRAFT02_REVISION = "2013-10-19";
+
+    private final static String RESTCONF_MODULE_DRAFT02_NAME = "ietf-restconf";
+
+    private final static String RESTCONF_MODULE_DRAFT02_NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf";
+
+    private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE = "restconf";
+
+    private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf";
+
+    private final static String RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules";
+
+    private final static String RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module";
+
+    private final static String RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams";
+
+    private final static String RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream";
+
+    private final static String RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations";
+
+    private final static String SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote";
+
+    private final static String SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription";
+
+    private BrokerFacade broker;
+
+    private ControllerContext controllerContext;
+
+    public void setBroker(final BrokerFacade broker) {
+        this.broker = broker;
+    }
+
+    public void setControllerContext(final ControllerContext controllerContext) {
+        this.controllerContext = controllerContext;
+    }
+
+    private RestconfImpl() {
+    }
+
+    public static RestconfImpl getInstance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public StructuredData getModules() {
+        final Module restconfModule = this.getRestconfModule();
+
+        final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
+        final DataSchemaNode moduleSchemaNode =
+                this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+
+        Set<Module> allModules = this.controllerContext.getAllModules();
+        for (final Module module : allModules) {
+            CompositeNode moduleCompositeNode = this.toModuleCompositeNode(module, moduleSchemaNode);
+            modulesAsData.add(moduleCompositeNode);
+        }
+
+        final DataSchemaNode modulesSchemaNode =
+                this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+        QName qName = modulesSchemaNode.getQName();
+        final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
+        return new StructuredData(modulesNode, modulesSchemaNode, null);
+    }
+
+    @Override
+    public StructuredData getAvailableStreams() {
+        Set<String> availableStreams = Notificator.getStreamNames();
+
+        final List<Node<?>> streamsAsData = new ArrayList<Node<?>>();
+        Module restconfModule = this.getRestconfModule();
+        final DataSchemaNode streamSchemaNode =
+            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
+        for (final String streamName : availableStreams) {
+            streamsAsData.add(this.toStreamCompositeNode(streamName, streamSchemaNode));
+        }
+
+        final DataSchemaNode streamsSchemaNode =
+            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
+        QName qName = streamsSchemaNode.getQName();
+        final CompositeNode streamsNode = NodeFactory.createImmutableCompositeNode(qName, null, streamsAsData);
+        return new StructuredData(streamsNode, streamsSchemaNode, null);
+    }
+
+    @Override
+    public StructuredData getModules(final String identifier) {
+        Set<Module> modules = null;
+        MountInstance mountPoint = null;
+        if (identifier.contains(ControllerContext.MOUNT)) {
+            InstanceIdWithSchemaNode mountPointIdentifier =
+                                           this.controllerContext.toMountPointIdentifier(identifier);
+            mountPoint = mountPointIdentifier.getMountPoint();
+            modules = this.controllerContext.getAllModules(mountPoint);
+        }
+        else {
+            throw new ResponseException(Status.BAD_REQUEST,
+                "URI has bad format. If modules behind mount point should be showed, URI has to end with " +
+                ControllerContext.MOUNT);
+        }
+
+        final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
+        Module restconfModule = this.getRestconfModule();
+        final DataSchemaNode moduleSchemaNode =
+            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+
+        for (final Module module : modules) {
+            modulesAsData.add(this.toModuleCompositeNode(module, moduleSchemaNode));
+        }
+
+        final DataSchemaNode modulesSchemaNode =
+            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+        QName qName = modulesSchemaNode.getQName();
+        final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
+        return new StructuredData(modulesNode, modulesSchemaNode, mountPoint);
+    }
+
+    @Override
+    public StructuredData getModule(final String identifier) {
+        final QName moduleNameAndRevision = this.getModuleNameAndRevision(identifier);
+        Module module = null;
+        MountInstance mountPoint = null;
+        if (identifier.contains(ControllerContext.MOUNT)) {
+            InstanceIdWithSchemaNode mountPointIdentifier =
+                                            this.controllerContext.toMountPointIdentifier(identifier);
+            mountPoint = mountPointIdentifier.getMountPoint();
+            module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision);
+        }
+        else {
+            module = this.controllerContext.findModuleByNameAndRevision(moduleNameAndRevision);
+        }
+
+        if (module == null) {
+            throw new ResponseException(Status.BAD_REQUEST,
+                    "Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '" +
+                    moduleNameAndRevision.getRevision() + "' was not found.");
+        }
+
+        Module restconfModule = this.getRestconfModule();
+        final DataSchemaNode moduleSchemaNode =
+            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+        final CompositeNode moduleNode = this.toModuleCompositeNode(module, moduleSchemaNode);
+        return new StructuredData(moduleNode, moduleSchemaNode, mountPoint);
+    }
+
+    @Override
+    public StructuredData getOperations() {
+        Set<Module> allModules = this.controllerContext.getAllModules();
+        return this.operationsFromModulesToStructuredData(allModules, null);
+    }
+
+    @Override
+    public StructuredData getOperations(final String identifier) {
+        Set<Module> modules = null;
+        MountInstance mountPoint = null;
+        if (identifier.contains(ControllerContext.MOUNT)) {
+            InstanceIdWithSchemaNode mountPointIdentifier =
+                                         this.controllerContext.toMountPointIdentifier(identifier);
+            mountPoint = mountPointIdentifier.getMountPoint();
+            modules = this.controllerContext.getAllModules(mountPoint);
+        }
+        else {
+            throw new ResponseException(Status.BAD_REQUEST,
+                "URI has bad format. If operations behind mount point should be showed, URI has to end with " +
+            ControllerContext.MOUNT);
+        }
+
+        return this.operationsFromModulesToStructuredData(modules, mountPoint);
+    }
+
+    private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
+                                                                 final MountInstance mountPoint) {
+        final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
+        Module restconfModule = this.getRestconfModule();
+        final DataSchemaNode operationsSchemaNode =
+            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
+        QName qName = operationsSchemaNode.getQName();
+        SchemaPath path = operationsSchemaNode.getPath();
+        ContainerSchemaNodeBuilder containerSchemaNodeBuilder =
+                             new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, qName, path);
+        final ContainerSchemaNodeBuilder fakeOperationsSchemaNode = containerSchemaNodeBuilder;
+        for (final Module module : modules) {
+            Set<RpcDefinition> rpcs = module.getRpcs();
+            for (final RpcDefinition rpc : rpcs) {
+                QName rpcQName = rpc.getQName();
+                SimpleNode<Object> immutableSimpleNode =
+                                     NodeFactory.<Object>createImmutableSimpleNode(rpcQName, null, null);
+                operationsAsData.add(immutableSimpleNode);
+
+                String name = module.getName();
+                LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName, null);
+                final LeafSchemaNodeBuilder fakeRpcSchemaNode = leafSchemaNodeBuilder;
+                fakeRpcSchemaNode.setAugmenting(true);
+
+                EmptyType instance = EmptyType.getInstance();
+                fakeRpcSchemaNode.setType(instance);
+                fakeOperationsSchemaNode.addChildNode(fakeRpcSchemaNode.build());
+            }
+        }
+
+        final CompositeNode operationsNode =
+                                  NodeFactory.createImmutableCompositeNode(qName, null, operationsAsData);
+        ContainerSchemaNode schemaNode = fakeOperationsSchemaNode.build();
+        return new StructuredData(operationsNode, schemaNode, mountPoint);
+    }
+
+    private Module getRestconfModule() {
+        QName qName = QName.create(RESTCONF_MODULE_DRAFT02_NAMESPACE, RESTCONF_MODULE_DRAFT02_REVISION,
+                                   RESTCONF_MODULE_DRAFT02_NAME);
+        final Module restconfModule = this.controllerContext.findModuleByNameAndRevision(qName);
+        if (restconfModule == null) {
+            throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Restconf module was not found.");
+        }
+
+        return restconfModule;
+    }
+
+    private QName getModuleNameAndRevision(final String identifier) {
+        final int mountIndex = identifier.indexOf(ControllerContext.MOUNT);
+        String moduleNameAndRevision = "";
+        if (mountIndex >= 0) {
+            moduleNameAndRevision = identifier.substring(mountIndex + ControllerContext.MOUNT.length());
+        }
+        else {
+            moduleNameAndRevision = identifier;
+        }
+
+        Splitter splitter = Splitter.on("/").omitEmptyStrings();
+        Iterable<String> split = splitter.split(moduleNameAndRevision);
+        final List<String> pathArgs = Lists.<String>newArrayList(split);
+        if (pathArgs.size() < 2) {
+            throw new ResponseException(Status.BAD_REQUEST,
+                    "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'");
+        }
+
+        try {
+            final String moduleName = pathArgs.get( 0 );
+            String revision = pathArgs.get(1);
+            final Date moduleRevision = REVISION_FORMAT.parse(revision);
+            return QName.create(null, moduleRevision, moduleName);
+        }
+        catch (ParseException e) {
+            throw new ResponseException(Status.BAD_REQUEST, "URI has bad format. It should be \'moduleName/yyyy-MM-dd\'");
+        }
+    }
+
+    private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
+        final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
+        List<DataSchemaNode> instanceDataChildrenByName =
+                this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) streamSchemaNode),
+                                                                       "name");
+        final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(), null,
+                                                                           streamName));
+
+        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+                                                 ((DataNodeContainer) streamSchemaNode), "description");
+        final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
+                                                                           "DESCRIPTION_PLACEHOLDER"));
+
+        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+                                               ((DataNodeContainer) streamSchemaNode), "replay-support");
+        final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        streamNodeValues.add(NodeFactory.<Boolean>createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
+                                                                            Boolean.valueOf(true)));
+
+        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+                                           ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
+        final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
+                                                                           null, ""));
+
+        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+                                                        ((DataNodeContainer) streamSchemaNode), "events");
+        final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(eventsSchemaNode.getQName(),
+                                                                           null, ""));
+
+        return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
+    }
+
+    private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
+        final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
+        List<DataSchemaNode> instanceDataChildrenByName =
+            this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) moduleSchemaNode), "name");
+        final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(),
+                                                                           null, module.getName()));
+
+        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+                                                          ((DataNodeContainer) moduleSchemaNode), "revision");
+        final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        Date _revision = module.getRevision();
+        moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
+                                                                           REVISION_FORMAT.format(_revision)));
+
+        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+                                                        ((DataNodeContainer) moduleSchemaNode), "namespace");
+        final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
+                                                                           module.getNamespace().toString()));
+
+        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+                                                           ((DataNodeContainer) moduleSchemaNode), "feature");
+        final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        for (final FeatureDefinition feature : module.getFeatures()) {
+            moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(featureSchemaNode.getQName(), null,
+                                                                               feature.getQName().getLocalName()));
+        }
+
+        return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.getQName(), null, moduleNodeValues);
+    }
+
+    private DataSchemaNode getSchemaNode(final Module restconfModule, final String schemaNodeName) {
+        Set<GroupingDefinition> groupings = restconfModule.getGroupings();
+
+        final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
+            @Override
+            public boolean apply(final GroupingDefinition g) {
+                return Objects.equal(g.getQName().getLocalName(),
+                                     RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE);
+            }
+        };
+
+        Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
+
+        final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
+
+        List<DataSchemaNode> instanceDataChildrenByName =
+                this.controllerContext.findInstanceDataChildrenByName(restconfGrouping,
+                                                            RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE);
+        final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
+
+        if (Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                    RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                   RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                   RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
+            final DataSchemaNode modules = Iterables.getFirst(instances, null);
+            instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+                                                               RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                         RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                         RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+            final DataSchemaNode modules = Iterables.getFirst(instances, null);
+            instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+                                                                 RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+
+        return null;
+    }
+
+    @Override
+    public Object getRoot() {
+        return null;
+    }
+
+    @Override
+    public StructuredData invokeRpc(final String identifier, final CompositeNode payload) {
+        final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
+        if (Objects.equal(rpc.getQName().getNamespace().toString(), SAL_REMOTE_NAMESPACE) &&
+            Objects.equal(rpc.getQName().getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
+
+            final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
+            final SimpleNode<? extends Object> pathNode = value == null ? null :
+                                   value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
+            final Object pathValue = pathNode == null ? null : pathNode.getValue();
+
+            if (!(pathValue instanceof InstanceIdentifier)) {
+                throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+                                             "Instance identifier was not normalized correctly.");
+            }
+
+            final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
+            String streamName = null;
+            if (!Iterables.isEmpty(pathIdentifier.getPath())) {
+                String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
+                streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
+            }
+
+            if (Strings.isNullOrEmpty(streamName)) {
+                throw new ResponseException(Status.BAD_REQUEST,
+                         "Path is empty or contains data node which is not Container or List build-in type.");
+            }
+
+            final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
+                                 QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
+            final List<Node<?>> output = new ArrayList<Node<?>>();
+            output.add(streamNameNode);
+
+            final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
+                                                  rpc.getOutput().getQName(), null, output, null, null);
+
+            if (!Notificator.existListenerFor(pathIdentifier)) {
+                Notificator.createListener(pathIdentifier, streamName);
+            }
+
+            return new StructuredData(responseData, rpc.getOutput(), null);
+        }
+
+        RpcDefinition rpcDefinition = this.controllerContext.getRpcDefinition(identifier);
+        return this.callRpc(rpcDefinition, payload);
+    }
+
+    @Override
+    public StructuredData invokeRpc(final String identifier, final String noPayload) {
+        if (!Strings.isNullOrEmpty(noPayload)) {
+            throw new ResponseException(Status.UNSUPPORTED_MEDIA_TYPE,
+                                                       "Content-Type contains unsupported Media Type.");
+        }
+
+        final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
+        return this.callRpc(rpc, null);
+    }
+
+    private RpcDefinition resolveIdentifierInInvokeRpc(final String identifier) {
+        if (identifier.indexOf("/") < 0) {
+            final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifier);
+            final RpcDefinition rpc = this.controllerContext.getRpcDefinition(identifierDecoded);
+            if (rpc != null) {
+                return rpc;
+            }
+
+            throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
+        }
+
+        final String slashErrorMsg = String.format(
+                "Identifier %n%s%ncan\'t contain slash character (/).%nIf slash is part of identifier name then use %%2F placeholder.",
+                identifier);
+
+        throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
+    }
+
+    private StructuredData callRpc(final RpcDefinition rpc, final CompositeNode payload) {
+        if (rpc == null) {
+            throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
+        }
+
+        CompositeNode rpcRequest = null;
+        if (payload == null) {
+            rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, null, null, null);
+        }
+        else {
+            final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
+            final List<Node<?>> input = new ArrayList<Node<?>>();
+            input.add(value);
+
+            rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, input, null, null);
+        }
+
+        final RpcResult<CompositeNode> rpcResult = broker.invokeRpc(rpc.getQName(), rpcRequest);
+
+        if (!rpcResult.isSuccessful()) {
+            throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Operation failed");
+        }
+
+        CompositeNode result = rpcResult.getResult();
+        if (result == null) {
+            return null;
+        }
+
+        return new StructuredData(result, rpc.getOutput(), null);
+    }
+
+    @Override
+    public StructuredData readConfigurationData(final String identifier) {
+        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+        CompositeNode data = null;
+        MountInstance mountPoint = iiWithData.getMountPoint();
+        if (mountPoint != null) {
+            data = broker.readConfigurationDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
+        }
+        else {
+            data = broker.readConfigurationData(iiWithData.getInstanceIdentifier());
+        }
+
+        return new StructuredData(data, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
+    }
+
+    @Override
+    public StructuredData readOperationalData(final String identifier) {
+        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+        CompositeNode data = null;
+        MountInstance mountPoint = iiWithData.getMountPoint();
+        if (mountPoint != null) {
+            data = broker.readOperationalDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
+        }
+        else {
+            data = broker.readOperationalData(iiWithData.getInstanceIdentifier());
+        }
+
+        return new StructuredData(data, iiWithData.getSchemaNode(), mountPoint);
+    }
+
+    @Override
+    public Response updateConfigurationData(final String identifier, final CompositeNode payload) {
+        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+        MountInstance mountPoint = iiWithData.getMountPoint();
+        final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint);
+        RpcResult<TransactionStatus> status = null;
+
+        try {
+            if (mountPoint != null) {
+                status = broker.commitConfigurationDataPutBehindMountPoint(
+                                                mountPoint, iiWithData.getInstanceIdentifier(), value).get();
+            } else {
+                status = broker.commitConfigurationDataPut(iiWithData.getInstanceIdentifier(), value).get();
+            }
+        }
+        catch( Exception e ) {
+            throw new ResponseException( e, "Error updating data" );
+        }
+
+        if( status.getResult() == TransactionStatus.COMMITED )
+            return Response.status(Status.OK).build();
+
+        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+    }
+
+    @Override
+    public Response createConfigurationData(final String identifier, final CompositeNode payload) {
+        URI payloadNS = this.namespace(payload);
+        if (payloadNS == null) {
+            throw new ResponseException(Status.BAD_REQUEST,
+                    "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
+        }
+
+        InstanceIdWithSchemaNode iiWithData = null;
+        CompositeNode value = null;
+        if (this.representsMountPointRootData(payload)) {
+             // payload represents mount point data and URI represents path to the mount point
+
+            if (this.endsWithMountPoint(identifier)) {
+                throw new ResponseException(Status.BAD_REQUEST,
+                            "URI has bad format. URI should be without \"" + ControllerContext.MOUNT +
+                            "\" for POST operation.");
+            }
+
+            final String completeIdentifier = this.addMountPointIdentifier(identifier);
+            iiWithData = this.controllerContext.toInstanceIdentifier(completeIdentifier);
+
+            value = this.normalizeNode(payload, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
+        }
+        else {
+            final InstanceIdWithSchemaNode incompleteInstIdWithData =
+                                               this.controllerContext.toInstanceIdentifier(identifier);
+            final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
+            MountInstance mountPoint = incompleteInstIdWithData.getMountPoint();
+            final Module module = this.findModule(mountPoint, payload);
+            if (module == null) {
+                throw new ResponseException(Status.BAD_REQUEST,
+                                            "Module was not found for \"" + payloadNS + "\"");
+            }
+
+            String payloadName = this.getName(payload);
+            final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+                                                              parentSchema, payloadName, module.getNamespace());
+            value = this.normalizeNode(payload, schemaNode, mountPoint);
+
+            iiWithData = this.addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
+        }
+
+        RpcResult<TransactionStatus> status = null;
+        MountInstance mountPoint = iiWithData.getMountPoint();
+        try {
+            if (mountPoint != null) {
+                Future<RpcResult<TransactionStatus>> future =
+                                          broker.commitConfigurationDataPostBehindMountPoint(
+                                                       mountPoint, iiWithData.getInstanceIdentifier(), value);
+                status = future == null ? null : future.get();
+            }
+            else {
+                Future<RpcResult<TransactionStatus>> future =
+                               broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
+                status = future == null ? null : future.get();
+            }
+        }
+        catch( ResponseException e) { throw e; }
+        catch( Exception e ) {
+            throw new ResponseException( e, "Error creating data" );
+        }
+
+        if (status == null) {
+            return Response.status(Status.ACCEPTED).build();
+        }
+
+        if( status.getResult() == TransactionStatus.COMMITED )
+            return Response.status(Status.NO_CONTENT).build();
+
+        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+    }
+
+    @Override
+    public Response createConfigurationData(final CompositeNode payload) {
+        URI payloadNS = this.namespace(payload);
+        if (payloadNS == null) {
+            throw new ResponseException(Status.BAD_REQUEST,
+                    "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
+        }
+
+        final Module module = this.findModule(null, payload);
+        if (module == null) {
+            throw new ResponseException(Status.BAD_REQUEST,
+                    "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
+        }
+
+        String payloadName = this.getName(payload);
+        final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+                                                                   module, payloadName, module.getNamespace());
+        final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
+        final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
+        RpcResult<TransactionStatus> status = null;
+        MountInstance mountPoint = iiWithData.getMountPoint();
+
+        try {
+            if (mountPoint != null) {
+                Future<RpcResult<TransactionStatus>> future =
+                                             broker.commitConfigurationDataPostBehindMountPoint(
+                                                          mountPoint, iiWithData.getInstanceIdentifier(), value);
+                status = future == null ? null : future.get();
+            }
+            else {
+                Future<RpcResult<TransactionStatus>> future =
+                                 broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
+                status = future == null ? null : future.get();
+            }
+        }
+        catch( ResponseException e) { throw e; }
+        catch( Exception e ) {
+            throw new ResponseException( e, "Error creating data" );
+        }
+
+        if (status == null) {
+            return Response.status(Status.ACCEPTED).build();
+        }
+
+        if( status.getResult() == TransactionStatus.COMMITED )
+            return Response.status(Status.NO_CONTENT).build();
+
+        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+    }
+
+    @Override
+    public Response deleteConfigurationData(final String identifier) {
+        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+        RpcResult<TransactionStatus> status = null;
+        MountInstance mountPoint = iiWithData.getMountPoint();
+
+        try {
+            if (mountPoint != null) {
+                status = broker.commitConfigurationDataDeleteBehindMountPoint(
+                                        mountPoint, iiWithData.getInstanceIdentifier()).get();
+            }
+            else {
+                status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier()).get();
+            }
+        }
+        catch( Exception e ) {
+            throw new ResponseException( e, "Error creating data" );
+        }
+
+        if( status.getResult() == TransactionStatus.COMMITED )
+            return Response.status(Status.OK).build();
+
+        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+    }
+
+    @Override
+    public Response subscribeToStream(final String identifier, final UriInfo uriInfo) {
+        final String streamName = Notificator.createStreamNameFromUri(identifier);
+        if (Strings.isNullOrEmpty(streamName)) {
+            throw new ResponseException(Status.BAD_REQUEST, "Stream name is empty.");
+        }
+
+        final ListenerAdapter listener = Notificator.getListenerFor(streamName);
+        if (listener == null) {
+            throw new ResponseException(Status.BAD_REQUEST, "Stream was not found.");
+        }
+
+        broker.registerToListenDataChanges(listener);
+
+        final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
+        UriBuilder port = uriBuilder.port(WebSocketServer.PORT);
+        final URI uriToWebsocketServer = port.replacePath(streamName).build();
+
+        return Response.status(Status.OK).location(uriToWebsocketServer).build();
+    }
+
+    private Module findModule(final MountInstance mountPoint, final CompositeNode data) {
+        if (data instanceof CompositeNodeWrapper) {
+            return findModule(mountPoint, (CompositeNodeWrapper)data);
+        }
+        else if (data != null) {
+            URI namespace = data.getNodeType().getNamespace();
+            if (mountPoint != null) {
+                return this.controllerContext.findModuleByNamespace(mountPoint, namespace);
+            }
+            else {
+                return this.controllerContext.findModuleByNamespace(namespace);
+            }
+        }
+        else {
+            throw new IllegalArgumentException("Unhandled parameter types: " +
+                    Arrays.<Object>asList(mountPoint, data).toString());
+        }
+    }
+
+    private Module findModule(final MountInstance mountPoint, final CompositeNodeWrapper data) {
+        URI namespace = data.getNamespace();
+        Preconditions.<URI>checkNotNull(namespace);
+
+        Module module = null;
+        if (mountPoint != null) {
+            module = this.controllerContext.findModuleByNamespace(mountPoint, namespace);
+            if (module == null) {
+                module = this.controllerContext.findModuleByName(mountPoint, namespace.toString());
+            }
+        }
+        else {
+            module = this.controllerContext.findModuleByNamespace(namespace);
+            if (module == null) {
+                module = this.controllerContext.findModuleByName(namespace.toString());
+            }
+        }
+
+        return module;
+    }
+
+    private InstanceIdWithSchemaNode addLastIdentifierFromData(
+                                              final InstanceIdWithSchemaNode identifierWithSchemaNode,
+                                              final CompositeNode data, final DataSchemaNode schemaOfData) {
+        InstanceIdentifier instanceIdentifier = null;
+        if (identifierWithSchemaNode != null) {
+            instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier();
+        }
+
+        final InstanceIdentifier iiOriginal = instanceIdentifier;
+        InstanceIdentifierBuilder iiBuilder = null;
+        if (iiOriginal == null) {
+            iiBuilder = InstanceIdentifier.builder();
+        }
+        else {
+            iiBuilder = InstanceIdentifier.builder(iiOriginal);
+        }
+
+        if ((schemaOfData instanceof ListSchemaNode)) {
+            HashMap<QName,Object> keys = this.resolveKeysFromData(((ListSchemaNode) schemaOfData), data);
+            iiBuilder.nodeWithKey(schemaOfData.getQName(), keys);
+        }
+        else {
+            iiBuilder.node(schemaOfData.getQName());
+        }
+
+        InstanceIdentifier instance = iiBuilder.toInstance();
+        MountInstance mountPoint = null;
+        if (identifierWithSchemaNode != null) {
+            mountPoint=identifierWithSchemaNode.getMountPoint();
+        }
+
+        return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint);
+    }
+
+    private HashMap<QName,Object> resolveKeysFromData(final ListSchemaNode listNode,
+                                                      final CompositeNode dataNode) {
+        final HashMap<QName,Object> keyValues = new HashMap<QName, Object>();
+        List<QName> _keyDefinition = listNode.getKeyDefinition();
+        for (final QName key : _keyDefinition) {
+            SimpleNode<? extends Object> head = null;
+            String localName = key.getLocalName();
+            List<SimpleNode<? extends Object>> simpleNodesByName = dataNode.getSimpleNodesByName(localName);
+            if (simpleNodesByName != null) {
+                head = Iterables.getFirst(simpleNodesByName, null);
+            }
+
+            Object dataNodeKeyValueObject = null;
+            if (head != null) {
+                dataNodeKeyValueObject = head.getValue();
+            }
+
+            if (dataNodeKeyValueObject == null) {
+                throw new ResponseException(Status.BAD_REQUEST,
+                            "Data contains list \"" + dataNode.getNodeType().getLocalName() +
+                            "\" which does not contain key: \"" + key.getLocalName() + "\"");
+            }
+
+            keyValues.put(key, dataNodeKeyValueObject);
+        }
+
+        return keyValues;
+    }
+
+    private boolean endsWithMountPoint(final String identifier) {
+        return identifier.endsWith(ControllerContext.MOUNT) ||
+               identifier.endsWith(ControllerContext.MOUNT + "/");
+    }
+
+    private boolean representsMountPointRootData(final CompositeNode data) {
+        URI namespace = this.namespace(data);
+        return (SchemaContext.NAME.getNamespace().equals( namespace ) /* ||
+                MOUNT_POINT_MODULE_NAME.equals( namespace.toString() )*/ ) &&
+                SchemaContext.NAME.getLocalName().equals( this.localName(data) );
+    }
+
+    private String addMountPointIdentifier(final String identifier) {
+        boolean endsWith = identifier.endsWith("/");
+        if (endsWith) {
+            return (identifier + ControllerContext.MOUNT);
+        }
+
+        return identifier + "/" + ControllerContext.MOUNT;
+    }
+
+    private CompositeNode normalizeNode(final CompositeNode node, final DataSchemaNode schema,
+                                        final MountInstance mountPoint) {
+        if (schema == null) {
+            QName nodeType = node == null ? null : node.getNodeType();
+            String localName = nodeType == null ? null : nodeType.getLocalName();
+            String _plus = ("Data schema node was not found for " + localName);
+            throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+                                        "Data schema node was not found for " + localName );
+        }
+
+        if (!(schema instanceof DataNodeContainer)) {
+            throw new ResponseException(Status.BAD_REQUEST,
+                                        "Root element has to be container or list yang datatype.");
+        }
+
+        if ((node instanceof CompositeNodeWrapper)) {
+            boolean isChangeAllowed = ((CompositeNodeWrapper) node).isChangeAllowed();
+            if (isChangeAllowed) {
+                try {
+                    this.normalizeNode(((CompositeNodeWrapper) node), schema, null, mountPoint);
+                }
+                catch (NumberFormatException e) {
+                    throw new ResponseException(Status.BAD_REQUEST, e.getMessage());
+                }
+            }
+
+            return ((CompositeNodeWrapper) node).unwrap();
+        }
+
+        return node;
+    }
+
+    private void normalizeNode(final NodeWrapper<? extends Object> nodeBuilder,
+                               final DataSchemaNode schema, final QName previousAugment,
+                               final MountInstance mountPoint) {
+        if (schema == null) {
+            throw new ResponseException(Status.BAD_REQUEST,
+                                        "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
+                                        "\" does not exist in yang schema.");
+        }
+
+        QName currentAugment = null;
+        if (nodeBuilder.getQname() != null) {
+            currentAugment = previousAugment;
+        }
+        else {
+            currentAugment = this.normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint);
+            if (nodeBuilder.getQname() == null) {
+                throw new ResponseException(Status.BAD_REQUEST,
+                        "Data has bad format.\nIf data is in XML format then namespace for \"" +
+                        nodeBuilder.getLocalName() +
+                        "\" should be \"" + schema.getQName().getNamespace() + "\".\n" +
+                        "If data is in JSON format then module name for \"" + nodeBuilder.getLocalName() +
+                         "\" should be corresponding to namespace \"" +
+                        schema.getQName().getNamespace() + "\".");
+            }
+        }
+
+        if ((nodeBuilder instanceof CompositeNodeWrapper)) {
+            final List<NodeWrapper<?>> children = ((CompositeNodeWrapper) nodeBuilder).getValues();
+            for (final NodeWrapper<? extends Object> child : children) {
+                final List<DataSchemaNode> potentialSchemaNodes =
+                        this.controllerContext.findInstanceDataChildrenByName(
+                                             ((DataNodeContainer) schema), child.getLocalName());
+
+                if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
+                    StringBuilder builder = new StringBuilder();
+                    for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
+                        builder.append("   ").append(potentialSchemaNode.getQName().getNamespace().toString())
+                               .append("\n");
+                    }
+
+                    throw new ResponseException(Status.BAD_REQUEST,
+                                 "Node \"" + child.getLocalName() +
+                                 "\" is added as augment from more than one module. " +
+                                 "Therefore node must have namespace (XML format) or module name (JSON format)." +
+                                 "\nThe node is added as augment from modules with namespaces:\n" + builder);
+                }
+
+                boolean rightNodeSchemaFound = false;
+                for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
+                    if (!rightNodeSchemaFound) {
+                        final QName potentialCurrentAugment =
+                                this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint);
+                        if (child.getQname() != null ) {
+                            this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint);
+                            rightNodeSchemaFound = true;
+                        }
+                    }
+                }
+
+                if (!rightNodeSchemaFound) {
+                    throw new ResponseException(Status.BAD_REQUEST,
+                                      "Schema node \"" + child.getLocalName() + "\" was not found in module.");
+                }
+            }
+
+            if ((schema instanceof ListSchemaNode)) {
+                final List<QName> listKeys = ((ListSchemaNode) schema).getKeyDefinition();
+                for (final QName listKey : listKeys) {
+                    boolean foundKey = false;
+                    for (final NodeWrapper<? extends Object> child : children) {
+                        if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) {
+                            foundKey = true;
+                        }
+                    }
+
+                    if (!foundKey) {
+                        throw new ResponseException(Status.BAD_REQUEST,
+                                       "Missing key in URI \"" + listKey.getLocalName() +
+                                       "\" of list \"" + schema.getQName().getLocalName() + "\"");
+                    }
+                }
+            }
+        }
+        else {
+            if ((nodeBuilder instanceof SimpleNodeWrapper)) {
+                final SimpleNodeWrapper simpleNode = ((SimpleNodeWrapper) nodeBuilder);
+                final Object value = simpleNode.getValue();
+                Object inputValue = value;
+                TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
+                if ((typeDefinition instanceof IdentityrefTypeDefinition)) {
+                    if ((value instanceof String)) {
+                        inputValue = new IdentityValuesDTO( nodeBuilder.getNamespace().toString(),
+                                                            (String) value, null, (String) value );
+                    } // else value is already instance of IdentityValuesDTO
+                }
+
+                Codec<Object,Object> codec = RestCodec.from(typeDefinition, mountPoint);
+                Object outputValue = codec == null ? null : codec.deserialize(inputValue);
+
+                simpleNode.setValue(outputValue);
+            }
+            else {
+                if ((nodeBuilder instanceof EmptyNodeWrapper)) {
+                    final EmptyNodeWrapper emptyNodeBuilder = ((EmptyNodeWrapper) nodeBuilder);
+                    if ((schema instanceof LeafSchemaNode)) {
+                        emptyNodeBuilder.setComposite(false);
+                    }
+                    else {
+                        if ((schema instanceof ContainerSchemaNode)) {
+                            // FIXME: Add presence check
+                            emptyNodeBuilder.setComposite(true);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private QName normalizeNodeName(final NodeWrapper<? extends Object> nodeBuilder,
+                                    final DataSchemaNode schema, final QName previousAugment,
+                                    final MountInstance mountPoint) {
+        QName validQName = schema.getQName();
+        QName currentAugment = previousAugment;
+        if (schema.isAugmenting()) {
+            currentAugment = schema.getQName();
+        }
+        else if (previousAugment != null &&
+                 !Objects.equal( schema.getQName().getNamespace(), previousAugment.getNamespace())) {
+            validQName = QName.create(currentAugment, schema.getQName().getLocalName());
+        }
+
+        String moduleName = null;
+        if (mountPoint == null) {
+            moduleName = controllerContext.findModuleNameByNamespace(validQName.getNamespace());
+        }
+        else {
+            moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.getNamespace());
+        }
+
+        if (nodeBuilder.getNamespace() == null ||
+            Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace()) ||
+            Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*||
+            Note: this check is wrong - can never be true as it compares a URI with a String
+                  not sure what the intention is so commented out...
+            Objects.equal(nodeBuilder.getNamespace(), MOUNT_POINT_MODULE_NAME)*/ ) {
+
+            nodeBuilder.setQname(validQName);
+        }
+
+        return currentAugment;
+    }
+
+    private URI namespace(final CompositeNode data) {
+        if (data instanceof CompositeNodeWrapper) {
+            return ((CompositeNodeWrapper)data).getNamespace();
+        }
+        else if (data != null) {
+            return data.getNodeType().getNamespace();
+        }
+        else {
+            throw new IllegalArgumentException("Unhandled parameter types: " +
+                    Arrays.<Object>asList(data).toString());
+        }
+    }
+
+    private String localName(final CompositeNode data) {
+        if (data instanceof CompositeNodeWrapper) {
+            return ((CompositeNodeWrapper)data).getLocalName();
+        }
+        else if (data != null) {
+            return data.getNodeType().getLocalName();
+        }
+        else {
+            throw new IllegalArgumentException("Unhandled parameter types: " +
+                    Arrays.<Object>asList(data).toString());
+        }
+    }
+
+    private String getName(final CompositeNode data) {
+        if (data instanceof CompositeNodeWrapper) {
+            return ((CompositeNodeWrapper)data).getLocalName();
+        }
+        else if (data != null) {
+            return data.getNodeType().getLocalName();
+        }
+        else {
+            throw new IllegalArgumentException("Unhandled parameter types: " +
+                    Arrays.<Object>asList(data).toString());
+        }
+    }
+
+    private TypeDefinition<? extends Object> _typeDefinition(final LeafSchemaNode node) {
+        TypeDefinition<?> baseType = node.getType();
+        while (baseType.getBaseType() != null) {
+            baseType = baseType.getBaseType();
+        }
+
+        return baseType;
+    }
+
+    private TypeDefinition<? extends Object> typeDefinition(final LeafListSchemaNode node) {
+        TypeDefinition<?> baseType = node.getType();
+        while (baseType.getBaseType() != null) {
+            baseType = baseType.getBaseType();
+        }
+
+        return baseType;
+    }
+
+    private TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
+        if (node instanceof LeafListSchemaNode) {
+            return typeDefinition((LeafListSchemaNode)node);
+        }
+        else if (node instanceof LeafSchemaNode) {
+            return _typeDefinition((LeafSchemaNode)node);
+        }
+        else {
+            throw new IllegalArgumentException("Unhandled parameter types: " +
+                    Arrays.<Object>asList(node).toString());
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
deleted file mode 100644 (file)
index f1901d7..0000000
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.restconf.impl
-
-import com.google.common.base.Preconditions
-import com.google.common.base.Splitter
-import com.google.common.collect.Lists
-import java.net.URI
-import java.text.ParseException
-import java.text.SimpleDateFormat
-import java.util.ArrayList
-import java.util.HashMap
-import java.util.List
-import java.util.Set
-import javax.ws.rs.core.Response
-import javax.ws.rs.core.UriInfo
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus
-import org.opendaylight.controller.sal.core.api.mount.MountInstance
-import org.opendaylight.controller.sal.rest.api.RestconfService
-import org.opendaylight.controller.sal.streams.listeners.Notificator
-import org.opendaylight.controller.sal.streams.websockets.WebSocketServer
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.Module
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
-import org.opendaylight.yangtools.yang.model.util.EmptyType
-import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder
-import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder
-
-import static javax.ws.rs.core.Response.Status.*
-
-class RestconfImpl implements RestconfService {
-
-    val static RestconfImpl INSTANCE = new RestconfImpl
-    val static MOUNT_POINT_MODULE_NAME = "ietf-netconf"
-    val static REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")
-    val static RESTCONF_MODULE_DRAFT02_REVISION = "2013-10-19"
-    val static RESTCONF_MODULE_DRAFT02_NAME = "ietf-restconf"
-    val static RESTCONF_MODULE_DRAFT02_NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf"
-    val static RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE = "restconf"
-    val static RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf"
-    val static RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules"
-    val static RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module"
-    val static RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams"
-    val static RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream"
-    val static RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations"
-    val static SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"
-    val static SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription"
-
-    @Property
-    BrokerFacade broker
-
-    @Property
-    extension ControllerContext controllerContext
-
-    private new() {
-        if (INSTANCE !== null) {
-            throw new IllegalStateException("Already instantiated");
-        }
-    }
-
-    static def getInstance() {
-        return INSTANCE
-    }
-
-    override getModules() {
-        val restconfModule = getRestconfModule()
-        val List<Node<?>> modulesAsData = new ArrayList
-        val moduleSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)
-        for (module : allModules) {
-            modulesAsData.add(module.toModuleCompositeNode(moduleSchemaNode))
-        }
-        val modulesSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)
-        val modulesNode = NodeFactory.createImmutableCompositeNode(modulesSchemaNode.QName, null, modulesAsData)
-        return new StructuredData(modulesNode, modulesSchemaNode, null)
-    }
-
-    override getAvailableStreams(){
-        var Set<String> availableStreams = Notificator.getStreamNames();
-        val List<Node<?>> streamsAsData = new ArrayList
-        val streamSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)
-        for (String streamName:availableStreams){
-            streamsAsData.add(streamName.toStreamCompositeNode(streamSchemaNode))
-        }
-        val streamsSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)
-        val streamsNode = NodeFactory.createImmutableCompositeNode(streamsSchemaNode.QName, null, streamsAsData)
-        return new StructuredData(streamsNode, streamsSchemaNode, null)
-    }
-    override getModules(String identifier) {
-        var Set<Module> modules = null
-        var MountInstance mountPoint = null
-        if (identifier.contains(ControllerContext.MOUNT)) {
-            mountPoint = identifier.toMountPointIdentifier.mountPoint
-            modules = mountPoint.allModules
-        } else {
-            throw new ResponseException(BAD_REQUEST, "URI has bad format. If modules behind mount point should be showed, URI has to end with " + ControllerContext.MOUNT)
-        }
-        val List<Node<?>> modulesAsData = new ArrayList
-        val moduleSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)
-        for (module : modules) {
-            modulesAsData.add(module.toModuleCompositeNode(moduleSchemaNode))
-        }
-        val modulesSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)
-        val modulesNode = NodeFactory.createImmutableCompositeNode(modulesSchemaNode.QName, null, modulesAsData)
-        return new StructuredData(modulesNode, modulesSchemaNode, mountPoint)
-    }
-
-    override getModule(String identifier) {
-        val moduleNameAndRevision = identifier.moduleNameAndRevision
-        var Module module = null
-        var MountInstance mountPoint = null
-        if (identifier.contains(ControllerContext.MOUNT)) {
-            mountPoint = identifier.toMountPointIdentifier.mountPoint
-            module = mountPoint.findModuleByNameAndRevision(moduleNameAndRevision)
-        } else {
-            module = findModuleByNameAndRevision(moduleNameAndRevision)
-        }
-        if (module === null) {
-            throw new ResponseException(BAD_REQUEST,
-                "Module with name '" + moduleNameAndRevision.localName + "' and revision '" +
-                    moduleNameAndRevision.revision + "' was not found.")
-        }
-        val moduleSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)
-        val moduleNode = module.toModuleCompositeNode(moduleSchemaNode)
-        return new StructuredData(moduleNode, moduleSchemaNode, mountPoint)
-    }
-
-    override getOperations() {
-        return operationsFromModulesToStructuredData(allModules,null)
-    }
-    
-    override getOperations(String identifier) {
-        var Set<Module> modules = null
-        var MountInstance mountPoint = null
-        if (identifier.contains(ControllerContext.MOUNT)) {
-            mountPoint = identifier.toMountPointIdentifier.mountPoint
-            modules = mountPoint.allModules
-        } else {
-            throw new ResponseException(BAD_REQUEST, "URI has bad format. If operations behind mount point should be showed, URI has to end with " + ControllerContext.MOUNT)
-        }
-        return operationsFromModulesToStructuredData(modules,mountPoint)
-    }
-    
-    private def StructuredData operationsFromModulesToStructuredData(Set<Module> modules,MountInstance mountPoint) {
-        val List<Node<?>> operationsAsData = new ArrayList
-        val operationsSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE)        
-        val fakeOperationsSchemaNode = new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, operationsSchemaNode.QName, operationsSchemaNode.path)
-        for (module : modules) {
-            for (rpc : module.rpcs) {
-                operationsAsData.add(NodeFactory.createImmutableSimpleNode(rpc.QName, null, null))
-                val fakeRpcSchemaNode = new LeafSchemaNodeBuilder(module.name, 0, rpc.QName, null)
-                fakeRpcSchemaNode.setAugmenting(true)
-                fakeRpcSchemaNode.setType(EmptyType.instance)
-                fakeOperationsSchemaNode.addChildNode(fakeRpcSchemaNode.build)                
-            }
-        }
-        val operationsNode = NodeFactory.createImmutableCompositeNode(operationsSchemaNode.QName, null, operationsAsData)
-        return new StructuredData(operationsNode, fakeOperationsSchemaNode.build, mountPoint)        
-    }
-
-    private def Module getRestconfModule() {
-        val restconfModule = findModuleByNameAndRevision(
-            QName.create(RESTCONF_MODULE_DRAFT02_NAMESPACE, RESTCONF_MODULE_DRAFT02_REVISION,
-                RESTCONF_MODULE_DRAFT02_NAME))
-        if (restconfModule === null) {
-            throw new ResponseException(INTERNAL_SERVER_ERROR, "Restconf module was not found.")
-        }
-        return restconfModule
-    }
-
-    private def QName getModuleNameAndRevision(String identifier) {
-        val indexOfMountPointFirstLetter = identifier.indexOf(ControllerContext.MOUNT)
-        var moduleNameAndRevision = "";
-        if (indexOfMountPointFirstLetter !== -1) { // module and revision is behind mount point string
-            moduleNameAndRevision = identifier.substring(indexOfMountPointFirstLetter + ControllerContext.MOUNT.length)
-        } else (
-            moduleNameAndRevision = identifier
-        )
-        val pathArgs = Lists.newArrayList(Splitter.on("/").omitEmptyStrings.split(moduleNameAndRevision))
-        if (pathArgs.length < 2) {
-            throw new ResponseException(BAD_REQUEST,
-                "URI has bad format. End of URI should be in format 'moduleName/yyyy-MM-dd'")
-        }
-        try {
-            val moduleName = pathArgs.head
-            val moduleRevision = REVISION_FORMAT.parse(pathArgs.get(1))
-            return QName.create(null, moduleRevision, moduleName)
-        } catch(ParseException e) {
-            throw new ResponseException(BAD_REQUEST, "URI has bad format. It should be 'moduleName/yyyy-MM-dd'")
-        }
-    }
-
-    private def CompositeNode toStreamCompositeNode(String streamName, DataSchemaNode streamSchemaNode) {
-        val List<Node<?>> streamNodeValues = new ArrayList
-        val nameSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("name").head
-        streamNodeValues.add(NodeFactory.createImmutableSimpleNode(nameSchemaNode.QName, null, streamName))
-
-        val descriptionSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("description").head
-        streamNodeValues.add(NodeFactory.createImmutableSimpleNode(descriptionSchemaNode.QName, null, "DESCRIPTION_PLACEHOLDER"))
-
-        val replaySupportSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("replay-support").head
-        streamNodeValues.add(NodeFactory.createImmutableSimpleNode(replaySupportSchemaNode.QName, null, true))
-
-        val replayLogCreationTimeSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("replay-log-creation-time").head
-        streamNodeValues.add(NodeFactory.createImmutableSimpleNode(replayLogCreationTimeSchemaNode.QName, null, ""))
-
-        val eventsSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("events").head
-        streamNodeValues.add(NodeFactory.createImmutableSimpleNode(eventsSchemaNode.QName, null, ""))
-
-        return NodeFactory.createImmutableCompositeNode(streamSchemaNode.QName, null, streamNodeValues)
-    }
-    private def CompositeNode toModuleCompositeNode(Module module, DataSchemaNode moduleSchemaNode) {
-        val List<Node<?>> moduleNodeValues = new ArrayList
-        val nameSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("name").head
-        moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(nameSchemaNode.QName, null, module.name))
-        val revisionSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("revision").head
-        moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(revisionSchemaNode.QName, null, REVISION_FORMAT.format(module.revision)))
-        val namespaceSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("namespace").head
-        moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(namespaceSchemaNode.QName, null, module.namespace.toString))
-        val featureSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("feature").head
-        for (feature : module.features) {
-            moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(featureSchemaNode.QName, null, feature.QName.localName))
-        }
-        return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.QName, null, moduleNodeValues)
-    }
-
-    private def DataSchemaNode getSchemaNode(Module restconfModule, String schemaNodeName) {
-        val restconfGrouping = restconfModule.groupings.filter[g|g.QName.localName == RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE].head
-        val restconfContainer = restconfGrouping.findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE).head
-        if (schemaNodeName == RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE) {
-            return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE).head
-        } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE) {
-           return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE).head
-        } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE) {
-           val modules = (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE).head
-           return (modules as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE).head
-        }else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE) {
-            return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE).head
-        } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE) {
-            val modules = (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE).head
-            return (modules as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE).head
-        }
-        return null
-    }
-
-    override getRoot() {
-        return null;
-    }
-
-    override invokeRpc(String identifier, CompositeNode payload) {
-        val rpc = resolveIdentifierInInvokeRpc(identifier)
-        if (rpc.QName.namespace.toString == SAL_REMOTE_NAMESPACE && rpc.QName.localName == SAL_REMOTE_RPC_SUBSRCIBE) {
-            val value = normalizeNode(payload, rpc.input, null)
-            val pathNode = value?.getFirstSimpleByName(QName.create(rpc.QName, "path"))
-            val pathValue = pathNode?.value
-            if (pathValue === null && !(pathValue instanceof InstanceIdentifier)) {
-                throw new ResponseException(INTERNAL_SERVER_ERROR, "Instance identifier was not normalized correctly.");
-            }
-            val pathIdentifier = (pathValue as InstanceIdentifier)
-            var String streamName = null
-            if (!pathIdentifier.path.nullOrEmpty) {
-                streamName = Notificator.createStreamNameFromUri(pathIdentifier.toFullRestconfIdentifier)
-            }
-            if (streamName.nullOrEmpty) {
-                throw new ResponseException(BAD_REQUEST, "Path is empty or contains data node which is not Container or List build-in type.");
-            }
-            val streamNameNode = NodeFactory.createImmutableSimpleNode(QName.create(rpc.output.QName, "stream-name"), null, streamName)
-            val List<Node<?>> output = new ArrayList
-            output.add(streamNameNode)
-            val responseData = NodeFactory.createMutableCompositeNode(rpc.output.QName, null, output, null, null)
-
-            if (!Notificator.existListenerFor(pathIdentifier)) {
-                Notificator.createListener(pathIdentifier, streamName)
-            }
-
-            return new StructuredData(responseData, rpc.output, null)
-        }
-        return callRpc(identifier.rpcDefinition, payload)
-    }
-
-    override invokeRpc(String identifier, String noPayload) {
-        if (!noPayload.nullOrEmpty) {
-            throw new ResponseException(UNSUPPORTED_MEDIA_TYPE, "Content-Type contains unsupported Media Type.");
-        }
-        val rpc = resolveIdentifierInInvokeRpc(identifier)
-        return callRpc(rpc, null)
-    }
-
-    private def resolveIdentifierInInvokeRpc(String identifier) {
-        if (identifier.indexOf("/") === -1) {
-            val identifierDecoded = identifier.urlPathArgDecode
-            val rpc = identifierDecoded.rpcDefinition
-            if (rpc !== null) {
-                return rpc
-            }
-            throw new ResponseException(NOT_FOUND, "RPC does not exist.");
-        }
-        val slashErrorMsg = String.format(
-            "Identifier %n%s%ncan't contain slash character (/).%nIf slash is part of identifier name then use %%2F placeholder.", identifier)
-        throw new ResponseException(NOT_FOUND, slashErrorMsg);
-    }
-
-    private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) {
-        if (rpc === null) {
-            throw new ResponseException(NOT_FOUND, "RPC does not exist.");
-        }
-        var CompositeNode rpcRequest;
-        if (payload === null) {
-            rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, null, null, null)
-        } else {
-            val value = normalizeNode(payload, rpc.input, null)
-            val List<Node<?>> input = new ArrayList
-            input.add(value)
-            rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
-        }
-        val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest);
-        if (!rpcResult.successful) {
-            throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed")
-        }
-        if (rpcResult.result === null) {
-            return null
-        }
-        return new StructuredData(rpcResult.result, rpc.output, null)
-    }
-
-    override readConfigurationData(String identifier) {
-        val iiWithData = identifier.toInstanceIdentifier
-        var CompositeNode data = null;
-        if (iiWithData.mountPoint !== null) {
-            data = broker.readConfigurationDataBehindMountPoint(iiWithData.mountPoint, iiWithData.getInstanceIdentifier)
-        } else {
-            data = broker.readConfigurationData(iiWithData.getInstanceIdentifier);
-        }
-        return new StructuredData(data, iiWithData.schemaNode, iiWithData.mountPoint)
-    }
-
-    override readOperationalData(String identifier) {
-        val iiWithData = identifier.toInstanceIdentifier
-        var CompositeNode data = null;
-        if (iiWithData.mountPoint !== null) {
-            data = broker.readOperationalDataBehindMountPoint(iiWithData.mountPoint, iiWithData.getInstanceIdentifier)
-        } else {
-            data = broker.readOperationalData(iiWithData.getInstanceIdentifier);
-        }
-        return new StructuredData(data, iiWithData.schemaNode, iiWithData.mountPoint)
-    }
-
-    override updateConfigurationData(String identifier, CompositeNode payload) {
-        val iiWithData = identifier.toInstanceIdentifier
-        val value = normalizeNode(payload, iiWithData.schemaNode, iiWithData.mountPoint)
-        var RpcResult<TransactionStatus> status = null
-        if (iiWithData.mountPoint !== null) {
-            status = broker.commitConfigurationDataPutBehindMountPoint(iiWithData.mountPoint,
-                iiWithData.instanceIdentifier, value).get()
-        } else {
-            status = broker.commitConfigurationDataPut(iiWithData.instanceIdentifier, value).get();
-        }
-        switch status.result {
-            case TransactionStatus.COMMITED: Response.status(OK).build
-            default: Response.status(INTERNAL_SERVER_ERROR).build
-        }
-    }
-
-    override createConfigurationData(String identifier, CompositeNode payload) {
-        if (payload.namespace === null) {
-            throw new ResponseException(BAD_REQUEST,
-                "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
-        }
-        var InstanceIdWithSchemaNode iiWithData;
-        var CompositeNode value;
-        if (payload.representsMountPointRootData) { // payload represents mount point data and URI represents path to the mount point
-            if (identifier.endsWithMountPoint) {
-                throw new ResponseException(BAD_REQUEST,
-                    "URI has bad format. URI should be without \"" + ControllerContext.MOUNT + "\" for POST operation.");
-            }
-            val completIdentifier = identifier.addMountPointIdentifier
-            iiWithData = completIdentifier.toInstanceIdentifier
-            value = normalizeNode(payload, iiWithData.schemaNode, iiWithData.mountPoint)
-        } else {
-            val uncompleteInstIdWithData = identifier.toInstanceIdentifier
-            val parentSchema = uncompleteInstIdWithData.schemaNode as DataNodeContainer
-            val module = uncompleteInstIdWithData.mountPoint.findModule(payload)
-            if (module === null) {
-                throw new ResponseException(BAD_REQUEST, "Module was not found for \"" + payload.namespace + "\"")
-            }
-            val schemaNode = parentSchema.findInstanceDataChildByNameAndNamespace(payload.name, module.namespace)
-            value = normalizeNode(payload, schemaNode, uncompleteInstIdWithData.mountPoint)
-            iiWithData = uncompleteInstIdWithData.addLastIdentifierFromData(value, schemaNode)
-        }
-        var RpcResult<TransactionStatus> status = null
-        if (iiWithData.mountPoint !== null) {
-            status = broker.commitConfigurationDataPostBehindMountPoint(iiWithData.mountPoint,
-                iiWithData.instanceIdentifier, value)?.get();
-        } else {
-            status = broker.commitConfigurationDataPost(iiWithData.instanceIdentifier, value)?.get();
-        }
-        if (status === null) {
-            return Response.status(ACCEPTED).build
-        }
-        switch status.result {
-            case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
-            default: Response.status(INTERNAL_SERVER_ERROR).build
-        }
-    }
-
-    override createConfigurationData(CompositeNode payload) {
-        if (payload.namespace === null) {
-            throw new ResponseException(BAD_REQUEST,
-                "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
-        }
-        val module = findModule(null, payload)
-        if (module === null) {
-            throw new ResponseException(BAD_REQUEST,
-                "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
-        }
-        val schemaNode = module.findInstanceDataChildByNameAndNamespace(payload.name, module.namespace)
-        val value = normalizeNode(payload, schemaNode, null)
-        val iiWithData = addLastIdentifierFromData(null, value, schemaNode)
-        var RpcResult<TransactionStatus> status = null
-        if (iiWithData.mountPoint !== null) {
-            status = broker.commitConfigurationDataPostBehindMountPoint(iiWithData.mountPoint,
-                iiWithData.instanceIdentifier, value)?.get();
-        } else {
-            status = broker.commitConfigurationDataPost(iiWithData.instanceIdentifier, value)?.get();
-        }
-        if (status === null) {
-            return Response.status(ACCEPTED).build
-        }
-        switch status.result {
-            case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
-            default: Response.status(INTERNAL_SERVER_ERROR).build
-        }
-    }
-
-    override deleteConfigurationData(String identifier) {
-        val iiWithData = identifier.toInstanceIdentifier
-        var RpcResult<TransactionStatus> status = null
-        if (iiWithData.mountPoint !== null) {
-            status = broker.commitConfigurationDataDeleteBehindMountPoint(iiWithData.mountPoint,
-                iiWithData.getInstanceIdentifier).get;
-        } else {
-            status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier).get;
-        }
-        switch status.result {
-            case TransactionStatus.COMMITED: Response.status(OK).build
-            default: Response.status(INTERNAL_SERVER_ERROR).build
-        }
-    }
-
-    override subscribeToStream(String identifier, UriInfo uriInfo) {
-        val streamName = Notificator.createStreamNameFromUri(identifier)
-        if (streamName.nullOrEmpty) {
-            throw new ResponseException(BAD_REQUEST, "Stream name is empty.")
-        }
-        val listener = Notificator.getListenerFor(streamName);
-        if (listener === null) {
-            throw new ResponseException(BAD_REQUEST, "Stream was not found.")
-        }
-        broker.registerToListenDataChanges(listener)
-        val uriBuilder = uriInfo.getAbsolutePathBuilder()
-        val uriToWebsocketServer = uriBuilder.port(WebSocketServer.PORT).replacePath(streamName).build()
-        return Response.status(OK).location(uriToWebsocketServer).build
-    }
-
-    private def dispatch URI namespace(CompositeNode data) {
-        return data.nodeType.namespace
-    }
-
-    private def dispatch URI namespace(CompositeNodeWrapper data) {
-        return data.namespace
-    }
-
-    private def dispatch String localName(CompositeNode data) {
-        return data.nodeType.localName
-    }
-
-    private def dispatch String localName(CompositeNodeWrapper data) {
-        return data.localName
-    }
-
-    private def dispatch Module findModule(MountInstance mountPoint, CompositeNode data) {
-        if (mountPoint !== null) {
-            return mountPoint.findModuleByNamespace(data.nodeType.namespace)
-        } else {
-            return findModuleByNamespace(data.nodeType.namespace)
-        }
-    }
-
-    private def dispatch Module findModule(MountInstance mountPoint, CompositeNodeWrapper data) {
-        Preconditions.checkNotNull(data.namespace)
-        var Module module = null;
-        if (mountPoint !== null) {
-            module = mountPoint.findModuleByNamespace(data.namespace) // namespace from XML
-            if (module === null) {
-                module = mountPoint.findModuleByName(data.namespace.toString) // namespace (module name) from JSON
-            }
-        } else {
-            module = data.namespace.findModuleByNamespace // namespace from XML
-            if (module === null) {
-                module = data.namespace.toString.findModuleByName // namespace (module name) from JSON
-            }
-        }
-        return module
-    }
-
-    private def dispatch getName(CompositeNode data) {
-        return data.nodeType.localName
-    }
-
-    private def dispatch getName(CompositeNodeWrapper data) {
-        return data.localName
-    }
-
-    private def InstanceIdWithSchemaNode addLastIdentifierFromData(InstanceIdWithSchemaNode identifierWithSchemaNode,
-        CompositeNode data, DataSchemaNode schemaOfData) {
-        val iiOriginal = identifierWithSchemaNode?.instanceIdentifier
-        var InstanceIdentifierBuilder iiBuilder = null
-        if (iiOriginal === null) {
-            iiBuilder = InstanceIdentifier.builder
-        } else {
-            iiBuilder = InstanceIdentifier.builder(iiOriginal)
-        }
-
-        if (schemaOfData instanceof ListSchemaNode) {
-            iiBuilder.nodeWithKey(schemaOfData.QName, (schemaOfData as ListSchemaNode).resolveKeysFromData(data))
-        } else {
-            iiBuilder.node(schemaOfData.QName)
-        }
-        return new InstanceIdWithSchemaNode(iiBuilder.toInstance, schemaOfData, identifierWithSchemaNode?.mountPoint)
-    }
-
-    private def resolveKeysFromData(ListSchemaNode listNode, CompositeNode dataNode) {
-        val keyValues = new HashMap<QName, Object>();
-        for (key : listNode.keyDefinition) {
-            val dataNodeKeyValueObject = dataNode.getSimpleNodesByName(key.localName)?.head?.value
-            if (dataNodeKeyValueObject === null) {
-                throw new ResponseException(BAD_REQUEST,
-                    "Data contains list \"" + dataNode.nodeType.localName + "\" which does not contain key: \"" +
-                        key.localName + "\"")
-            }
-            keyValues.put(key, dataNodeKeyValueObject);
-        }
-        return keyValues
-    }
-
-    private def endsWithMountPoint(String identifier) {
-        return (identifier.endsWith(ControllerContext.MOUNT) || identifier.endsWith(ControllerContext.MOUNT + "/"))
-    }
-
-    private def representsMountPointRootData(CompositeNode data) {
-        return ((data.namespace == SchemaContext.NAME.namespace || data.namespace == MOUNT_POINT_MODULE_NAME) &&
-            data.localName == SchemaContext.NAME.localName)
-    }
-
-    private def addMountPointIdentifier(String identifier) {
-        if (identifier.endsWith("/")) {
-            return identifier + ControllerContext.MOUNT
-        }
-        return identifier + "/" + ControllerContext.MOUNT
-    }
-
-    private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema, MountInstance mountPoint) {
-        if (schema === null) {
-            throw new ResponseException(INTERNAL_SERVER_ERROR,
-                "Data schema node was not found for " + node?.nodeType?.localName)
-        }
-        if (!(schema instanceof DataNodeContainer)) {
-            throw new ResponseException(BAD_REQUEST, "Root element has to be container or list yang datatype.");
-        }
-        if (node instanceof CompositeNodeWrapper) {
-            if ((node  as CompositeNodeWrapper).changeAllowed) {
-                try {
-                    normalizeNode(node as CompositeNodeWrapper, schema, null, mountPoint)
-                } catch (NumberFormatException e) {
-                    throw new ResponseException(BAD_REQUEST,e.message)
-                }
-            }
-            return (node as CompositeNodeWrapper).unwrap()
-        }
-        return node
-    }
-
-    private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment,
-        MountInstance mountPoint) {
-        if (schema === null) {
-            throw new ResponseException(BAD_REQUEST,
-                "Data has bad format.\n\"" + nodeBuilder.localName + "\" does not exist in yang schema.");
-        }
-
-        var QName currentAugment;
-        if (nodeBuilder.qname !== null) {
-            currentAugment = previousAugment
-        } else {
-            currentAugment = normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint)
-            if (nodeBuilder.qname === null) {
-                throw new ResponseException(BAD_REQUEST,
-                    "Data has bad format.\nIf data is in XML format then namespace for \"" + nodeBuilder.localName +
-                        "\" should be \"" + schema.QName.namespace + "\".\n" +
-                        "If data is in JSON format then module name for \"" + nodeBuilder.localName +
-                         "\" should be corresponding to namespace \"" + schema.QName.namespace + "\".");
-            }
-        }
-
-        if (nodeBuilder instanceof CompositeNodeWrapper) {
-            val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
-            for (child : children) {
-                val potentialSchemaNodes = (schema as DataNodeContainer).findInstanceDataChildrenByName(child.localName)
-                if (potentialSchemaNodes.size > 1 && child.namespace === null) {
-                    val StringBuilder namespacesOfPotentialModules = new StringBuilder;
-                    for (potentialSchemaNode : potentialSchemaNodes) {
-                        namespacesOfPotentialModules.append("   ").append(potentialSchemaNode.QName.namespace.toString).append("\n")
-                    }
-                    throw new ResponseException(BAD_REQUEST,
-                        "Node \"" + child.localName + "\" is added as augment from more than one module. " 
-                        + "Therefore node must have namespace (XML format) or module name (JSON format)."
-                        + "\nThe node is added as augment from modules with namespaces:\n" + namespacesOfPotentialModules)
-                }
-                var rightNodeSchemaFound = false
-                for (potentialSchemaNode : potentialSchemaNodes) {
-                    if (!rightNodeSchemaFound) {
-                        val potentialCurrentAugment = normalizeNodeName(child, potentialSchemaNode, currentAugment,
-                            mountPoint)
-                        if (child.qname !== null) {
-                            normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint)
-                            rightNodeSchemaFound = true
-                        }
-                    }
-                }
-                if (!rightNodeSchemaFound) {
-                    throw new ResponseException(BAD_REQUEST,
-                        "Schema node \"" + child.localName + "\" was not found in module.")
-                }
-            }
-            if (schema instanceof ListSchemaNode) {
-                val listKeys = (schema as ListSchemaNode).keyDefinition
-                for (listKey : listKeys) {
-                    var foundKey = false
-                    for (child : children) {
-                        if (child.unwrap.nodeType.localName == listKey.localName) {
-                            foundKey = true;
-                        }
-                    }
-                    if (!foundKey) {
-                        throw new ResponseException(BAD_REQUEST,
-                            "Missing key in URI \"" + listKey.localName + "\" of list \"" + schema.QName.localName +
-                                "\"")
-                    }
-                }
-            }
-        } else if (nodeBuilder instanceof SimpleNodeWrapper) {
-            val simpleNode = (nodeBuilder as SimpleNodeWrapper)
-            val value = simpleNode.value
-            var inputValue = value;
-
-            if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
-                if (value instanceof String) {
-                    inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null,value as String);
-                } // else value is already instance of IdentityValuesDTO
-            }
-            
-            val outputValue = RestCodec.from(schema.typeDefinition, mountPoint)?.deserialize(inputValue);
-            simpleNode.setValue(outputValue)
-        } else if (nodeBuilder instanceof EmptyNodeWrapper) {
-            val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
-            if (schema instanceof LeafSchemaNode) {
-                emptyNodeBuilder.setComposite(false);
-            } else if (schema instanceof ContainerSchemaNode) {
-
-                // FIXME: Add presence check
-                emptyNodeBuilder.setComposite(true);
-            }
-        }
-    }
-
-    private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
-        var baseType = node.type
-        while (baseType.baseType !== null) {
-            baseType = baseType.baseType;
-        }
-        baseType
-    }
-
-    private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
-        var TypeDefinition<?> baseType = node.type
-        while (baseType.baseType !== null) {
-            baseType = baseType.baseType;
-        }
-        baseType
-    }
-    
-    private def QName normalizeNodeName(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment,
-        MountInstance mountPoint) {
-        var validQName = schema.QName
-        var currentAugment = previousAugment;
-        if (schema.augmenting) {
-            currentAugment = schema.QName
-        } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
-            validQName = QName.create(currentAugment, schema.QName.localName);
-        }
-        var String moduleName = null;
-        if (mountPoint === null) {
-            moduleName = controllerContext.findModuleNameByNamespace(validQName.namespace);
-        } else {
-            moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.namespace)
-        }
-        if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
-            nodeBuilder.namespace.toString == moduleName || nodeBuilder.namespace == MOUNT_POINT_MODULE_NAME) {
-            nodeBuilder.qname = validQName
-        }
-        return currentAugment
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java
new file mode 100644 (file)
index 0000000..18199de
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) ${year} 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.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
+import org.opendaylight.controller.sal.streams.listeners.Notificator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+
+/**
+ * Unit tests for BrokerFacade.
+ *
+ * @author Thomas Pantelis
+ */
+public class BrokerFacadeTest {
+
+    @Mock
+    DataBrokerService dataBroker;
+
+    @Mock
+    DataModificationTransaction mockTransaction;
+
+    @Mock
+    ConsumerSession mockConsumerSession;
+
+    @Mock
+    MountInstance mockMountInstance;
+
+    BrokerFacade brokerFacade = BrokerFacade.getInstance();
+
+    CompositeNode dataNode = TestUtils.readInputToCnSn( "/parts/ietf-interfaces_interfaces.xml",
+                                                        XmlToCompositeNodeProvider.INSTANCE );
+
+    QName qname = QName.create( "node" );
+
+    InstanceIdentifier instanceID = InstanceIdentifier.builder().node( qname ).toInstance();
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks( this );
+
+        brokerFacade.setDataService( dataBroker );
+        brokerFacade.setContext( mockConsumerSession );
+    }
+
+    @Test
+    public void testReadConfigurationData() {
+        when( dataBroker.readConfigurationData( instanceID ) ).thenReturn( dataNode );
+
+        CompositeNode actualNode = brokerFacade.readConfigurationData( instanceID );
+
+        assertSame( "readConfigurationData", dataNode, actualNode );
+    }
+
+    @Test
+    public void testReadConfigurationDataBehindMountPoint() {
+        when( mockMountInstance.readConfigurationData( instanceID ) ).thenReturn( dataNode );
+
+        CompositeNode actualNode = brokerFacade.readConfigurationDataBehindMountPoint(
+                                                                              mockMountInstance, instanceID );
+
+        assertSame( "readConfigurationDataBehindMountPoint", dataNode, actualNode );
+    }
+
+    @Test
+    public void testReadOperationalData() {
+        when( dataBroker.readOperationalData( instanceID ) ).thenReturn( dataNode );
+
+        CompositeNode actualNode = brokerFacade.readOperationalData( instanceID );
+
+        assertSame( "readOperationalData", dataNode, actualNode );
+    }
+
+    @Test
+    public void testReadOperationalDataBehindMountPoint() {
+        when( mockMountInstance.readOperationalData( instanceID ) ).thenReturn( dataNode );
+
+        CompositeNode actualNode = brokerFacade.readOperationalDataBehindMountPoint(
+                                                                              mockMountInstance, instanceID );
+
+        assertSame( "readOperationalDataBehindMountPoint", dataNode, actualNode );
+    }
+
+    @Test(expected=ResponseException.class)
+    public void testReadOperationalDataWithNoDataBroker() {
+        brokerFacade.setDataService( null );
+
+        brokerFacade.readOperationalData( instanceID );
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testInvokeRpc() {
+        RpcResult<CompositeNode> expResult = mock( RpcResult.class );
+        Future<RpcResult<CompositeNode>> future = Futures.immediateFuture( expResult );
+        when( mockConsumerSession.rpc( qname, dataNode ) ).thenReturn( future );
+
+        RpcResult<CompositeNode> actualResult = brokerFacade.invokeRpc( qname, dataNode );
+
+        assertSame( "invokeRpc", expResult, actualResult );
+    }
+
+    @Test(expected=ResponseException.class)
+    public void testInvokeRpcWithException() {
+        Exception mockEx = new Exception( "mock" );
+        Future<RpcResult<CompositeNode>> future = Futures.immediateFailedFuture( mockEx );
+        when( mockConsumerSession.rpc( qname, dataNode ) ).thenReturn( future );
+
+        brokerFacade.invokeRpc( qname, dataNode );
+    }
+
+    @Test(expected=ResponseException.class)
+    public void testInvokeRpcWithNoConsumerSession() {
+        brokerFacade.setContext( null );
+
+        brokerFacade.invokeRpc( qname, dataNode );
+    }
+
+    @Test
+    public void testCommitConfigurationDataPut() {
+        Future<RpcResult<TransactionStatus>> expFuture =  Futures.immediateFuture( null );
+
+        when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.putConfigurationData( instanceID, dataNode );
+        when( mockTransaction.commit() ).thenReturn( expFuture );
+
+        Future<RpcResult<TransactionStatus>> actualFuture =
+                             brokerFacade.commitConfigurationDataPut( instanceID, dataNode );
+
+        assertSame( "invokeRpc", expFuture, actualFuture );
+
+        InOrder inOrder = inOrder( dataBroker, mockTransaction );
+        inOrder.verify( dataBroker ).beginTransaction();
+        inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+        inOrder.verify( mockTransaction ).commit();
+    }
+
+    @Test
+    public void testCommitConfigurationDataPutBehindMountPoint() {
+        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+        when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.putConfigurationData( instanceID, dataNode );
+        when( mockTransaction.commit() ).thenReturn( expFuture );
+
+        Future<RpcResult<TransactionStatus>> actualFuture =
+                 brokerFacade.commitConfigurationDataPutBehindMountPoint(
+                                                       mockMountInstance, instanceID, dataNode );
+
+        assertSame( "invokeRpc", expFuture, actualFuture );
+
+        InOrder inOrder = inOrder( mockMountInstance, mockTransaction );
+        inOrder.verify( mockMountInstance ).beginTransaction();
+        inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+        inOrder.verify( mockTransaction ).commit();
+    }
+
+    @Test
+    public void testCommitConfigurationDataPost() {
+        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+        Map<InstanceIdentifier, CompositeNode> nodeMap =
+                new ImmutableMap.Builder<InstanceIdentifier,CompositeNode>()
+                                                             .put( instanceID, dataNode ).build();
+
+        when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.putConfigurationData( instanceID, dataNode );
+        when( mockTransaction.getCreatedConfigurationData() ).thenReturn( nodeMap );
+        when( mockTransaction.commit() ).thenReturn( expFuture );
+
+        Future<RpcResult<TransactionStatus>> actualFuture =
+                             brokerFacade.commitConfigurationDataPost( instanceID, dataNode );
+
+        assertSame( "commitConfigurationDataPut", expFuture, actualFuture );
+
+        InOrder inOrder = inOrder( dataBroker, mockTransaction );
+        inOrder.verify( dataBroker ).beginTransaction();
+        inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+        inOrder.verify( mockTransaction ).commit();
+    }
+
+    @Test(expected=ResponseException.class)
+    public void testCommitConfigurationDataPostAlreadyExists() {
+        when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.putConfigurationData( instanceID, dataNode );
+        when ( mockTransaction.readConfigurationData( instanceID ) )
+            .thenReturn( dataNode );
+        try {
+            brokerFacade.commitConfigurationDataPost( instanceID, dataNode );
+        } catch (ResponseException e) {
+            assertEquals("Unexpect Exception Status -> "
+                    + "http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48",
+                    (e.getResponse().getStatus()), Status.CONFLICT.getStatusCode());
+            throw e;
+        }
+    }
+
+    @Test
+    public void testCommitConfigurationDataPostBehindMountPoint() {
+        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+        Map<InstanceIdentifier, CompositeNode> nodeMap =
+                new ImmutableMap.Builder<InstanceIdentifier,CompositeNode>()
+                                                           .put( instanceID, dataNode ).build();
+
+        when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.putConfigurationData( instanceID, dataNode );
+        when( mockTransaction.getCreatedConfigurationData() ).thenReturn( nodeMap );
+        when( mockTransaction.commit() ).thenReturn( expFuture );
+
+        Future<RpcResult<TransactionStatus>> actualFuture =
+                brokerFacade.commitConfigurationDataPostBehindMountPoint( mockMountInstance,
+                                                                          instanceID, dataNode );
+
+        assertSame( "commitConfigurationDataPostBehindMountPoint", expFuture, actualFuture );
+
+        InOrder inOrder = inOrder( mockMountInstance, mockTransaction );
+        inOrder.verify( mockMountInstance ).beginTransaction();
+        inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+        inOrder.verify( mockTransaction ).commit();
+    }
+
+    @Test(expected=ResponseException.class)
+    public void testCommitConfigurationDataPostBehindMountPointAlreadyExists() {
+
+        when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.putConfigurationData( instanceID, dataNode );
+        when ( mockTransaction.readConfigurationData( instanceID ) )
+            .thenReturn( dataNode );
+        try {
+            brokerFacade.commitConfigurationDataPostBehindMountPoint( mockMountInstance,
+                    instanceID, dataNode );
+        } catch (ResponseException e) {
+            assertEquals("Unexpect Exception Status -> "
+                    + "http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48",
+                    e.getResponse().getStatus(), Status.CONFLICT.getStatusCode());
+            throw e;
+        }
+    }
+
+    @Test
+    public void testCommitConfigurationDataDelete() {
+        Future<RpcResult<TransactionStatus>> expFuture =  Futures.immediateFuture( null );
+
+        when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.removeConfigurationData( instanceID );
+        when( mockTransaction.commit() ).thenReturn( expFuture );
+
+        Future<RpcResult<TransactionStatus>> actualFuture =
+                             brokerFacade.commitConfigurationDataDelete( instanceID );
+
+        assertSame( "commitConfigurationDataDelete", expFuture, actualFuture );
+
+        InOrder inOrder = inOrder( dataBroker, mockTransaction );
+        inOrder.verify( dataBroker ).beginTransaction();
+        inOrder.verify( mockTransaction ).removeConfigurationData( instanceID );
+        inOrder.verify( mockTransaction ).commit();
+    }
+
+    @Test
+    public void testCommitConfigurationDataDeleteBehindMountPoint() {
+        Future<RpcResult<TransactionStatus>> expFuture =  Futures.immediateFuture( null );
+
+        when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+        mockTransaction.removeConfigurationData( instanceID );
+        when( mockTransaction.commit() ).thenReturn( expFuture );
+
+        Future<RpcResult<TransactionStatus>> actualFuture =
+                             brokerFacade.commitConfigurationDataDeleteBehindMountPoint(
+                                                              mockMountInstance, instanceID );
+
+        assertSame( "commitConfigurationDataDeleteBehindMountPoint", expFuture, actualFuture );
+
+        InOrder inOrder = inOrder( mockMountInstance, mockTransaction );
+        inOrder.verify( mockMountInstance ).beginTransaction();
+        inOrder.verify( mockTransaction ).removeConfigurationData( instanceID );
+        inOrder.verify( mockTransaction ).commit();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testRegisterToListenDataChanges() {
+        ListenerAdapter listener = Notificator.createListener( instanceID, "stream" );
+
+        ListenerRegistration<DataChangeListener> mockRegistration = mock( ListenerRegistration.class );
+        when( dataBroker.registerDataChangeListener( instanceID, listener ) )
+            .thenReturn( mockRegistration );
+
+        brokerFacade.registerToListenDataChanges( listener );
+
+        verify( dataBroker ).registerDataChangeListener( instanceID, listener );
+
+        assertEquals( "isListening", true, listener.isListening() );
+
+        brokerFacade.registerToListenDataChanges( listener );
+        verifyNoMoreInteractions( dataBroker );
+    }
+}
index 320a7f9d08b1f80d3465e7a9570df2044831563a..4198e20b838e15391c650f5ffd34afdcc5693840 100644 (file)
@@ -234,7 +234,7 @@ public class RestGetOperationTest extends JerseyTest {
         response = target(uri).request("application/yang.api+xml").get();
         responseBody = response.readEntity(String.class);
         assertNotNull(responseBody);
-        assertTrue(responseBody.contains("<streams xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\"/>"));
+        assertTrue(responseBody.contains("<streams xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\""));
     }
 
     // /modules/module
index a12f394e66553765f7d168005d7dae3c4a316ddf..1ec65e8f811235865372d6369827c192c800c71e 100644 (file)
@@ -21,7 +21,11 @@ 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.network.topology.topology.Link;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 /**
  * InventoryService provides functions related to Nodes & NodeConnectors.
index ecf116b171993659a0c42ae5e1ba9e21c19ea24d..b4ea94242c66bef9ad6879e396c9c6976afd86f0 100644 (file)
@@ -19,7 +19,8 @@ import org.opendaylight.controller.sal.packet.RawPacket;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.NetUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.address.tracker.rev140402.l2.addresses.L2Address;
index 79a9ea3f0e3be43035a8290291477f4a8fabd20a..f6a8306a98b6a71650ffcbc7b06a331a184dbd32 100644 (file)
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Export-Package>org.opendaylight.controller.sample.toaster.provider.api,
-                            org.opendaylight.controller.config.yang.toaster-consumer,</Export-Package>
-            <Import-Package>*</Import-Package>
-          </instructions>
-        </configuration>
       </plugin>
       <plugin>
         <groupId>org.opendaylight.yangtools</groupId>
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java
new file mode 100644 (file)
index 0000000..4dc3645
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+* Generated file
+
+* Generated from: yang module name: toaster-consumer-impl  yang module local name: toaster-consumer-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Feb 05 11:31:30 CET 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.kitchen_service.impl;
+
+import org.opendaylight.controller.config.yang.config.kitchen_service.impl.AbstractKitchenServiceModule;
+import org.opendaylight.controller.sample.kitchen.api.EggsType;
+import org.opendaylight.controller.sample.kitchen.api.KitchenService;
+import org.opendaylight.controller.sample.kitchen.impl.KitchenServiceImpl;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+*
+*/
+public final class KitchenServiceModule extends AbstractKitchenServiceModule {
+    private static final Logger log = LoggerFactory.getLogger(KitchenServiceModule.class);
+
+    public KitchenServiceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public KitchenServiceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            KitchenServiceModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    protected void customValidation(){
+        // No need to validate dependencies, since all dependencies have mandatory true flag in yang
+        // config-subsystem will perform the validation
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        ToasterService toasterService = getRpcRegistryDependency().getRpcService(ToasterService.class);
+
+        final KitchenServiceImpl kitchenService = new KitchenServiceImpl(toasterService);
+
+        final Registration<NotificationListener> toasterListenerReg =
+                getNotificationServiceDependency().registerNotificationListener( kitchenService );
+
+        final KitchenServiceRuntimeRegistration runtimeReg =
+                getRootRuntimeBeanRegistratorWrapper().register( kitchenService );
+
+        final class AutoCloseableKitchenService implements KitchenService, AutoCloseable {
+
+            @Override
+            public void close() throws Exception {
+                toasterListenerReg.close();
+                runtimeReg.close();
+                log.info("Toaster consumer (instance {}) torn down.", this);
+            }
+
+            @Override
+            public boolean makeBreakfast( EggsType eggs, Class<? extends ToastType> toast, int toastDoneness ) {
+                return kitchenService.makeBreakfast( eggs, toast, toastDoneness );
+            }
+        }
+
+        AutoCloseable ret = new AutoCloseableKitchenService();
+        log.info("KitchenService (instance {}) initialized.", ret );
+        return ret;
+    }
+}
@@ -7,12 +7,14 @@
 *
 * Do not modify this file unless it is present under src/main directory
 */
-package org.opendaylight.controller.config.yang.config.toaster_consumer.impl;
+package org.opendaylight.controller.config.yang.config.kitchen_service.impl;
+
+import org.opendaylight.controller.config.yang.config.kitchen_service.impl.AbstractKitchenServiceModuleFactory;
 
 /**
 *
 */
-public class ToasterConsumerModuleFactory extends org.opendaylight.controller.config.yang.config.toaster_consumer.impl.AbstractToasterConsumerModuleFactory
+public class KitchenServiceModuleFactory extends AbstractKitchenServiceModuleFactory
 {
 
 
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/toaster_consumer/impl/ToasterConsumerModule.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/toaster_consumer/impl/ToasterConsumerModule.java
deleted file mode 100644 (file)
index 486cdcf..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
-* Generated file
-
-* Generated from: yang module name: toaster-consumer-impl  yang module local name: toaster-consumer-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Feb 05 11:31:30 CET 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.controller.config.yang.config.toaster_consumer.impl;
-
-import org.opendaylight.controller.sal.binding.api.NotificationListener;
-import org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer;
-import org.opendaylight.controller.sample.toaster.provider.impl.ToastConsumerImpl;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastDone;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
-import org.opendaylight.yangtools.concepts.Registration;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
-*
-*/
-public final class ToasterConsumerModule extends org.opendaylight.controller.config.yang.config.toaster_consumer.impl.AbstractToasterConsumerModule
- {
-    private static final Logger log = LoggerFactory.getLogger(ToasterConsumerModule.class);
-
-    public ToasterConsumerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-        super(identifier, dependencyResolver);
-    }
-
-    public ToasterConsumerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
-            ToasterConsumerModule oldModule, java.lang.AutoCloseable oldInstance) {
-
-        super(identifier, dependencyResolver, oldModule, oldInstance);
-    }
-
-    @Override
-    protected void customValidation(){
-        // No need to validate dependencies, since all dependencies have mandatory true flag in yang
-        // config-subsystem will perform the validation
-    }
-
-    @Override
-    public java.lang.AutoCloseable createInstance() {
-        ToasterService toasterService = getRpcRegistryDependency().getRpcService(ToasterService.class);
-
-        final ToastConsumerImpl consumer = new ToastConsumerImpl(toasterService);
-        final Registration<NotificationListener<ToastDone>> notificationRegistration = getNotificationServiceDependency()
-                .registerNotificationListener(ToastDone.class, consumer);
-
-        final ToasterConsumerRuntimeRegistration runtimeRegistration = getRootRuntimeBeanRegistratorWrapper().register(consumer);
-
-        final class AutoCloseableToastConsumer implements AutoCloseable, ToastConsumer {
-
-            @Override
-            public void close() throws Exception {
-                runtimeRegistration.close();
-                notificationRegistration.close();
-                log.info("Toaster consumer (instance {}) torn down.", this);
-            }
-
-            @Override
-            public boolean createToast(Class<? extends ToastType> type, int doneness) {
-                return consumer.createToast(type, doneness);
-            }
-        }
-
-        AutoCloseable ret = new AutoCloseableToastConsumer();
-        log.info("Toaster consumer (instance {}) initialized.", ret);
-        return ret;
-    }
-}
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/api/EggsType.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/api/EggsType.java
new file mode 100644 (file)
index 0000000..d9c7f45
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sample.kitchen.api;
+
+public enum EggsType {
+    SCRAMBLED,
+    OVER_EASY,
+    POACHED
+}
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/api/KitchenService.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/api/KitchenService.java
new file mode 100644 (file)
index 0000000..ef9c122
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.sample.kitchen.api;
+
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
+
+public interface KitchenService {
+    boolean makeBreakfast( EggsType eggs, Class<? extends ToastType> toast, int toastDoneness );
+}
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java
new file mode 100644 (file)
index 0000000..911a8c8
--- /dev/null
@@ -0,0 +1,84 @@
+package org.opendaylight.controller.sample.kitchen.impl;
+
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
+import org.opendaylight.controller.sample.kitchen.api.EggsType;
+import org.opendaylight.controller.sample.kitchen.api.KitchenService;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBread;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
+
+    private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class );
+
+    private final ToasterService toaster;
+
+    private volatile boolean toasterOutOfBread;
+
+    public KitchenServiceImpl(ToasterService toaster) {
+        this.toaster = toaster;
+    }
+
+    @Override
+    public boolean makeBreakfast( EggsType eggs, Class<? extends ToastType> toast, int toastDoneness ) {
+
+        if( toasterOutOfBread )
+        {
+            log.info( "We're out of toast but we can make eggs" );
+            return true;
+        }
+
+        // Access the ToasterService to make the toast.
+        // We don't actually make the eggs for this example - sorry.
+        MakeToastInputBuilder toastInput = new MakeToastInputBuilder();
+        toastInput.setToasterDoneness( (long) toastDoneness);
+        toastInput.setToasterToastType( toast );
+
+        try {
+            RpcResult<Void> result = toaster.makeToast( toastInput.build() ).get();
+
+            if( result.isSuccessful() ) {
+                log.info( "makeToast succeeded" );
+            } else {
+                log.warn( "makeToast failed: " + result.getErrors() );
+            }
+
+            return result.isSuccessful();
+        } catch( InterruptedException | ExecutionException e ) {
+            log.warn( "Error occurred during toast creation" );
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean makeScrambledWithWheat() {
+        return makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 );
+    }
+
+    /**
+     * Implemented from the ToasterListener interface.
+     */
+    @Override
+    public void onToasterOutOfBread( ToasterOutOfBread notification ) {
+        log.info( "ToasterOutOfBread notification" );
+        toasterOutOfBread = true;
+    }
+
+    /**
+     * Implemented from the ToasterListener interface.
+     */
+    @Override
+    public void onToasterRestocked( ToasterRestocked notification ) {
+        log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );
+        toasterOutOfBread = false;
+    }
+}
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/toaster/provider/api/ToastConsumer.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/toaster/provider/api/ToastConsumer.java
deleted file mode 100644 (file)
index afc972b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sample.toaster.provider.api;
-
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
-
-public interface ToastConsumer {
-       
-       boolean createToast(Class<? extends ToastType> type,int doneness);
-
-}
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/toaster/provider/impl/ToastConsumerImpl.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/toaster/provider/impl/ToastConsumerImpl.java
deleted file mode 100644 (file)
index 5a4b45c..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sample.toaster.provider.impl;
-
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.config.yang.config.toaster_consumer.impl.ToasterConsumerRuntimeMXBean;
-import org.opendaylight.controller.sal.binding.api.NotificationListener;
-import org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.*;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ToastConsumerImpl implements
-        ToastConsumer,
-        NotificationListener<ToastDone>,ToasterConsumerRuntimeMXBean {
-
-    private static final Logger log = LoggerFactory.getLogger(ToastConsumerImpl.class);
-
-    private ToasterService toaster;
-
-    public ToastConsumerImpl(ToasterService toaster) {
-        this.toaster = toaster;
-    }
-
-    @Override
-    public boolean createToast(Class<? extends ToastType> type, int doneness) {
-        MakeToastInputBuilder toastInput = new MakeToastInputBuilder();
-        toastInput.setToasterDoneness((long) doneness);
-        toastInput.setToasterToastType(type);
-
-        try {
-            RpcResult<Void> result = toaster.makeToast(toastInput.build()).get();
-
-            if (result.isSuccessful()) {
-                log.trace("Toast was successfully finished");
-            } else {
-                log.warn("Toast was not successfully finished");
-            }
-            return result.isSuccessful();
-        } catch (InterruptedException | ExecutionException e) {
-            log.warn("Error occurred during toast creation");
-        }
-        return false;
-
-    }
-
-    @Override
-    public void onNotification(ToastDone notification) {
-        log.trace("ToastDone Notification Received: {} ",notification.getToastStatus());
-    }
-
-    @Override
-    public Boolean makeHashBrownToast(Integer doneness) {
-        return createToast(HashBrown.class, doneness);
-    }
-}
similarity index 55%
rename from opendaylight/md-sal/samples/toaster-consumer/src/main/yang/toaster-consumer-impl.yang
rename to opendaylight/md-sal/samples/toaster-consumer/src/main/yang/kitchen-service-impl.yang
index 8bc1a5cc22ba1f0e1ca2e82af68961bedebcb71e..d22dfc619a30327612e7e72b76e3bfb22786f97f 100644 (file)
@@ -1,35 +1,40 @@
 // vi: set smarttab et sw=4 tabstop=4:
-module toaster-consumer-impl {
+module kitchen-service-impl {
 
     yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl";
-    prefix "toaster-consumer-impl";
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl";
+    prefix "kitchen-service-impl";
 
     import config { prefix config; revision-date 2013-04-05; }
     import rpc-context { prefix rpcx; revision-date 2013-06-17; }
 
-    import toaster-consumer { prefix toaster-consumer; revision-date 2014-01-31; }
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
 
     description
         "This module contains the base YANG definitions for
-        toaster-consumer impl implementation.";
+        kitchen-service impl implementation.";
 
     revision "2014-01-31" {
         description
             "Initial revision.";
     }
 
-    // This is the definition of a service implementation
-    identity toaster-consumer-impl {
+    // This is the definition of kitchen service interface identity.
+    identity kitchen-service {
+        base "config:service-type";
+        config:java-class "org.opendaylight.controller.sample.kitchen.api.KitchenService";
+    }
+
+    // This is the definition of kitchen service implementation module identity. 
+    identity kitchen-service-impl {
             base config:module-type;
-            config:provided-service toaster-consumer:toaster-consumer;
-            config:java-name-prefix ToasterConsumer;
+            config:provided-service kitchen-service;
+            config:java-name-prefix KitchenService;
     }
 
     augment "/config:modules/config:module/config:configuration" {
-        case toaster-consumer-impl {
-            when "/config:modules/config:module/config:type = 'toaster-consumer-impl'";
+        case kitchen-service-impl {
+            when "/config:modules/config:module/config:type = 'kitchen-service-impl'";
 
             container rpc-registry {
                 uses config:service-ref {
@@ -48,30 +53,31 @@ module toaster-consumer-impl {
                     }
                 }
             }
-
         }
     }
-
+    
     augment "/config:modules/config:module/config:state" {
-        case toaster-consumer-impl {
-            when "/config:modules/config:module/config:type = 'toaster-consumer-impl'";
-            rpcx:rpc-context-instance "make-hash-brown-toast-rpc";
+        case kitchen-service-impl {
+            when "/config:modules/config:module/config:type = 'kitchen-service-impl'";
+            
+            rpcx:rpc-context-instance "make-scrambled-with-wheat-rpc";
         }
     }
 
-    identity make-hash-brown-toast-rpc;
+    identity make-scrambled-with-wheat-rpc;
 
-    rpc make-hash-brown-toast {
+    rpc make-scrambled-with-wheat  {
+        description
+          "Shortcut JMX call to make breakfast with scrambled eggs and wheat toast for testing.";
+          
         input {
             uses rpcx:rpc-context-ref {
                 refine context-instance {
-                    rpcx:rpc-context-instance make-hash-brown-toast-rpc;
+                    rpcx:rpc-context-instance make-scrambled-with-wheat-rpc;
                 }
             }
-            leaf doneness {
-                type uint16;
-            }
         }
+        
         output {
             leaf result {
                 type boolean;
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/yang/toaster-consumer.yang b/opendaylight/md-sal/samples/toaster-consumer/src/main/yang/toaster-consumer.yang
deleted file mode 100644 (file)
index c050ee8..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// vi: set smarttab et sw=4 tabstop=4:
-module toaster-consumer {
-
-    yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer";
-    prefix "toaster-consumer";
-
-    import config { prefix config; revision-date 2013-04-05; }
-
-    description
-        "This module contains the base YANG definitions for
-        toaster-consumer services.";
-
-    revision "2014-01-31" {
-        description
-            "Initial revision.";
-    }
-
-    // This is the definition of a service
-    identity toaster-consumer {
-
-        base "config:service-type";
-
-        config:java-class "org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer";
-    }
-}
\ No newline at end of file
index eb826055295d68bf7873edfbd3008175db002604..907b35475f80f3565e18d2965885ff505bb55d6e 100644 (file)
@@ -10,7 +10,8 @@ package org.opendaylight.controller.sample.toaster.it;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer;
+import org.opendaylight.controller.sample.kitchen.api.EggsType;
+import org.opendaylight.controller.sample.kitchen.api.KitchenService;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.HashBrown;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WhiteBread;
 import org.ops4j.pax.exam.Configuration;
@@ -23,6 +24,7 @@ import org.ops4j.pax.exam.util.PathUtils;
 import javax.inject.Inject;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
+
 import java.lang.management.ManagementFactory;
 
 import static org.junit.Assert.assertEquals;
@@ -42,7 +44,7 @@ public class ToasterTest {
 
     @Inject
     @Filter(timeout=60*1000)
-    ToastConsumer toastConsumer;
+    KitchenService kitchenService;
 
     @Configuration
     public Option[] config() {
@@ -86,7 +88,6 @@ public class ToasterTest {
     public void testToaster() throws Exception {
 
         MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
-        ObjectName consumerOn = new ObjectName("org.opendaylight.controller:instanceName=toaster-consumer-impl,type=RuntimeBean,moduleFactoryName=toaster-consumer-impl");
         ObjectName providerOn = new ObjectName("org.opendaylight.controller:instanceName=toaster-provider-impl,type=RuntimeBean,moduleFactoryName=toaster-provider-impl");
 
         long toastsMade = (long) platformMBeanServer.getAttribute(providerOn, "ToastsMade");
@@ -95,17 +96,14 @@ public class ToasterTest {
         boolean toasts = true;
 
         // Make toasts using OSGi service
-        toasts &= toastConsumer.createToast(HashBrown.class, 4);
-        toasts &= toastConsumer.createToast(WhiteBread.class, 8);
-
-        // Make toast using JMX/config-subsystem
-        toasts &= (Boolean)platformMBeanServer.invoke(consumerOn, "makeHashBrownToast", new Object[]{4}, new String[]{Integer.class.getName()});
+        toasts &= kitchenService.makeBreakfast( EggsType.SCRAMBLED, HashBrown.class, 4);
+        toasts &= kitchenService.makeBreakfast( EggsType.POACHED, WhiteBread.class, 8 );
 
-        Assert.assertTrue("Not all toasts done by " + toastConsumer, toasts);
+        Assert.assertTrue("Not all toasts done by " + kitchenService, toasts);
 
         // Verify toasts made count on provider via JMX/config-subsystem
         toastsMade = (long) platformMBeanServer.getAttribute(providerOn, "ToastsMade");
-        assertEquals(3, toastsMade);
+        assertEquals(2, toastsMade);
     }
 
 }
index 7a282db025312f81bb3d5662ddd34bae1a9f8da3..c5a2a0d340cfbfb982d62da396bc7bda2c48b178 100644 (file)
@@ -3,7 +3,7 @@
     <snapshots>
         <snapshot>
             <required-capabilities>
-                <capability>urn:opendaylight:l2:types?module=opendaylight-l2-types&amp;revision=2013-08-27</capability>
+                <!-- <capability>urn:opendaylight:l2:types?module=opendaylight-l2-types&amp;revision=2013-08-27</capability>-->
                 <capability>
                     urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28
                 </capability>
                     urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28
                 </capability>
                 <capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&amp;revision=2013-07-16</capability>
-                <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&amp;revision=2013-07-09
-                </capability>
+                <!-- <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&amp;revision=2013-07-09</capability>-->
                 <capability>
                     urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28
                 </capability>
                 <capability>http://netconfcentral.org/ns/toaster?module=toaster&amp;revision=2009-11-20</capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer?module=toaster-consumer&amp;revision=2014-01-31</capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl?module=toaster-consumer-impl&amp;revision=2014-01-31</capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider?module=toaster-provider&amp;revision=2014-01-31</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&amp;revision=2014-01-31</capability>
                 <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&amp;revision=2014-01-31</capability>
 
             </required-capabilities>
                                 <name>binding-rpc-broker</name>
                             </rpc-registry>
 
+                            <data-broker>
+                              <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                              <name>ref_binding-data-broker</name>
+                            </data-broker>
+                    
                             <notification-service>
                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
                                     binding:binding-notification-service
                         </module>
 
                         <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl">
-                                prefix:toaster-consumer-impl
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+                                prefix:kitchen-service-impl
                             </type>
-                            <name>toaster-consumer-impl</name>
+                            <name>kitchen-service-impl</name>
 
                             <rpc-registry>
                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
                     </modules>
 
                     <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                        <service>
+                          <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+                            kitchen:kitchen-service
+                          </type>
+                          <instance>
+                            <name>kitchen-service</name>
+                            <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
+                          </instance>
+                        </service>
                         <service>
                             <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
                                 dom:schema-service
index d9bb36eb8ec6d1ca97032e3328cbb72a9879f1bf..bd8e89fd7a5ab99ddb1246a167d0b142f446a07f 100644 (file)
 package org.opendaylight.controller.config.yang.config.toaster_provider.impl;
 
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sample.toaster.provider.OpendaylightToaster;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterData;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +47,13 @@ public final class ToasterProviderModule extends org.opendaylight.controller.con
 
         // Register to md-sal
         opendaylightToaster.setNotificationProvider(getNotificationServiceDependency());
-        opendaylightToaster.setDataProvider(getDataBrokerDependency());
+
+        DataProviderService dataBrokerService = getDataBrokerDependency();
+        opendaylightToaster.setDataProvider(dataBrokerService);
+
+        final ListenerRegistration<DataChangeListener> dataChangeListenerRegistration =
+                dataBrokerService.registerDataChangeListener( OpendaylightToaster.TOASTER_IID, opendaylightToaster );
+
         final BindingAwareBroker.RpcRegistration<ToasterService> rpcRegistration = getRpcRegistryDependency()
                 .addRpcImplementation(ToasterService.class, opendaylightToaster);
 
@@ -56,20 +63,16 @@ public final class ToasterProviderModule extends org.opendaylight.controller.con
 
         // Wrap toaster as AutoCloseable and close registrations to md-sal at
         // close()
-        final class AutoCloseableToaster implements AutoCloseable, ToasterData {
+        final class AutoCloseableToaster implements AutoCloseable {
 
             @Override
             public void close() throws Exception {
+                dataChangeListenerRegistration.close();
                 rpcRegistration.close();
                 runtimeReg.close();
                 opendaylightToaster.close();
                 log.info("Toaster provider (instance {}) torn down.", this);
             }
-
-            @Override
-            public Toaster getToaster() {
-                return opendaylightToaster.getToaster();
-            }
         }
 
         AutoCloseable ret = new AutoCloseableToaster();
index 2dab924e7709dc74fcb3047272d068f9e459c2d5..b4da5a3d226f05bfd02fe21890ea0307e7efb2ce 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.sample.toaster.provider;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -16,19 +17,24 @@ import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.opendaylight.controller.config.yang.config.toaster_provider.impl.ToasterProviderRuntimeMXBean;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastDone.ToastStatus;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastDoneBuilder;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster.ToasterStatus;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.RestockToasterInput;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterBuilder;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterData;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBreadBuilder;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestockedBuilder;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -37,84 +43,179 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.util.concurrent.Futures;
 
-public class OpendaylightToaster implements ToasterData, ToasterService, ToasterProviderRuntimeMXBean, AutoCloseable {
+public class OpendaylightToaster implements ToasterService, ToasterProviderRuntimeMXBean,
+                                            DataChangeListener, AutoCloseable {
 
-    private static final Logger log = LoggerFactory.getLogger(OpendaylightToaster.class);
-    private static final InstanceIdentifier<Toaster>  toasterIID = InstanceIdentifier.builder(Toaster.class).build();
+    private static final Logger LOG = LoggerFactory.getLogger(OpendaylightToaster.class);
 
-    private static final DisplayString toasterManufacturer = new DisplayString("Opendaylight");
-    private static final DisplayString toasterModelNumber = new DisplayString("Model 1 - Binding Aware");
+    public static final InstanceIdentifier<Toaster> TOASTER_IID = InstanceIdentifier.builder(Toaster.class).build();
+
+    private static final DisplayString TOASTER_MANUFACTURER = new DisplayString("Opendaylight");
+    private static final DisplayString TOASTER_MODEL_NUMBER = new DisplayString("Model 1 - Binding Aware");
 
     private NotificationProviderService notificationProvider;
     private DataBrokerService dataProvider;
+
     private final ExecutorService executor;
 
-    private Future<RpcResult<Void>> currentTask;
+    // As you will see we are using multiple threads here. Therefore we need to be careful about concurrency.
+    // In this case we use the taskLock to provide synchronization for the current task.
+    private volatile Future<RpcResult<Void>> currentTask;
+    private final Object taskLock = new Object();
+
+    private final AtomicLong amountOfBreadInStock = new AtomicLong( 100 );
+
+    private final AtomicLong toastsMade = new AtomicLong(0);
+
+    // Thread safe holder for our darkness multiplier.
+    private final AtomicLong darknessFactor = new AtomicLong( 1000 );
 
     public OpendaylightToaster() {
         executor = Executors.newFixedThreadPool(1);
     }
 
+    public void setNotificationProvider(NotificationProviderService salService) {
+        this.notificationProvider = salService;
+    }
+
+    public void setDataProvider(DataBrokerService salDataProvider) {
+        this.dataProvider = salDataProvider;
+        updateStatus();
+    }
+
+    /**
+     * Implemented from the AutoCloseable interface.
+     */
     @Override
-    public synchronized Toaster getToaster() {
-        ToasterBuilder tb = new ToasterBuilder();
-        tb //
-        .setToasterManufacturer(toasterManufacturer) //
-        .setToasterModelNumber(toasterModelNumber) //
-        .setToasterStatus(currentTask == null ? ToasterStatus.Up : ToasterStatus.Down);
+    public void close() throws ExecutionException, InterruptedException {
+        // When we close this service we need to shutdown our executor!
+        executor.shutdown();
 
+        if (dataProvider != null) {
+            final DataModificationTransaction t = dataProvider.beginTransaction();
+            t.removeOperationalData(TOASTER_IID);
+            t.commit().get();
+        }
+    }
+
+    private Toaster buildToaster() {
+        // We don't need to synchronize on currentTask here b/c it's declared volatile and
+        // we're just doing a read.
+        boolean isUp = currentTask == null;
+
+        // note - we are simulating a device whose manufacture and model are
+        // fixed (embedded) into the hardware.
+        // This is why the manufacture and model number are hardcoded.
+        ToasterBuilder tb = new ToasterBuilder();
+        tb.setToasterManufacturer(TOASTER_MANUFACTURER).setToasterModelNumber(TOASTER_MODEL_NUMBER)
+                .setToasterStatus(isUp ? ToasterStatus.Up : ToasterStatus.Down);
         return tb.build();
     }
 
+    /**
+     * Implemented from the DataChangeListener interface.
+     */
     @Override
-    public synchronized Future<RpcResult<Void>> cancelToast() {
-        if (currentTask != null) {
-            cancelToastImpl();
+    public void onDataChanged( DataChangeEvent<InstanceIdentifier<?>, DataObject> change ) {
+        DataObject dataObject = change.getUpdatedConfigurationData().get( TOASTER_IID );
+        if( dataObject instanceof Toaster )
+        {
+            Toaster toaster = (Toaster) dataObject;
+            Long darkness = toaster.getDarknessFactor();
+            if( darkness != null )
+            {
+                darknessFactor.set( darkness );
+            }
         }
-        return null;
     }
 
+    /**
+     * RestConf RPC call implemented from the ToasterService interface.
+     */
     @Override
-    public synchronized Future<RpcResult<Void>> makeToast(MakeToastInput input) {
-        log.debug("makeToast - Received input for toast");
-        logToastInput(input);
-        if (currentTask != null) {
-            return inProgressError();
+    public Future<RpcResult<Void>> cancelToast() {
+        synchronized (taskLock) {
+            if (currentTask != null) {
+                currentTask.cancel(true);
+                currentTask = null;
+            }
         }
-        currentTask = executor.submit(new MakeToastTask(input));
-        updateStatus();
-        return currentTask;
+        // Always return success from the cancel toast call.
+        return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true, Collections.<RpcError> emptySet()));
     }
 
-    private Future<RpcResult<Void>> inProgressError() {
-        RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Collections.<RpcError> emptySet());
-        return Futures.immediateFuture(result);
-    }
+    /**
+     * RestConf RPC call implemented from the ToasterService interface.
+     */
+    @Override
+    public Future<RpcResult<Void>> makeToast(MakeToastInput input) {
+        LOG.info("makeToast: " + input);
 
-    private void cancelToastImpl() {
-        currentTask.cancel(true);
-        ToastDoneBuilder toastDone = new ToastDoneBuilder();
-        toastDone.setToastStatus(ToastStatus.Cancelled);
-        notificationProvider.publish(toastDone.build());
-    }
+        synchronized (taskLock) {
+            if (currentTask != null) {
+                // return an error since we are already toasting some toast.
+                LOG.info( "Toaster is already making toast" );
 
-    public void setNotificationProvider(NotificationProviderService salService) {
-        this.notificationProvider = salService;
-    }
+                RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Arrays.asList(
+                        RpcErrors.getRpcError( null, null, null, null,
+                                               "Toaster is busy", null, null ) ) );
+                return Futures.immediateFuture(result);
+            }
+            else if( outOfBread() ) {
+                RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Arrays.asList(
+                        RpcErrors.getRpcError( null, null, null, null,
+                                               "Toaster is out of bread", null, null ) ) );
+                return Futures.immediateFuture(result);
+            }
+            else {
+                // Notice that we are moving the actual call to another thread,
+                // allowing this thread to return immediately.
+                // The MD-SAL design encourages asynchronus programming. If the
+                // caller needs to block until the call is
+                // complete then they can leverage the blocking methods on the
+                // Future interface.
+                currentTask = executor.submit(new MakeToastTask(input));
+            }
+        }
 
-    public void setDataProvider(DataBrokerService salDataProvider) {
-        this.dataProvider = salDataProvider;
         updateStatus();
+        return currentTask;
     }
 
-    private void logToastInput(MakeToastInput input) {
-        String toastType = input.getToasterToastType().getName();
-        String toastDoneness = input.getToasterDoneness().toString();
-        log.trace("Toast: {} doneness: {}", toastType, toastDoneness);
+    /**
+     * RestConf RPC call implemented from the ToasterService interface.
+     * Restocks the bread for the toaster, resets the toastsMade counter to 0, and sends a
+     * ToasterRestocked notification.
+     */
+    @Override
+    public Future<RpcResult<java.lang.Void>> restockToaster(RestockToasterInput input) {
+        LOG.info( "restockToaster: " + input );
+
+        synchronized( taskLock ) {
+            amountOfBreadInStock.set( input.getAmountOfBreadToStock() );
+
+            if( amountOfBreadInStock.get() > 0 ) {
+                ToasterRestocked reStockedNotification =
+                    new ToasterRestockedBuilder().setAmountOfBread( input.getAmountOfBreadToStock() ).build();
+                notificationProvider.publish( reStockedNotification );
+            }
+        }
+
+        return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true, Collections.<RpcError> emptySet()));
     }
 
-    private final AtomicLong toastsMade = new AtomicLong(0);
+    /**
+     * JMX RPC call implemented from the ToasterProviderRuntimeMXBean interface.
+     */
+    @Override
+    public void clearToastsMade() {
+        LOG.info( "clearToastsMade" );
+        toastsMade.set( 0 );
+    }
 
+    /**
+     * Accesssor method implemented from the ToasterProviderRuntimeMXBean interface.
+     */
     @Override
     public Long getToastsMade() {
         return toastsMade.get();
@@ -123,26 +224,22 @@ public class OpendaylightToaster implements ToasterData, ToasterService, Toaster
     private void updateStatus() {
         if (dataProvider != null) {
             final DataModificationTransaction t = dataProvider.beginTransaction();
-            t.removeOperationalData(toasterIID);
-            t.putOperationalData(toasterIID, getToaster());
+            t.removeOperationalData(TOASTER_IID);
+            t.putOperationalData(TOASTER_IID, buildToaster());
 
             try {
                 t.commit().get();
             } catch (InterruptedException | ExecutionException e) {
-                log.warn("Failed to update toaster status, operational otherwise", e);
+                LOG.warn("Failed to update toaster status, operational otherwise", e);
             }
         } else {
-            log.trace("No data provider configured, not updating status");
+            LOG.trace("No data provider configured, not updating status");
         }
     }
 
-    @Override
-    public void close() throws ExecutionException, InterruptedException {
-        if (dataProvider != null) {
-            final DataModificationTransaction t = dataProvider.beginTransaction();
-            t.removeOperationalData(toasterIID);
-            t.commit().get();
-        }
+    private boolean outOfBread()
+    {
+        return amountOfBreadInStock.get() == 0;
     }
 
     private class MakeToastTask implements Callable<RpcResult<Void>> {
@@ -154,19 +251,35 @@ public class OpendaylightToaster implements ToasterData, ToasterService, Toaster
         }
 
         @Override
-        public RpcResult<Void> call() throws InterruptedException {
-            Thread.sleep(1000 * toastRequest.getToasterDoneness());
+        public RpcResult<Void> call() {
+            try
+            {
+                // make toast just sleeps for n secondn per doneness level.
+                long darknessFactor = OpendaylightToaster.this.darknessFactor.get();
+                Thread.sleep(darknessFactor * toastRequest.getToasterDoneness());
 
-            ToastDoneBuilder notifyBuilder = new ToastDoneBuilder();
-            notifyBuilder.setToastStatus(ToastStatus.Done);
-            notificationProvider.publish(notifyBuilder.build());
-            log.debug("Toast Done");
-            logToastInput(toastRequest);
+            }
+            catch( InterruptedException e ) {
+                LOG.info( "Interrupted while making the toast" );
+            }
 
-            currentTask = null;
             toastsMade.incrementAndGet();
+
+            amountOfBreadInStock.getAndDecrement();
+            if( outOfBread() ) {
+                LOG.info( "Toaster is out of bread!" );
+
+                notificationProvider.publish( new ToasterOutOfBreadBuilder().build() );
+            }
+
+            synchronized (taskLock) {
+                currentTask = null;
+            }
+
             updateStatus();
 
+            LOG.debug("Toast done");
+
             return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
         }
     }
index 17b0c8d0f0f9b3361ba4f15c8782bf8afb8828aa..d6de5cfd17136d625a205b0b77122b2143c803fc 100644 (file)
@@ -6,7 +6,7 @@ module toaster-provider-impl {
     prefix "toaster-provider-impl";
 
     import config { prefix config; revision-date 2013-04-05; }
-    import toaster-provider { prefix toaster-provider; revision-date 2014-01-31; }
+    import rpc-context { prefix rpcx; revision-date 2013-06-17; }
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
 
     description
@@ -18,13 +18,15 @@ module toaster-provider-impl {
             "Initial revision.";
     }
 
-    // This is the definition of a service implementation
+    // This is the definition of the service implementation as a module identity.
     identity toaster-provider-impl {
             base config:module-type;
-            config:provided-service toaster-provider:toaster-provider;
+            
+            // Specifies the prefix for generated java classes.
             config:java-name-prefix ToasterProvider;
     }
 
+    // Augments the 'configuration' choice node under modules/module.
     augment "/config:modules/config:module/config:configuration" {
         case toaster-provider-impl {
             when "/config:modules/config:module/config:type = 'toaster-provider-impl'";
@@ -61,11 +63,27 @@ module toaster-provider-impl {
     augment "/config:modules/config:module/config:state" {
         case toaster-provider-impl {
             when "/config:modules/config:module/config:type = 'toaster-provider-impl'";
-
+            
             leaf toasts-made {
                 type uint32;
             }
+            
+            rpcx:rpc-context-instance "clear-toasts-made-rpc";
+        }
+    }
+
+    identity clear-toasts-made-rpc;
 
+    rpc clear-toasts-made  {
+        description
+          "JMX call to clear the toasts-made counter.";
+          
+        input {
+            uses rpcx:rpc-context-ref {
+                refine context-instance {
+                    rpcx:rpc-context-instance clear-toasts-made-rpc;
+                }
+            }
         }
     }
 }
diff --git a/opendaylight/md-sal/samples/toaster-provider/src/main/yang/toaster-provider.yang b/opendaylight/md-sal/samples/toaster-provider/src/main/yang/toaster-provider.yang
deleted file mode 100644 (file)
index a5fba07..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// vi: set smarttab et sw=4 tabstop=4:
-module toaster-provider {
-
-    yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider";
-    prefix "toaster-provider";
-
-    import config { prefix config; revision-date 2013-04-05; }
-
-    description
-        "This module contains the base YANG definitions for
-        toaster-provider services.";
-
-    revision "2014-01-31" {
-        description
-            "Initial revision.";
-    }
-
-    // This is the definition of a service
-    identity toaster-provider {
-
-        base "config:service-type";
-
-        config:java-class "org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterData";
-    }
-}
\ No newline at end of file
index 15c0ac83edea5e3f0bfd80a4889c859541b23f93..11b746f68170db5084357de7e9c93c81f0456511 100644 (file)
           "This variable indicates the current state of 
                the toaster.";
       }
+      
+      leaf darknessFactor {
+        type uint32;
+        config true;
+        default 1000;
+        description
+          "The darkness factor. Basically, the number of ms to multiple the doneness value by.";
+      }
     }  // container toaster
 
     rpc make-toast {
            if the toaster service is disabled.";
     }  // rpc cancel-toast
 
-    notification toastDone {
-      description
-        "Indicates that the toast in progress has completed.";
-      leaf toastStatus {
-        type enumeration {
-          enum "done" {
-            value 0;
-            description "The toast is done.";
-          }
-          enum "cancelled" {
-            value 1;
-            description
-              "The toast was cancelled.";
-          }
-          enum "error" {
-            value 2;
-            description
-              "The toaster service was disabled or
-                     the toaster is broken.";
-          }
+    rpc restock-toaster {
+        description
+          "Restocks the toaster with the amount of bread specified.";
+          
+        input {
+            leaf amountOfBreadToStock {
+                type uint32;
+                description
+                  "Indicates the amount of bread to re-stock";
+            }
         }
+    }
+    
+    notification toasterOutOfBread {
+      description
+        "Indicates that the toaster has run of out bread.";
+    }  // notification toasterOutOfStock
+    
+    notification toasterRestocked {
+      description
+        "Indicates that the toaster has run of out bread.";
+      leaf amountOfBread {
+        type uint32;
         description
-          "Indicates the final toast status";
+          "Indicates the amount of bread that was re-stocked";
       }
-    }  // notification toastDone
+    }  // notification toasterOutOfStock
+    
   }  // module toaster
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/pom.xml b/opendaylight/md-sal/test/sal-rest-connector-it/pom.xml
deleted file mode 100644 (file)
index 4a0a025..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>sal-test-parent</artifactId>
-        <groupId>org.opendaylight.controller.tests</groupId>
-        <version>1.0-SNAPSHOT</version>
-    </parent>
-    <artifactId>sal-rest-connector-it</artifactId>
-    <scm>
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-    </scm>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.ops4j.pax.exam</groupId>
-                <artifactId>maven-paxexam-plugin</artifactId>
-                <version>1.2.4</version>
-                <executions>
-                    <execution>
-                        <id>generate-config</id>
-                        <goals>
-                            <goal>generate-depends-file</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <pluginManagement>
-            <plugins>
-                <!--This plugin's configuration is used to store Eclipse
-                    m2e settings only. It has no influence on the Maven build itself. -->
-                <plugin>
-                    <groupId>org.eclipse.m2e</groupId>
-                    <artifactId>lifecycle-mapping</artifactId>
-                    <version>1.0.0</version>
-                    <configuration>
-                        <lifecycleMappingMetadata>
-                            <pluginExecutions>
-                                <pluginExecution>
-                                    <pluginExecutionFilter>
-                                        <groupId>
-                                            org.ops4j.pax.exam
-                                        </groupId>
-                                        <artifactId>
-                                            maven-paxexam-plugin
-                                        </artifactId>
-                                        <versionRange>
-                                            [1.2.4,)
-                                        </versionRange>
-                                        <goals>
-                                            <goal>
-                                                generate-depends-file
-                                            </goal>
-                                        </goals>
-                                    </pluginExecutionFilter>
-                                    <action>
-                                        <ignore></ignore>
-                                    </action>
-                                </pluginExecution>
-                            </pluginExecutions>
-                        </lifecycleMappingMetadata>
-                    </configuration>
-                </plugin>
-            </plugins>
-        </pluginManagement>
-    </build>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>logging.bridge</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>xtend-lib-osgi</artifactId>
-            <version>2.4.3</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>bundlescanner.implementation</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-rest-connector</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-netconf-connector</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-it</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-container-native</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-junit4</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-all</artifactId>
-           <version>${netty.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-link-mvn</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <version>1.7.2</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-core</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-core-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-service</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-manager</artifactId>
-            <version>0.2.2-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-flow-management</artifactId>
-            <version>1.0-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-            <version>4.0</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-binding</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-common</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-data-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>commons.northbound</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-            <scope>runtime</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-            <version>1.7.2</version>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <version>1.7.2</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-core</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-        <dependency>
-            <groupId>commons-codec</groupId>
-            <artifactId>commons-codec</artifactId>
-            <version>1.7</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>javax.servlet</artifactId>
-            <version>3.0.0.v201112011016</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>javax.servlet.jsp</artifactId>
-            <version>2.2.0.v201112011158</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.equinox.ds</artifactId>
-            <version>1.4.0.v20120522-1841</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.equinox.util</artifactId>
-            <version>1.0.400.v20120522-2049</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.osgi.services</artifactId>
-            <version>3.3.100.v20120522-1822</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.apache.felix.gogo.command</artifactId>
-            <version>0.8.0.v201108120515</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.apache.felix.gogo.runtime</artifactId>
-            <version>0.8.0.v201108120515</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.apache.felix.gogo.shell</artifactId>
-            <version>0.8.0.v201110170705</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.equinox.cm</artifactId>
-            <version>1.0.400.v20120522-1841</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.equinox.console</artifactId>
-            <version>1.0.0.v20120522-1841</version>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.equinox.launcher</artifactId>
-            <version>1.3.0.v20120522-1813</version>
-        </dependency>
-        <!-- Gemini Web -->
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.gemini.web.core</artifactId>
-            <version>${geminiweb.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.gemini.web.extender</artifactId>
-            <version>${geminiweb.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.gemini.web.tomcat</artifactId>
-            <version>${geminiweb.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.virgo.kernel.equinox.extensions</artifactId>
-            <version>${virgo.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.virgo.util.common</artifactId>
-            <version>${virgo.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.virgo.util.io</artifactId>
-            <version>${virgo.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.virgo.util.math</artifactId>
-            <version>${virgo.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.virgo.util.osgi</artifactId>
-            <version>${virgo.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.virgo.util.osgi.manifest</artifactId>
-            <version>${virgo.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>geminiweb</groupId>
-            <artifactId>org.eclipse.virgo.util.parser.manifest</artifactId>
-            <version>${virgo.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.dependencymanager</artifactId>
-            <version>3.1.0</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
-            <version>3.0.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.transaction</groupId>
-            <artifactId>jboss-transaction-api_1.1_spec</artifactId>
-            <version>1.0.1.Final</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.fileinstall</artifactId>
-            <version>3.1.6</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-            <version>3.1</version>
-        </dependency>
-        <dependency>
-            <groupId>virgomirror</groupId>
-            <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId>
-            <version>3.8.0.I20120518-2145</version>
-        </dependency>
-        <dependency>
-            <groupId>eclipselink</groupId>
-            <artifactId>javax.persistence</artifactId>
-            <version>2.0.4.v201112161009</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.activation</artifactId>
-            <version>1.1.0.v201211130549</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.annotation</artifactId>
-            <version>1.1.0.v201209060031</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.ejb</artifactId>
-            <version>3.1.1.v201204261316</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.el</artifactId>
-            <version>2.2.0.v201108011116</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.mail.glassfish</artifactId>
-            <version>1.4.1.v201108011116</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.xml.rpc</artifactId>
-            <version>1.1.0.v201005080400</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.catalina</artifactId>
-            <version>7.0.32.v201211201336</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.catalina.ha</artifactId>
-            <version>7.0.32.v201211201952</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.catalina.tribes</artifactId>
-            <version>7.0.32.v201211201952</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.coyote</artifactId>
-            <version>7.0.32.v201211201952</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.el</artifactId>
-            <version>7.0.32.v201211081135</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.jasper</artifactId>
-            <version>7.0.32.v201211201952</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.juli.extras</artifactId>
-            <version>7.0.32.v201211081135</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.tomcat.api</artifactId>
-            <version>7.0.32.v201211081135</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>org.apache.tomcat.util</artifactId>
-            <version>7.0.32.v201211201952</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.servlet.jsp.jstl</artifactId>
-            <version>1.2.0.v201105211821</version>
-        </dependency>
-        <dependency>
-            <groupId>orbit</groupId>
-            <artifactId>javax.servlet.jsp.jstl.impl</artifactId>
-            <version>1.2.0.v201210211230</version>
-        </dependency>
-        <!-- Add Pax Exam -->
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-container-native</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-junit4</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-link-mvn</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.url</groupId>
-            <artifactId>pax-url-aether</artifactId>
-            <version>${url.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ow2.asm</groupId>
-            <artifactId>asm-all</artifactId>
-            <version>4.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.asm</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.aop</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.context</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.context.support</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.core</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.beans</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.expression</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.web</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.aopalliance</groupId>
-            <artifactId>com.springsource.org.aopalliance</artifactId>
-            <version>1.0.0</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.web.servlet</artifactId>
-            <version>${spring.version}</version>
-        </dependency>
-        <!-- Spring security -->
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-config</artifactId>
-            <version>${spring-security.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-core</artifactId>
-            <version>${spring-security.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-web</artifactId>
-            <version>${spring-security.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-taglibs</artifactId>
-            <version>${spring-security.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>org.springframework.transaction</artifactId>
-            <version>${spring-security.version}</version>
-        </dependency>
-        <!-- Visual VM hook -->
-        <dependency>
-            <groupId>org.ow2.chameleon.management</groupId>
-            <artifactId>chameleon-mbeans</artifactId>
-            <version>1.0.0</version>
-        </dependency>
-        <!-- Jersey for JAXRS -->
-        <dependency>
-            <groupId>com.sun.jersey</groupId>
-            <artifactId>jersey-core</artifactId>
-            <version>${jersey.version}</version>
-        </dependency>
-        <!-- <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-servlet</artifactId>
-            <version>${jersey.version}</version> </dependency> -->
-        <dependency>
-            <groupId>com.sun.jersey</groupId>
-            <artifactId>jersey-server</artifactId>
-            <version>${jersey.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.sun.jersey</groupId>
-            <artifactId>jersey-client</artifactId>
-            <version>${jersey.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>eclipselink</groupId>
-            <artifactId>javax.resource</artifactId>
-            <version>1.5.0.v200906010428</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.thirdparty</groupId>
-            <artifactId>com.sun.jersey.jersey-servlet</artifactId>
-            <version>1.17</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.thirdparty</groupId>
-            <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
-            <version>7.0.42</version>
-        </dependency>
-
-
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-manager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-util</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>yang-jmx-generator</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>logback-config</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-file-xml-adapter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-impl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-util</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-mapping-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-netconf-connector</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>config-persister-impl</artifactId>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java
deleted file mode 100644 (file)
index 4a43e0c..0000000
+++ /dev/null
@@ -1,329 +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.test.restconf.it;
-
-import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.*;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-import static org.ops4j.pax.exam.CoreOptions.maven;
-
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
-import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.controller.test.sal.binding.it.TestHelper;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.CoreOptions;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.util.PathUtils;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.*;
-
-@RunWith(PaxExam.class)
-public class ServiceProviderController {
-
-    public static final String ODL = "org.opendaylight.controller";
-    public static final String YANG = "org.opendaylight.yangtools";
-    public static final String SAMPLE = "org.opendaylight.controller.samples";
-
-    private static QName CONFIG_MODULES = new QName(
-            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
-    private static QName CONFIG_SERVICES = new QName(
-            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
-    @Inject
-    BundleContext context;
-
-    @Inject
-    MountProvisionService mountService;
-
-    @Inject
-    DataBrokerService dataBroker;
-
-    @Test
-    public void properInitialized() throws Exception {
-
-        Map<QName, String> arg = Collections.singletonMap(InventoryUtils.INVENTORY_ID, "foo");
-
-        InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
-                .nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
-
-
-        InstanceIdentifier mountPointPath = path;
-
-        /** We retrive a mountpoint **/
-        MountProvisionInstance mountPoint = mountService.getMountPoint(mountPointPath);
-        CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
-                .toInstance());
-        assertNotNull(data);
-        assertEquals(CONFIG_MODULES, data.getNodeType());
-
-        CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
-        assertNotNull(data2);
-
-        InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
-
-        CompositeNode data3 = dataBroker.readOperationalData(fullPath);
-        assertNotNull(data3);
-        assertEquals(CONFIG_MODULES, data.getNodeType());
-
-        //Thread.sleep(30 * 60 * 1000); // Waiting for services to get wired.
-        //assertTrue(true);
-        // assertTrue(consumer.createToast(WhiteBread.class, 5));
-    }
-
-    @Configuration
-    public Option[] config() {
-        return options(
-                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
-                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
-                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
-                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
-
-                mdSalCoreBundles(),
-                baseModelBundles(),
-                flowCapableModelBundles(),
-                configMinumumBundles(),
-
-                // mavenBundle(ODL,
-                // "sal-binding-broker-impl").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-common").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
-                mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
-
-                mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
-
-                mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
-                // mavenBundle(SAMPLE,
-                // "zeromq-test-provider").versionAsInProject(), //
-                mavenBundle(ODL, "sal-rest-connector").versionAsInProject(), //
-                mavenBundle(ODL, "sal-netconf-connector").versionAsInProject(), //
-
-                mavenBundle(YANG, "concepts").versionAsInProject(),
-                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
-                mavenBundle(YANG, "yang-common").versionAsInProject(), //
-                mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
-                mavenBundle(YANG, "yang-data-impl").versionAsInProject(), //
-                mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
-                mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
-                mavenBundle(YANG, "yang-parser-api").versionAsInProject(),
-                mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
-
-                mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
-                mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
-                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
-
-                // systemProperty("logback.configurationFile").value(
-                // "file:" + PathUtils.getBaseDir() +
-                // "/src/test/resources/logback.xml"),
-                // To start OSGi console for inspection remotely
-                systemProperty("osgi.console").value("2401"),
-                systemProperty("org.eclipse.gemini.web.tomcat.config.path").value(
-                        PathUtils.getBaseDir() + "/src/test/resources/tomcat-server.xml"),
-
-                // setting default level. Jersey bundles will need to be started
-                // earlier.
-                systemProperty("osgi.bundles.defaultStartLevel").value("4"),
-
-                systemProperty("netconf.tcp.address").value("127.0.0.1"),
-                systemProperty("netconf.tcp.port").value("8383"),
-
-                systemProperty("netconf.tcp.client.address").value("127.0.0.1"),
-                systemProperty("netconf.tcp.client.port").value("8383"),
-
-                // Set the systemPackages (used by clustering)
-                systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
-
-                mavenBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.xerces", "2.11.0_1"),
-                mavenBundle("org.eclipse.birt.runtime.3_7_1", "org.apache.xml.resolver", "1.2.0"),
-
-                mavenBundle("org.slf4j", "jcl-over-slf4j").versionAsInProject(),
-                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
-                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
-                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
-                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
-                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
-                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "clustering.services").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "containermanager").versionAsInProject(),
-                // List all the opendaylight modules
-                mavenBundle("org.opendaylight.controller", "configuration").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "sal").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "switchmanager").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "usermanager").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "logging.bridge").versionAsInProject(),
-                // mavenBundle("org.opendaylight.controller",
-                // "clustering.test").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "bundlescanner").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller", "bundlescanner.implementation").versionAsInProject(),
-
-                // Northbound bundles
-                mavenBundle("org.opendaylight.controller", "commons.northbound").versionAsInProject(),
-
-                mavenBundle("com.fasterxml.jackson.core", "jackson-annotations").versionAsInProject(),
-                mavenBundle("com.fasterxml.jackson.core", "jackson-core").versionAsInProject(),
-                mavenBundle("com.fasterxml.jackson.core", "jackson-databind").versionAsInProject(),
-                mavenBundle("com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider").versionAsInProject(),
-                mavenBundle("com.fasterxml.jackson.module", "jackson-module-jaxb-annotations").versionAsInProject(),
-
-                mavenBundle("org.codehaus.jettison", "jettison").versionAsInProject(),
-
-                mavenBundle("commons-io", "commons-io").versionAsInProject(),
-
-                // mavenBundle("commons-fileupload",
-                // "commons-fileupload").versionAsInProject(),
-
-                mavenBundle("io.netty", "netty-handler").versionAsInProject(),
-                mavenBundle("io.netty", "netty-codec").versionAsInProject(),
-                mavenBundle("io.netty", "netty-buffer").versionAsInProject(),
-                mavenBundle("io.netty", "netty-transport").versionAsInProject(),
-                mavenBundle("io.netty", "netty-common").versionAsInProject(),
-
-                mavenBundle(ODL, "config-api").versionAsInProject(),
-                mavenBundle(ODL, "config-manager").versionAsInProject(),
-                mavenBundle(ODL, "config-util").versionAsInProject(),
-                mavenBundle(ODL, "yang-jmx-generator").versionAsInProject(),
-                mavenBundle(ODL, "logback-config").versionAsInProject(),
-                mavenBundle(ODL, "config-persister-api").versionAsInProject(),
-                // mavenBundle(ODL,"config-persister-file-xml-adapter").versionAsInProject(),
-                mavenBundle(ODL, "protocol-framework").versionAsInProject(),
-                mavenBundle(ODL, "netconf-api").versionAsInProject(),
-                mavenBundle(ODL, "netconf-impl").versionAsInProject(),
-                mavenBundle(ODL, "netconf-client").versionAsInProject(),
-                mavenBundle(ODL, "netconf-util").versionAsInProject(),
-                mavenBundle(ODL + ".thirdparty", "ganymed").versionAsInProject(),
-                mavenBundle(ODL, "netconf-mapping-api").versionAsInProject(),
-                mavenBundle(ODL, "config-netconf-connector").versionAsInProject(),
-                mavenBundle(ODL, "config-persister-impl").versionAsInProject(),
-
-                mavenBundle(YANG, "binding-generator-spi").versionAsInProject(), //
-                mavenBundle(YANG, "binding-model-api").versionAsInProject(), //
-                mavenBundle(YANG, "binding-generator-util").versionAsInProject(),
-                mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
-                mavenBundle(YANG, "binding-type-provider").versionAsInProject(),
-
-                mavenBundle("equinoxSDK381", "javax.servlet").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "javax.servlet.jsp").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
-                mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.cm").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
-                mavenBundle("equinoxSDK381", "org.eclipse.equinox.launcher").versionAsInProject(),
-
-                mavenBundle("geminiweb", "org.eclipse.gemini.web.core").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.gemini.web.extender").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.gemini.web.tomcat").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.virgo.kernel.equinox.extensions").versionAsInProject().noStart(),
-                mavenBundle("geminiweb", "org.eclipse.virgo.util.common").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.virgo.util.io").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.virgo.util.math").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi.manifest").versionAsInProject(),
-                mavenBundle("geminiweb", "org.eclipse.virgo.util.parser.manifest").versionAsInProject(),
-
-                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
-                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager.shell").versionAsInProject(),
-
-                mavenBundle("com.google.code.gson", "gson").versionAsInProject(),
-                mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec").versionAsInProject(),
-                mavenBundle("org.apache.felix", "org.apache.felix.fileinstall").versionAsInProject(),
-                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
-                mavenBundle("commons-codec", "commons-codec").versionAsInProject(),
-                mavenBundle("virgomirror", "org.eclipse.jdt.core.compiler.batch").versionAsInProject(),
-                mavenBundle("eclipselink", "javax.persistence").versionAsInProject(),
-                mavenBundle("eclipselink", "javax.resource").versionAsInProject(),
-
-                mavenBundle("orbit", "javax.activation").versionAsInProject(),
-                mavenBundle("orbit", "javax.annotation").versionAsInProject(),
-                mavenBundle("orbit", "javax.ejb").versionAsInProject(),
-                mavenBundle("orbit", "javax.el").versionAsInProject(),
-                mavenBundle("orbit", "javax.mail.glassfish").versionAsInProject(),
-                mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
-                mavenBundle("orbit", "org.apache.catalina").versionAsInProject(),
-                // these are bundle fragments that can't be started on its own
-                mavenBundle("orbit", "org.apache.catalina.ha").versionAsInProject().noStart(),
-                mavenBundle("orbit", "org.apache.catalina.tribes").versionAsInProject().noStart(),
-                mavenBundle("orbit", "org.apache.coyote").versionAsInProject().noStart(),
-                mavenBundle("orbit", "org.apache.jasper").versionAsInProject().noStart(),
-
-                mavenBundle("orbit", "org.apache.el").versionAsInProject(),
-                mavenBundle("orbit", "org.apache.juli.extras").versionAsInProject(),
-                mavenBundle("orbit", "org.apache.tomcat.api").versionAsInProject(),
-                mavenBundle("orbit", "org.apache.tomcat.util").versionAsInProject().noStart(),
-                mavenBundle("orbit", "javax.servlet.jsp.jstl").versionAsInProject(),
-                mavenBundle("orbit", "javax.servlet.jsp.jstl.impl").versionAsInProject(),
-
-                mavenBundle("org.ops4j.pax.exam", "pax-exam-container-native").versionAsInProject(),
-                mavenBundle("org.ops4j.pax.exam", "pax-exam-junit4").versionAsInProject(),
-                mavenBundle("org.ops4j.pax.exam", "pax-exam-link-mvn").versionAsInProject(),
-                mavenBundle("org.ops4j.pax.url", "pax-url-aether").versionAsInProject(),
-
-                mavenBundle("org.ow2.asm", "asm-all").versionAsInProject(),
-
-                mavenBundle("org.springframework", "org.springframework.asm").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.aop").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.context").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.context.support").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.core").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.beans").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.expression").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.web").versionAsInProject(),
-
-                mavenBundle("org.aopalliance", "com.springsource.org.aopalliance").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.web.servlet").versionAsInProject(),
-                mavenBundle("org.springframework.security", "spring-security-config").versionAsInProject(),
-                mavenBundle("org.springframework.security", "spring-security-core").versionAsInProject(),
-                mavenBundle("org.springframework.security", "spring-security-web").versionAsInProject(),
-                mavenBundle("org.springframework.security", "spring-security-taglibs").versionAsInProject(),
-                mavenBundle("org.springframework", "org.springframework.transaction").versionAsInProject(),
-
-                mavenBundle("org.ow2.chameleon.management", "chameleon-mbeans").versionAsInProject(),
-                mavenBundle("org.opendaylight.controller.thirdparty", "com.sun.jersey.jersey-servlet")
-                        .versionAsInProject().startLevel(2),
-                mavenBundle("org.opendaylight.controller.thirdparty", "org.apache.catalina.filters.CorsFilter")
-                        .versionAsInProject().noStart(),
-
-                // Jersey needs to be started before the northbound application
-                // bundles, using a lower start level
-                mavenBundle("com.sun.jersey", "jersey-client").versionAsInProject(),
-                mavenBundle("com.sun.jersey", "jersey-server").versionAsInProject().startLevel(2),
-                mavenBundle("com.sun.jersey", "jersey-core").versionAsInProject().startLevel(2),
-                junitBundles());
-    }
-
-}
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/exam.properties b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/exam.properties
deleted file mode 100644 (file)
index d5f9ae1..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#pax.exam.system = default
-pax.exam.logging = none
-pax.exam.service.timeout = 5000
-
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/logback.xml b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 2d63ce5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<configuration scan="true">
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-      </pattern>
-    </encoder>
-  </appender>
-
-  <root level="error">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/tomcat-server.xml b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/resources/tomcat-server.xml
deleted file mode 100644 (file)
index d6ef6ed..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
-    license agreements. See the NOTICE file distributed with this work for additional 
-    information regarding copyright ownership. The ASF licenses this file to 
-    You under the Apache License, Version 2.0 (the "License"); you may not use 
-    this file except in compliance with the License. You may obtain a copy of 
-    the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
-    by applicable law or agreed to in writing, software distributed under the 
-    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
-    OF ANY KIND, either express or implied. See the License for the specific 
-    language governing permissions and limitations under the License. -->
-<Server>
-    <!--APR library loader. Documentation at /docs/apr.html -->
-    <Listener className="org.apache.catalina.core.AprLifecycleListener"
-        SSLEngine="on" />
-    <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
-    <Listener className="org.apache.catalina.core.JasperListener" />
-    <!-- Prevent memory leaks due to use of particular java/javax APIs -->
-    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
-    <Listener
-        className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
-    <Listener
-        className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
-
-    <Service name="Catalina">
-        <Connector port="8080" protocol="HTTP/1.1"
-            connectionTimeout="20000" redirectPort="8443" />
-
-        <!-- Please remove the comments around the following Connector tag 
-            to enable HTTPS Authentication support. Remember to add a valid keystore 
-            in the configuration folder. More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration -->
-
-        <!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
-            maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" 
-            keystoreFile="configuration/keystore" keystorePass="changeit"/> -->
-
-        <Engine name="Catalina" defaultHost="localhost">
-            <Host name="localhost" appBase="" unpackWARs="false"
-                autoDeploy="false" deployOnStartup="false" createDirs="false">
-                <!-- Realm
-                    className="org.opendaylight.controller.security.ControllerCustomRealm" /> -->
-                <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-
-                <Valve className="org.apache.catalina.valves.AccessLogValve"
-                    directory="logs" prefix="web_access_log_" suffix=".txt"
-                    resolveHosts="false" rotatable="true"
-                    fileDateFormat="yyyy-MM"
-                    pattern="%{yyyy-MM-dd HH:mm:ss.SSS z}t - [%a] - %r" />
-
-            </Host>
-        </Engine>
-    </Service>
-</Server>
index 87bbb50860322bcfcfc24be4b912700269757179..48ae0cb91a132d1cd7bff773df604e2d5ae1c47a 100644 (file)
@@ -159,6 +159,16 @@ public class ConfigPersisterActivator implements BundleActivator {
                         throw new IllegalStateException(e);
                     }
                     logger.info("Configuration Persister initialization completed.");
+
+                    /*
+                     * We have completed initial configuration. At this point
+                     * it is good idea to perform garbage collection to prune
+                     * any garbage we have accumulated during startup.
+                     */
+                    logger.debug("Running post-initialization garbage collection...");
+                    System.gc();
+                    logger.debug("Post-initialization garbage collection completed.");
+
                     ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator);
                     synchronized (ConfigPersisterActivator.this) {
                         autoCloseables.add(jmxNotificationHandler);
@@ -168,7 +178,7 @@ public class ConfigPersisterActivator implements BundleActivator {
             synchronized (ConfigPersisterActivator.this) {
                 autoCloseables.add(new AutoCloseable() {
                     @Override
-                    public void close() throws Exception {
+                    public void close() {
                         pushingThread.interrupt();
                     }
                 });
index ce5203232035413c997ef54b4523becb189f3046..66106075d320b14269ebb0a05ffde05df42ce740 100644 (file)
   </properties>
 
   <dependencies>
-    <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>sal-binding-it</artifactId>
-      <exclusions>
-        <!-- FIXME see IdentityRefNetconfTest  -->
-        <!-- Pax-url-aether contains guava classes e.g. ImmutableSet that clashes with guava and causes tests to fail-->
-        <exclusion>
-          <groupId>org.ops4j.pax.url</groupId>
-          <artifactId>pax-url-aether</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>commons.logback_settings</artifactId>
       <artifactId>yang-test</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.tinybundles</groupId>
-      <artifactId>tinybundles</artifactId>
-      <version>${tinybundles.version}</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <build>
           <forkCount>1</forkCount>
           <reuseForks>false</reuseForks>
           <perCoreThreadCount>false</perCoreThreadCount>
-          <classpathDependencyExcludes>
-            <classpathDependencyExcludes>com.google.collections:google-collections</classpathDependencyExcludes>
-            <classpathDependencyExcludes>org.ops4j.pax.url:pax-url-aether</classpathDependencyExcludes>
-          </classpathDependencyExcludes>
         </configuration>
         <executions>
           <execution>
index e99e51e92f67c14e28c06a7b52dc65b64894ac28..cd53995bce8a54c2bf12e2419ceab87300204edb 100644 (file)
@@ -11,7 +11,8 @@ package org.opendaylight.controller.netconf.it;
 import static java.util.Collections.emptyList;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -32,21 +33,19 @@ import java.util.concurrent.TimeoutException;
 import javax.management.ObjectName;
 import javax.xml.parsers.ParserConfigurationException;
 
-import junit.framework.Assert;
-
-import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
 import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
-import org.opendaylight.controller.netconf.StubUserManager;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
@@ -60,11 +59,13 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFact
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
-import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -73,9 +74,7 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
 
-import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-
+import com.google.common.base.Throwables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import io.netty.channel.ChannelFuture;
@@ -177,7 +176,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
     static List<ModuleFactory> getModuleFactoriesS() {
         return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
-                new NetconfTestImplModuleFactory());
+                new NetconfTestImplModuleFactory(), new IdentityTestModuleFactory());
     }
 
     @Test
@@ -376,54 +375,35 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
         return netconfClient;
     }
 
-    private void startSSHServer() throws Exception {
-        logger.info("Creating SSH server");
-        StubUserManager um = new StubUserManager(USERNAME, PASSWORD);
-        String pem;
-        try (InputStream is = getClass().getResourceAsStream("/RSA.pk")) {
-            pem = IOUtils.toString(is);
+    @Test
+    public void testIdRef() throws Exception {
+        NetconfMessage editId = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_identities.xml");
+        NetconfMessage commit = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
+
+        try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+            assertIsOK(netconfClient.sendMessage(editId).getDocument());
+            assertIsOK(netconfClient.sendMessage(commit).getDocument());
+
+            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>"));
+
+        } catch (Exception e) {
+            fail(Throwables.getStackTraceAsString(e));
         }
-        AuthProvider ap = new AuthProvider(um, pem);
-        Thread sshServerThread = new Thread(NetconfSSHServer.start(10830, tcpAddress, ap));
-        sshServerThread.setDaemon(true);
-        sshServerThread.start();
-        logger.info("SSH server on");
     }
 
-    @Test
-    public void sshTest() throws Exception {
-        startSSHServer();
-        logger.info("creating connection");
-        Connection conn = new Connection(sshAddress.getHostName(), sshAddress.getPort());
-        Assert.assertNotNull(conn);
-        logger.info("connection created");
-        conn.connect();
-        boolean isAuthenticated = conn.authenticateWithPassword(USERNAME, PASSWORD);
-        assertTrue(isAuthenticated);
-        logger.info("user authenticated");
-        final Session sess = conn.openSession();
-        sess.startSubSystem("netconf");
-        logger.info("user authenticated");
-        sess.getStdin().write(XmlUtil.toString(this.getConfig.getDocument()).getBytes());
-
-        new Thread() {
-            @Override
-            public void run() {
-                while (true) {
-                    byte[] bytes = new byte[1024];
-                    int c = 0;
-                    try {
-                        c = sess.getStdout().read(bytes);
-                    } catch (IOException e) {
-                        throw new IllegalStateException("IO exception while reading data on ssh bridge.");
-                    }
-                    logger.info("got data:" + bytes);
-                    if (c == 0) {
-                        break;
-                    }
-                }
-            }
-        }.join();
-    }
+    @Override
+    protected CodecRegistry getCodecRegistry() {
+        final IdentityCodec<?> codec = mock(IdentityCodec.class);
+        doReturn(TestIdentity1.class).when(codec).deserialize(TestIdentity1.QNAME);
+        doReturn(TestIdentity2.class).when(codec).deserialize(TestIdentity2.QNAME);
 
+        final CodecRegistry ret = super.getCodecRegistry();
+        doReturn(codec).when(ret).getIdentityCodec();
+        return ret;
+    }
 }
diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java
deleted file mode 100644 (file)
index 981f114..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
-* Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
-*
-* This program and the accompanying materials are made available under the
-* terms of the Eclipse Public License v1.0 which accompanies this distribution,
-* and is available at http://www.eclipse.org/legal/epl-v10.html
-*/
-package org.opendaylight.controller.netconf.it.pax;
-
-import static org.junit.Assert.fail;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.baseModelBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.bindingAwareSalBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.configMinumumBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.flowCapableModelBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.junitAndMockitoBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.mdSalCoreBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.streamBundle;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.Timer;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.matchers.JUnitMatchers;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
-import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
-import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
-import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.options.DefaultCompositeOption;
-import org.ops4j.pax.exam.util.Filter;
-import org.ops4j.pax.tinybundles.core.TinyBundles;
-import org.osgi.framework.Constants;
-import org.xml.sax.SAXException;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
-
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.concurrent.GlobalEventExecutor;
-
-@Ignore
-@RunWith(PaxExam.class)
-public class IdentityRefNetconfTest {
-
-    public static final int CLIENT_CONNECTION_TIMEOUT_MILLIS = 15000;
-
-    // Wait for controller to start
-
-    // FIXME move this (pax) test to different module
-    // pax jars contain guava classes that clash with real guava dependencies in non-pax tests
-    //
-    //@Inject
-    @Filter(timeout = 60 * 1000)
-    BindingAwareBroker broker;
-
-    @Configuration
-    public Option[] config() {
-        return options(
-                systemProperty("osgi.console").value("2401"),
-                systemProperty("osgi.bundles.defaultStartLevel").value("4"),
-                systemProperty("pax.exam.osgi.unresolved.fail").value("true"),
-                systemPackages("sun.nio.ch"),
-
-                testingModules(),
-                loggingModules(),
-                mdSalCoreBundles(),
-                bindingAwareSalBundles(), configMinumumBundles(), baseModelBundles(), flowCapableModelBundles(),
-                junitAndMockitoBundles(),
-
-                // Classes from test-jars bundled for pax-exam test
-                streamBundle(TinyBundles.bundle()
-                        .add(TestingNetconfClient.class)
-                        .add(XmlFileLoader.class)
-
-                        .add("/netconfMessages/editConfig_identities.xml",
-                                XmlFileLoader.class.getResource("/netconfMessages/editConfig_identities.xml"))
-                        .add("/netconfMessages/commit.xml",
-                                XmlFileLoader.class.getResource("/netconfMessages/commit.xml"))
-                        .add("/netconfMessages/getConfig.xml",
-                                XmlFileLoader.class.getResource("/netconfMessages/getConfig.xml"))
-
-                        .set(Constants.BUNDLE_SYMBOLICNAME, "TestingClient_bundle")
-                        .set(Constants.EXPORT_PACKAGE, "org.opendaylight.controller.netconf.client.test, " +
-                                "org.opendaylight.controller.netconf.util.test")
-                        .build(TinyBundles.withBnd())));
-    }
-
-    private Option loggingModules() {
-        return new DefaultCompositeOption(
-                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
-                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
-                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
-                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
-                mavenBundle("org.openexi", "nagasena").versionAsInProject(),
-                mavenBundle("org.openexi", "nagasena-rta").versionAsInProject());
-
-
-    }
-
-    private Option testingModules() {
-        return new DefaultCompositeOption(
-                mavenBundle("org.opendaylight.controller", "yang-test").versionAsInProject());
-    }
-
-    private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 18383);
-
-    @Test
-    public void testIdRef() throws Exception {
-        Preconditions.checkNotNull(broker, "Controller not initialized");
-
-
-        NetconfMessage edit = xmlFileToNetconfMessage("netconfMessages/editConfig_identities.xml");
-        NetconfMessage commit = xmlFileToNetconfMessage("netconfMessages/commit.xml");
-        NetconfMessage getConfig = xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
-
-        NioEventLoopGroup nettyThreadgroup = new NioEventLoopGroup();
-        Timer timer = new HashedWheelTimer();
-        NetconfClientDispatcherImpl clientDispatcher = new NetconfClientDispatcherImpl(nettyThreadgroup, nettyThreadgroup, timer);
-        try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(tcpAddress))) {
-            sendMessage(edit, netconfClient);
-            sendMessage(commit, netconfClient);
-            sendMessage(getConfig, netconfClient, "id-test",
-                        "<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:afi>",
-                        "<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:afi>",
-                        "<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:safi>",
-                        "<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:safi>");
-
-            clientDispatcher.close();
-        } catch (Exception e) {
-            fail(Throwables.getStackTraceAsString(e));
-        } finally {
-            nettyThreadgroup.shutdownGracefully().get();
-            timer.stop();
-        }
-    }
-
-    private void sendMessage(NetconfMessage edit, TestingNetconfClient netconfClient, String... containingResponse)
-            throws ExecutionException, InterruptedException, TimeoutException {
-        NetconfMessage response = netconfClient.sendRequest(edit).get();
-        if (containingResponse == null) {
-            Assert.assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<ok/>"));
-        } else {
-            for (String resp : containingResponse) {
-                Assert.assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString(resp));
-            }
-        }
-    }
-
-    public static NetconfMessage xmlFileToNetconfMessage(final String fileName) throws IOException, SAXException,
-            ParserConfigurationException {
-        return XmlFileLoader.xmlFileToNetconfMessage(fileName);
-    }
-
-    public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress) {
-        final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
-        b.withAddress(tcpAddress);
-        b.withSessionListener(new SimpleNetconfClientSessionListener());
-        b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE,
-                CLIENT_CONNECTION_TIMEOUT_MILLIS));
-        b.withConnectionTimeoutMillis(CLIENT_CONNECTION_TIMEOUT_MILLIS);
-        return b.build();
-    }
-}
diff --git a/opendaylight/netconf/netconf-it/src/test/resources/RSA.pk b/opendaylight/netconf/netconf-it/src/test/resources/RSA.pk
deleted file mode 100644 (file)
index c0266c7..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEogIBAAKCAQEAuC9hbEacpewvylI0mwFwjy3Wou2hpr/ncN9BBiFDSaG5yW2k
-3Oy+SCAcFCL+ZKWb6cc6Ch4gUeCwyEHRojZguuhliKtak9YQf6qbvpPLe00842Lx
-iqNAGurMpzizCDsGFq8ChaAkBZQI3TvcHuPoSUWSMJ+K8xHpRyUdVr6g2yEjezKJ
-sTXBtWaeCCh6YUafFujuDJk7fvYcPW7Je5KRBBStIKvxcMW0zB+7eq04deTHwGbJ
-gGjKWilQ72hsDDP3Hbp5CJMAYg1r4GlCmFx3KyHRGztgWgNgaD7nNpKCkTLjtmA6
-b4x7TA+jrzZ6Af2z5TMrI4dv5w1SrxHaZ+ziLQIDAQABAoIBAHTndeGgq/rQf8De
-Do+4CTaHtK0zQSAyu/azbXUzlZ7drKuCEVs8VMY4wzmwwGEnkF+A2YDkgEUX5X0l
-8aYQ97KKoS9u+43MGCrAIhyDeGrpqlT1TzRcy+qJz53v6gq2U/X/3QztiQ+VV078
-mIluxNgE9XYxPaNsYfGLSCTv1+9c8y/hjGVX2kwFK+u4ut0ZZETggNa8UxfaHVDS
-fIJQX9Gm3J3GSUV30fDGMBIUW6ESLc2L8b7u8Mp9TRP39ZeQSuEUjBe8MYKv0Rel
-oEpjZvcnniMTpFbLpndBYn7/AoIiEBvtCN8faVTuRRcvvLcsRm09IctzKQYnMh6M
-6PLKV+ECgYEA8HFRYaKHUzxpzE/fyon82GQbzqFFY0/bbWrfWICMfNbIgshJUie6
-FmH5iUFMfeqaT7v557HFM0GB9FeIeSbvd88YmiBAcRopZ3DfMkDH+DT73yJ+/TKG
-2nrQtdhyuTIs4bwHqeS2BBJYs7PK9R2rratF3l34Tf7mjlvyOgygHdUCgYEAxBo2
-8hEBlAVNcNb1hTYUxe1w1B6675/mFlmw98Xmj9dRYfICXNhahs8tX3/lsBEd+vBu
-fI0oyHaff8m5bPgGzD1ZMybfeROujNrgxaKVk7Ef0FDRRCop4bm18OroFlFAt9l8
-wMp++ToACbdvQvL/mjWMPYlIxhB/YxHswICZZvkCgYAexxKYwdo6sGAGlC7cWT9x
-X5cjowcjyEQZRHXkeUgCbufpvcOM7aLnXJE5nY8yCwbHsBM0MlBA2GDPKylAANjk
-aDEJAZneIHAuWodngl1Wi0m2bU7+ECqs6s2uiU9eH2sZVh1RBQK7kLGkBx6ys6KX
-L3ZZGYRAT6GplWFzRsx0JQKBgCeVlxPD5QqpC1nEumi6YvUVGdpnnZpzL3HBhxxs
-wT612wKnZFyze4qM1X7ahVXGDsQxtkvD/sCAWW/lG13orw6ZL6FIroF1PJ3ILOkY
-CZN3hJF7TtKwpCWhZB2OfWzL2AGEkE8mUP0j/Q/5DCd6f6f0OSvOw3bfq6cm3iB5
-lP2ZAoGAXsRN5TZTX4AQ2xTlrDQ8A5XgcvyWQpJOmEXMTyHV7VaJVzmNWFVAvndK
-5UIq8ALDwB2t7vjmMUW6euvIwqtXiop7G79UOb3e3NhzeyWFGQyBLqCRznGaXQTT
-dlFy73xhukZMhFnj006bjKCYvOPnwuGl3+0fuWil5Rq3jOuY5c8=
------END RSA PRIVATE KEY-----
diff --git a/opendaylight/netconf/netconf-it/src/test/resources/controller.xml b/opendaylight/netconf/netconf-it/src/test/resources/controller.xml
deleted file mode 100644 (file)
index 96efc10..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<persisted-snapshots>
-   <snapshots>
-      <snapshot>
-         <required-capabilities>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:config:test:types?module=test-types&amp;revision=2013-11-27</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:config?module=config&amp;revision=2013-04-05</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&amp;revision=2013-07-16</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:test:impl?module=config-test-impl&amp;revision=2013-04-03</capability>
-            <capability>urn:opendaylight:params:xml:ns:yang:controller:test?module=config-test&amp;revision=2013-06-13</capability>
-         </required-capabilities>
-         <configuration>
-            <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-               <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:impl-identity-test</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">id-test</prefix:name>
-                     <identities-container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</prefix:afi>
-                     </identities-container>
-                     <identities xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        <prefix:safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</prefix:safi>
-                        <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</prefix:afi>
-                     </identities>
-                     <identities xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        <prefix:safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</prefix:safi>
-                        <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</prefix:afi>
-                     </identities>
-                     <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</prefix:afi>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-broker-impl</prefix:name>
-                     <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                        <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</prefix:type>
-                        <name>ref_binding-notification-broker</name>
-                     </notification-service>
-                     <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                        <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</prefix:type>
-                        <name>ref_binding-data-broker</name>
-                     </data-broker>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">runtime-mapping-singleton</prefix:name>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-notification-broker</prefix:name>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-data-broker</prefix:name>
-                     <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                        <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</prefix:type>
-                        <name>ref_dom-broker</name>
-                     </dom-broker>
-                     <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                        <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-dom-mapping-service</prefix:type>
-                        <name>ref_runtime-mapping-singleton</name>
-                     </mapping-service>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:logback:config">prefix:logback</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:logback:config">singleton</prefix:name>
-                     <console-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
-                        <threshold-filter>DEBUG</threshold-filter>
-                        <name>console</name>
-                        <encoder-pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</encoder-pattern>
-                     </console-appenders>
-                     <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
-                        <level>DEBUG</level>
-                        <logger-name>ROOT</logger-name>
-                        <appenders>console</appenders>
-                     </loggers>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">yang-schema-service</prefix:name>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">hash-map-data-store</prefix:name>
-                  </module>
-                  <module>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</prefix:type>
-                     <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">dom-broker</prefix:name>
-                     <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                        <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-data-store</prefix:type>
-                        <name>ref_hash-map-data-store</name>
-                     </data-store>
-                  </module>
-               </modules>
-               <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:schema-service</prefix:type>
-                     <instance>
-                        <name>ref_yang-schema-service</name>
-                        <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-data-store</prefix:type>
-                     <instance>
-                        <name>ref_hash-map-data-store</name>
-                        <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</prefix:type>
-                     <instance>
-                        <name>ref_dom-broker</name>
-                        <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</prefix:type>
-                     <instance>
-                        <name>ref_id-test</name>
-                        <provider>/modules/module[type='impl-identity-test'][name='id-test']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-dom-mapping-service</prefix:type>
-                     <instance>
-                        <name>ref_runtime-mapping-singleton</name>
-                        <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-consumer-broker</prefix:type>
-                     <instance>
-                        <name>ref_binding-data-broker</name>
-                        <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-rpc-registry</prefix:type>
-                     <instance>
-                        <name>ref_binding-broker-impl</name>
-                        <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</prefix:type>
-                     <instance>
-                        <name>ref_binding-notification-broker</name>
-                        <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</prefix:type>
-                     <instance>
-                        <name>ref_binding-broker-impl</name>
-                        <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-subscription-service</prefix:type>
-                     <instance>
-                        <name>ref_binding-notification-broker</name>
-                        <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
-                     </instance>
-                  </service>
-                  <service>
-                     <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</prefix:type>
-                     <instance>
-                        <name>ref_binding-data-broker</name>
-                        <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
-                     </instance>
-                  </service>
-               </services>
-            </data>
-         </configuration>
-      </snapshot>
-   </snapshots>
-</persisted-snapshots>
diff --git a/opendaylight/netconf/netconf-it/src/test/resources/keystore.jks b/opendaylight/netconf/netconf-it/src/test/resources/keystore.jks
deleted file mode 100644 (file)
index 201d375..0000000
Binary files a/opendaylight/netconf/netconf-it/src/test/resources/keystore.jks and /dev/null differ
diff --git a/opendaylight/netconf/netconf-it/src/test/resources/netconfMessages/commit.xml b/opendaylight/netconf/netconf-it/src/test/resources/netconfMessages/commit.xml
deleted file mode 100644 (file)
index ffdf132..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
-    <commit></commit>
-</rpc>
diff --git a/opendaylight/netconf/netconf-it/src/test/resources/netconfMessages/getConfig.xml b/opendaylight/netconf/netconf-it/src/test/resources/netconfMessages/getConfig.xml
deleted file mode 100644 (file)
index 39efb49..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
-    <get-config>
-        <source>
-            <running/>
-        </source>
-    </get-config>
-</rpc>
index d7437c831d4eb38a248c72bbe4050114a358e32e..52c3337e40047fb844352fd9dcc0b6c596fcb8d0 100644 (file)
@@ -9,12 +9,15 @@
 package org.opendaylight.controller.networkconfig.neutron.northbound;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -22,7 +25,9 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.core.Response;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
@@ -60,6 +65,9 @@ import org.opendaylight.controller.sal.utils.ServiceHelper;
 @Path("/networks")
 public class NeutronNetworksNorthbound {
 
+    @Context
+    UriInfo uriInfo;
+
     private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {
         return o.extractFields(fields);
     }
@@ -72,7 +80,7 @@ public class NeutronNetworksNorthbound {
     //@TypeHint(OpenStackNetworks.class)
     @StatusCodes({
         @ResponseCode(code = 200, condition = "Operation successful"),
-        @ResponseCode(code = 401, condition = "Unauthorized") })
+        @ResponseCode(code = 401, condition = "Unauthorized")})
     public Response listNetworks(
             // return fields
             @QueryParam("fields") List<String> fields,
@@ -88,9 +96,9 @@ public class NeutronNetworksNorthbound {
             @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,
             @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,
             // pagination
-            @QueryParam("limit") String limit,
+            @QueryParam("limit") Integer limit,
             @QueryParam("marker") String marker,
-            @QueryParam("page_reverse") String pageReverse
+            @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse
             // sorting not supported
             ) {
         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
@@ -130,9 +138,94 @@ public class NeutronNetworksNorthbound {
                 }
             }
         }
-        //TODO: apply pagination to results
-        return Response.status(200).entity(
-                new NeutronNetworkRequest(ans)).build();
+
+        Comparator<NeutronNetwork> neutronNetworkComparator = new Comparator<NeutronNetwork>() {
+            @Override
+            public int compare(NeutronNetwork o1, NeutronNetwork o2) {
+                return o1.getID().compareTo(o2.getID());
+            }
+        };
+
+        Collections.sort(ans, neutronNetworkComparator);
+
+        if (limit != null && ans.size() > 1) {
+            List<NeutronPageLink> links = new ArrayList<>();
+            Integer startPos = null;
+            String startMarker;
+            String endMarker;
+            Boolean firstPage = false;
+            Boolean lastPage = false;
+
+            if (marker == null) {
+                startPos = 0;
+            }
+
+            else {
+
+                NeutronNetwork markerNetwork = new NeutronNetwork();
+                markerNetwork.setNetworkUUID(marker);
+
+                startPos = Collections.binarySearch(ans, markerNetwork, neutronNetworkComparator);
+
+                if (!pageReverse){
+                    startPos = startPos + 1;
+                }
+                else {
+                    startPos = startPos - limit;
+                }
+
+            }
+
+            if (startPos == null) {
+                throw new ResourceNotFoundException("UUID for marker:" + marker + " could not be found");
+            }
+
+            if (startPos == 0){
+                firstPage = true;
+            }
+
+            if (startPos + limit >= ans.size()) {
+                ans = ans.subList(startPos, ans.size());
+                startMarker = ans.get(0).getID();
+                endMarker = ans.get(ans.size() - 1).getID();
+                lastPage = true;
+            }
+            else if (startPos < 0) {
+                if (startPos + limit > 0) {
+                    ans = ans.subList(0, startPos + limit);
+                    startMarker = ans.get(0).getID();
+                    endMarker = ans.get(ans.size() - 1).getID();
+                    firstPage = true;
+                }
+                else {
+                    throw new BadRequestException("Requested page is out of bounds. Please check the supplied limit and marker");
+                }
+            }
+            else {
+                ans = ans.subList(startPos, startPos + limit);
+                startMarker = ans.get(0).getID();
+                endMarker = ans.get(limit-1).getID();
+            }
+
+            if (!lastPage) {
+                NeutronPageLink next = new NeutronPageLink();
+                next.setRef("next");
+                next.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + endMarker);
+                links.add(next);
+            }
+
+            if (!firstPage) {
+                NeutronPageLink previous = new NeutronPageLink();
+                previous.setRef("previous");
+                previous.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + startMarker + "&page_reverse=True");
+                links.add(previous);
+            }
+
+            return Response.status(200).entity(new PaginatedNeutronNetworkRequest(ans, links)).build();
+        }
+
+    return Response.status(200).entity(new NeutronNetworkRequest(ans)).build();
+
     }
 
     /**
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPageLink.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPageLink.java
new file mode 100644 (file)
index 0000000..f65d7f6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 Hewlett-Packard Development Company L.P
+ *
+ * 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
+ *
+ * Authors : Dave Tucker
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronPageLink {
+
+    @XmlElement(name="ref")
+    String ref;
+
+    @XmlElement (name="href")
+    String href;
+
+    public String getRef() {
+        return ref;
+    }
+
+    public void setRef(String ref) {
+        this.ref = ref;
+    }
+
+    public String getHref() {
+        return href;
+    }
+
+    public void setHref(String href) {
+        this.href = href;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java
new file mode 100644 (file)
index 0000000..c050661
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Hewlett-Packard Development Company L.P
+ *
+ * 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
+ *
+ * Authors : Dave Tucker
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.List;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class PaginatedNeutronNetworkRequest {
+
+    @XmlElement (name="networks")
+    List<NeutronNetwork> networks;
+
+    @XmlElement (name="network_links")
+    List<NeutronPageLink> networkLinks;
+
+    public PaginatedNeutronNetworkRequest() {
+    }
+
+    public PaginatedNeutronNetworkRequest(List<NeutronNetwork> networks, List<NeutronPageLink> networkLinks) {
+        this.networks = networks;
+        this.networkLinks = networkLinks;
+    }
+
+    public List<NeutronNetwork> getNetworks() {
+        return networks;
+    }
+
+    public void setNetworks(List<NeutronNetwork> networks) {
+        this.networks = networks;
+    }
+
+    public List<NeutronPageLink> getNetworkLinks() {
+        return networkLinks;
+    }
+
+    public void setNetworkLinks(List<NeutronPageLink> networkLinks) {
+        this.networkLinks = networkLinks;
+    }
+}
index 662af723ed4861aa339ff99c3cacedb00af20cf2..e30dad24ab18866b1c455a8facf7bf347a0d22b2 100644 (file)
@@ -396,6 +396,85 @@ public class SwitchNorthbound {
         return NorthboundUtils.getResponse(status);
     }
 
+    /**
+     * Get a property of a node
+     *
+     * @param containerName
+     *            Name of the Container (Eg. 'SliceRed')
+     * @param nodeType
+     *            Type of the node being programmed (Eg. 'OF')
+     * @param nodeId
+     *            Node Identifier as specified by
+     *            {@link org.opendaylight.controller.sal.core.Node} (Eg.
+     *            '00:00:00:00:00:03:01:02')
+     * @param propertyName
+     *            Name of the Property. Properties that can be deleted are
+     *            description, forwarding(only in default container) and tier.
+     * @return Property value of the property
+     *
+     *         <pre>
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:01/property/description
+     *
+     * Response body in XML
+     * &lt;description&gt;
+     *     &#x20;&#x20;&lt;value&gt;switch1&lt;/value&gt;
+     * &lt;/description&gt;
+     *
+     * Response body in JSON
+     * {
+     *     &#x20;&#x20;"value": "switch1"
+     * }
+     * </pre>
+     */
+
+    @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @TypeHint(String.class)
+    @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
+        @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+        @ResponseCode(code = 404, condition = "The containerName is not found"),
+        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
+    public Property getNodeProperty(@PathParam("containerName") String containerName,
+            @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
+            @PathParam("propertyName") String propertyName) {
+
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        handleNodeAvailability(containerName, nodeType, nodeId);
+        Node node = Node.fromString(nodeType, nodeId);
+        if (node == null) {
+            throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString());
+        }
+        SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
+        if (switchConfig == null) {
+            throw new ResourceNotFoundException(nodeId + " : " + "Config Not Found" );
+        } else {
+            Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
+            if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
+                String msg = "Property " + propertyName + " does not exist or not "
+                        + "configured for switch " + nodeId;
+                throw new ResourceNotFoundException(msg);
+            } else {
+                return nodeProperties.get(propertyName.toLowerCase());
+            }
+        }
+    }
+
     /**
      *
      * Retrieve a list of all the nodeconnectors and their properties in a given
index a995bf860999f55699bf1606276d0f945ccb77f7..b2cb414303fa2a826f9b9a3ebfc0ab7f7365da88 100644 (file)
@@ -150,9 +150,9 @@ public class ConnectionService implements IPluginOutConnectionService, IConnecti
      */
     @Override
     public void notifyNodeDisconnectFromMaster(Node node) {
-        for (String pluginType : this.pluginService.keySet()) {
-            IPluginInConnectionService s = pluginService.get(pluginType);
-            s.notifyNodeDisconnectFromMaster(node);
+        IPluginInConnectionService s = pluginService.get(node.getType());
+        if (s != null) {
+             s.notifyNodeDisconnectFromMaster(node);
         }
     }
-}
\ No newline at end of file
+}
index e95ab8095d08c8b3fcf80094fc958d0053b4d256..8372f88e7dce895e135debf1daef17e18d02b0f1 100644 (file)
@@ -54,6 +54,7 @@ import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
 import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
@@ -1017,6 +1018,18 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
                     ForwardingMode mode = (ForwardingMode) nodeProperties.get(ForwardingMode.name);
                     forwardingModeChanged = mode.isProactive();
                 }
+            } else if ((conf == null) &&  !(GlobalConstants.DEFAULT.toString().equals(containerName))) {
+                ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, GlobalConstants.DEFAULT.toString(), this);
+                if (defaultSwitchManager != null) {
+                    Property defaultContainerSwitchDesc = (Description) defaultSwitchManager.getNodeProp(node, Description.propertyName);
+                    if (defaultContainerSwitchDesc != null) {
+                        Map<String, Property> descPropMap = new HashMap<String, Property>();
+                        descPropMap.put(Description.propertyName, defaultContainerSwitchDesc);
+                        conf = new SwitchConfig(nodeId, descPropMap);
+                        updateNodeConfig(conf);
+                        propMap.put(Description.propertyName, defaultContainerSwitchDesc);
+                    }
+                }
             }
         }
 
diff --git a/pom.xml b/pom.xml
index 3408c0513cb5229de9b4ae036263335a2fceb9b2..3a3c3dcfb462b2d2a56341799760e9074added56 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/commons/parent</module>
     <module>opendaylight/commons/logback_settings</module>
 
-    <!-- Karaf Distribution 
-    <module>feature</module> -->
+    <!-- Karaf Distribution -->
+    <module>features/base</module>
     <module>opendaylight/dummy-console</module>
     <module>opendaylight/distribution/opendaylight-karaf</module>
   </modules>