Merge "Bug 1029: Remove dead code: sal-schema-repository-api"
authorTony Tkacik <ttkacik@cisco.com>
Wed, 28 May 2014 14:40:46 +0000 (14:40 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 28 May 2014 14:40:46 +0000 (14:40 +0000)
355 files changed:
.gitignore
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-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/SearchableServiceReferenceWritableRegistry.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/AbstractYangTest.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeRegistratorTest.java
opendaylight/config/yang-jmx-generator/src/test/resources/config-bgp-listener-impl.yang
opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang
opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java
opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java
opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java
opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java
opendaylight/config/yang-test/src/main/yang/config-test-impl.yang
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
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/dummy-console/pom.xml
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/ComponentActivator.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyAdapter.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyAdapter.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategyTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPutsTest.java [moved from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java with 98% similarity]
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
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/DataNormalizer.java
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-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/BackwardsCompatibleDataBroker.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingListenerInvoker.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java [deleted file]
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 [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataPreconditionFailedException.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTree.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidateNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeSnapshot.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreUtils.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java with 98% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AbstractDataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationApplyOperation.java with 68% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/NodeModification.java with 53% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/OperationWithModification.java with 71% similarity]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/Version.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/RpcRegistrationWrapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStoreTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceActivator.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java [moved from opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationMetadataTreeTest.java with 78% similarity]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperationRoot.java with 87% similarity]
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/NetconfDeviceTwoPhaseCommitTransaction.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImpl.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandler.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImplTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/MockRoutingTable.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImplTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandlerTest.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/MessagingUtil.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/RemoteServerTestClient.java
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfDocumentedExceptionMapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ResponseException.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfDocumentedException.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfError.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/AbstractRpcExecutor.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/BrokerRpcExecutor.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/MountPointRpcExecutor.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/RpcExecutor.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnJsonBasicYangTypesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonIdentityrefTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonNotExistingLeafTypeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonWithDataFromSeveralModulesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlNotExistingLeafTypeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlWithChoiceTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonIdentityrefToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonLeafrefToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CnSnToXmlAndJsonInstanceIdentifierTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CodecsExceptionsCatchingTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/NormalizeNodeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetAugmentedElementWhenEqualNamesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfErrorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfImplTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/URITest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlLeafrefToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/yangs/toaster.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/pom.xml
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/l2switch/implementation/src/main/java/org/opendaylight/controller/sample/l2switch/md/util/InstanceIdentifierUtils.java
opendaylight/md-sal/samples/l2switch/implementation/src/test/java/org/opendaylight/controller/sample/l2switch/md/flow/FlowWriterServiceImplTest.java
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/sample/toaster/provider/OpendaylightToaster.java
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-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/SimpleAttributeResolvingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/AbstractAttributeWritingStrategy.java [deleted file]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectNameAttributeWritingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/RuntimeBeanEntryWritingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleIdentityRefAttributeWritingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementDefinition.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ServiceRegistryWrapper.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MissingInstanceHandlingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreServiceImpl.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDocumentedException.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfExiSession.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfExiSession.java with 86% similarity]
opendaylight/netconf/netconf-client/pom.xml
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiator.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/SshClientChannelInitializer.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/TcpClientChannelInitializer.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfiguration.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfigurationBuilder.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfiguration.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/MessageParserTest.java
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-netty-util/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/AbstractChannelInitializer.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java with 85% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/AbstractNetconfSession.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSession.java with 94% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/AbstractNetconfSessionNegotiator.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java with 95% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ChunkedFramingMechanismEncoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ChunkedFramingMechanismEncoder.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/EOMFramingMechanismEncoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/EOMFramingMechanismEncoder.java with 92% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/FramingMechanismHandlerFactory.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/FramingMechanismHandlerFactory.java with 94% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfChunkAggregator.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregator.java with 99% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfEOMAggregator.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfEOMAggregator.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfEXICodec.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfEXICodec.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfEXIToMessageDecoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfEXIToMessageDecoder.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfHelloMessageToXMLEncoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfHelloMessageToXMLEncoder.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToEXIEncoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageToEXIEncoder.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToXMLEncoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageToXMLEncoder.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToHelloMessageDecoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToHelloMessageDecoder.java with 99% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfXMLToMessageDecoder.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToMessageDecoder.java with 95% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/exi/EXIParameters.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/EXIParameters.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/exi/NetconfStartExiMessage.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfStartExiMessage.java with 98% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/SshHandler.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/SshHandler.java with 80% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/authentication/AuthenticationHandler.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/AuthenticationHandler.java with 87% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/authentication/LoginPassword.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/LoginPassword.java with 86% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/Invoker.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/Invoker.java with 94% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClient.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClient.java with 87% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClientAdapter.java with 95% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshSession.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshSession.java with 96% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelInputStream.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelInputStream.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelOutputStream.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelOutputStream.java with 96% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/VirtualSocket.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocket.java with 98% similarity]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/VirtualSocketException.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocketException.java with 86% similarity]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfChunkAggregatorTest.java [moved from opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregatorTest.java with 97% similarity]
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageFactoryTest.java [moved from opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactoryTest.java with 87% similarity]
opendaylight/netconf/netconf-netty-util/src/test/resources/netconfMessages/client_hello_with_auth.xml [moved from opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/client_hello_with_auth.xml with 100% similarity]
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/PEMGenerator.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/osgi/NetconfSSHActivator.java
opendaylight/netconf/netconf-util/pom.xml
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlUnitUtil.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_setUnions.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml
opendaylight/netconf/pom.xml
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityGroupInterface.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityRuleInterface.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupAware.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupCRUD.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleAware.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleCRUD.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityGroup.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityRule.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupRequest.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRuleRequest.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java [new file with mode: 0644]
pom.xml

index 6fc003be270022a4c55a2d4b2ccdb951886ccbbd..f8cf74f8263758e9cf39e2a4dbbf30d6c904628e 100644 (file)
@@ -25,3 +25,5 @@ classes
 out/
 .externalToolBuilders
 maven-eclipse.xml
+.DS_STORE
+.metadata
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..e1e3164f71820d89390431e177e3a75057ea4e8b 100644 (file)
@@ -17,6 +17,7 @@
   <properties>
     <aopalliance.version>1.0.0</aopalliance.version>
     <appauth.version>0.4.2-SNAPSHOT</appauth.version>
+    <aries.util.version>1.1.0</aries.util.version>
     <!-- Controller Modules Versions -->
     <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
     <asm.version>4.1</asm.version>
@@ -77,6 +78,7 @@
     <hosttracker.northbound.version>0.4.2-SNAPSHOT</hosttracker.northbound.version>
     <hosttracker_new.api.version>0.4.2-SNAPSHOT</hosttracker_new.api.version>
     <ietf-inet-types.version>2010.09.24.4-SNAPSHOT</ietf-inet-types.version>
+    <ietf-restconf.version>2013.10.19.1-SNAPSHOT</ietf-restconf.version>
     <ietf-topology.version>2013.10.21.2-SNAPSHOT</ietf-topology.version>
     <ietf-yang-types.version>2010.09.24.4-SNAPSHOT</ietf-yang-types.version>
     <jackson.version>2.3.2</jackson.version>
         <artifactId>ietf-netconf-monitoring-extension</artifactId>
         <version>${netconf.version}</version>
       </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>netconf-netty-util</artifactId>
+        <version>${netconf.version}</version>
+      </dependency>
       <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <artifactId>netconf-monitoring</artifactId>
         <version>${netconf.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-netty-util</artifactId>
+        <version>${netconf.version}</version>
+        <type>test-jar</type>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>netconf-ssh</artifactId>
         <artifactId>concepts</artifactId>
         <version>${yangtools.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>object-cache-api</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>object-cache-guava</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.yangtools</groupId>
         <artifactId>restconf-client-api</artifactId>
         <artifactId>ietf-inet-types</artifactId>
         <version>${ietf-inet-types.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <artifactId>ietf-restconf</artifactId>
+        <version>${ietf-restconf.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.yangtools.model</groupId>
         <artifactId>ietf-topology</artifactId>
         <artifactId>ietf-yang-types</artifactId>
         <version>${ietf-yang-types.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <artifactId>ietf-yang-types-20130715</artifactId>
+        <version>2013.07.15.1-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.yangtools.model</groupId>
         <artifactId>opendaylight-l2-types</artifactId>
index 8f85972d050cd9d3dc0e8460c21baf3506913db8..b7cdf9475753e92f34fcbeae620a95025c9941a9 100644 (file)
@@ -359,7 +359,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             }
 
             // register services to OSGi
-            Map<String, ServiceInterfaceAnnotation> annotationMapping = configTransactionController.getWritableRegistry().findServiceInterfaces(moduleIdentifier);
+            Map<ServiceInterfaceAnnotation, String /* service ref name */> annotationMapping = configTransactionController.getWritableRegistry().findServiceInterfaces(moduleIdentifier);
             BundleContext bc = configTransactionController.getModuleFactoryBundleContext(
                     entry.getModuleFactory().getImplementationName());
             if (osgiRegistration == null) {
index 7a41a3bfa24567cbad07e5fc1f214bebbe9ac654..4c5e391f74ebbd0147f1eedea77fc9c110999dae 100644 (file)
@@ -21,6 +21,6 @@ public interface SearchableServiceReferenceWritableRegistry extends ServiceRefer
      * @throws java.lang.IllegalArgumentException if any of service qNames is not found
      * @throws java.lang.NullPointerException     if parameter is null
      */
-    Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier);
+    Map<ServiceInterfaceAnnotation, String /* service ref name */> findServiceInterfaces(ModuleIdentifier moduleIdentifier);
 
 }
index ceea99415471d1ecd48a0d2cd17f469174aa792a..52bb3f5ed1df99a678e9ad44357cef6eadc4b3cf 100644 (file)
@@ -50,7 +50,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
     private final Map<String /* service qName */, ServiceInterfaceAnnotation> serviceQNamesToAnnotations;
     // all Service Interface qNames for sanity checking
     private final Set<String /* qName */> allQNames;
-    Map<ModuleIdentifier, Map<String /* service ref name */, ServiceInterfaceAnnotation >> modulesToServiceRef = new HashMap<>();
+    Map<ModuleIdentifier, Map<ServiceInterfaceAnnotation, String /* service ref name */>> modulesToServiceRef = new HashMap<>();
 
 
     // actual reference database
@@ -241,8 +241,8 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
     }
 
     @Override
-    public Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier) {
-        Map<String, ServiceInterfaceAnnotation> result = modulesToServiceRef.get(moduleIdentifier);
+    public Map<ServiceInterfaceAnnotation, String /* service ref name */> findServiceInterfaces(ModuleIdentifier moduleIdentifier) {
+        Map<ServiceInterfaceAnnotation, String /* service ref name */> result = modulesToServiceRef.get(moduleIdentifier);
         if (result == null) {
             return Collections.emptyMap();
         }
@@ -417,7 +417,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
         }
         // save to refNames
         refNames.put(serviceReference, moduleIdentifier);
-        Map<String, ServiceInterfaceAnnotation> refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier);
+        Map<ServiceInterfaceAnnotation, String /* service ref name */> refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier);
         if (refNamesToAnnotations == null){
             refNamesToAnnotations = new HashMap<>();
             modulesToServiceRef.put(moduleIdentifier, refNamesToAnnotations);
@@ -425,7 +425,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe
 
         ServiceInterfaceAnnotation annotation = serviceQNamesToAnnotations.get(serviceReference.getServiceInterfaceQName());
         checkNotNull(annotation, "Possible error in code, cannot find annotation for " + serviceReference);
-        refNamesToAnnotations.put(serviceReference.getRefName(), annotation);
+        refNamesToAnnotations.put(annotation, serviceReference.getRefName());
         return result;
     }
 
index fbc7eb6cbe7925ef6da5a96ad69e8c1a38433007..b592fa3c79736d09b22f0b133bef142702783dbb 100644 (file)
@@ -37,7 +37,7 @@ public class BeanToOsgiServiceManager {
      */
     public OsgiRegistration registerToOsgi(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
                                            BundleContext bundleContext,
-                                           Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+                                           Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
         return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations);
     }
 
@@ -57,11 +57,11 @@ public class BeanToOsgiServiceManager {
         @GuardedBy("this")
         private final Set<ServiceRegistration<?>> serviceRegistrations;
         @GuardedBy("this")
-        private final Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations;
+        private final Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations;
 
         public OsgiRegistration(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
                                 BundleContext bundleContext,
-                                Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+                                Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
             this.instance = instance;
             this.moduleIdentifier = moduleIdentifier;
             this.serviceNamesToAnnotations = serviceNamesToAnnotations;
@@ -69,13 +69,13 @@ public class BeanToOsgiServiceManager {
         }
 
         private static Set<ServiceRegistration<?>> registerToSR(AutoCloseable instance, BundleContext bundleContext,
-                                                                Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+                                                                Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
             Set<ServiceRegistration<?>> serviceRegistrations = new HashSet<>();
-            for (Entry<String, ServiceInterfaceAnnotation> entry : serviceNamesToAnnotations.entrySet()) {
-                Class<?> requiredInterface = entry.getValue().osgiRegistrationType();
+            for (Entry<ServiceInterfaceAnnotation, String /* service ref name */> entry : serviceNamesToAnnotations.entrySet()) {
+                Class<?> requiredInterface = entry.getKey().osgiRegistrationType();
                 checkState(requiredInterface.isInstance(instance), instance.getClass().getName() +
                         " instance should implement " + requiredInterface.getName());
-                Dictionary<String, String> propertiesForOsgi = createProps(entry.getKey());
+                Dictionary<String, String> propertiesForOsgi = createProps(entry.getValue());
                 ServiceRegistration<?> serviceRegistration = bundleContext
                         .registerService(requiredInterface.getName(), instance, propertiesForOsgi);
                 serviceRegistrations.add(serviceRegistration);
@@ -95,7 +95,7 @@ public class BeanToOsgiServiceManager {
             serviceRegistrations.clear();
         }
 
-        public synchronized void updateRegistrations(Map<String, ServiceInterfaceAnnotation> newAnnotationMapping,
+        public synchronized void updateRegistrations(Map<ServiceInterfaceAnnotation, String /* service ref name */> newAnnotationMapping,
                                                      BundleContext bundleContext, AutoCloseable newInstance) {
             boolean notEquals = this.instance != newInstance;
             notEquals |= newAnnotationMapping.equals(serviceNamesToAnnotations) == false;
index 9d0fbd85dc98b0e87b118f2733876673764023eb..ec46219aaf8469e3d8ecadcc9988bb4a47188e3f 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.config.manager.impl.osgi.mapping;
 
 import javassist.ClassPool;
+
 import org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil;
 import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
@@ -27,10 +28,8 @@ public class CodecRegistryProvider implements AutoCloseable {
     private final RuntimeGeneratedMappingServiceImpl service;
     private final AutoCloseable registration;
 
-    public CodecRegistryProvider(ClassLoadingStrategy classLoadingStrategy, BundleContext context) {
-        service = new RuntimeGeneratedMappingServiceImpl(classLoadingStrategy);
-        service.setPool(CLASS_POOL);
-        service.init();
+    public CodecRegistryProvider(final ClassLoadingStrategy classLoadingStrategy, final BundleContext context) {
+        service = new RuntimeGeneratedMappingServiceImpl(CLASS_POOL, classLoadingStrategy);
         registration = OsgiRegistrationUtil.registerService(context, service,
                 SchemaServiceListener.class, BindingIndependentMappingService.class);
     }
index 0cc950af65d919ddeeef35029e8f45b6bc10157e..773025c3cf85560ac1c3900d50170155a4df5069 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.controller.config.yangjmxgenerator;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
-
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -73,6 +72,7 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     private final Map<String, QName> providedServices;
 
     private Collection<RuntimeBeanEntry> runtimeBeans;
+    private String nullableDummyContainerName;
 
     ModuleMXBeanEntry(ModuleMXBeanEntryInitial initials, Map<String, AttributeIfc> yangToAttributes,
             Map<String, QName> providedServices2, Collection<RuntimeBeanEntry> runtimeBeans) {
@@ -183,6 +183,15 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                 + '\'' + '}';
     }
 
+    public String getNullableDummyContainerName() {
+        return nullableDummyContainerName;
+    }
+
+    public void setNullableDummyContainerName(String nullableDummyContainerName) {
+        this.nullableDummyContainerName = nullableDummyContainerName;
+    }
+
+
     static final class ModuleMXBeanEntryInitial {
 
         private String localName;
index 676c8eca6ec6f9a903c34aeebd69d9c8abbeae07..6da8dfc663b9cb1e8b8ef43a384151af7c7d18f0 100644 (file)
@@ -7,12 +7,27 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
@@ -35,26 +50,13 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
-
 final class ModuleMXBeanEntryBuilder {
 
     private Module currentModule;
@@ -233,7 +235,7 @@ final class ModuleMXBeanEntryBuilder {
         return true;
     }
 
-    private void processChoiceCaseNode(Map<String, ModuleMXBeanEntry> result,
+    private <HAS_CHILDREN_AND_QNAME extends DataNodeContainer & SchemaNode> void processChoiceCaseNode(Map<String, ModuleMXBeanEntry> result,
             Map<String, QName> uniqueGeneratedClassesNames, String configModulePrefix,
             Map<String, IdentitySchemaNode> moduleIdentities,
             Map<String, IdentitySchemaNode> unaugmentedModuleIdentities, AugmentationSchema augmentation,
@@ -266,15 +268,17 @@ final class ModuleMXBeanEntryBuilder {
         // runtime-data
         Collection<RuntimeBeanEntry> runtimeBeans = null;
 
+        HAS_CHILDREN_AND_QNAME dataNodeContainer = getDataNodeContainer(choiceCaseNode);
+
         if (expectedConfigurationAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
             logger.debug("Parsing configuration of {}", moduleLocalNameFromXPath);
-            yangToAttributes = fillConfiguration(choiceCaseNode, currentModule, typeProviderWrapper, qNamesToSIEs,
+            yangToAttributes = fillConfiguration(dataNodeContainer, currentModule, typeProviderWrapper, qNamesToSIEs,
                     schemaContext, packageName);
             checkUniqueAttributesWithGeneratedClass(uniqueGeneratedClassesNames, when.getQName(), yangToAttributes);
         } else if (expectedStateAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
             logger.debug("Parsing state of {}", moduleLocalNameFromXPath);
             try {
-                runtimeBeans = fillRuntimeBeans(choiceCaseNode, currentModule, typeProviderWrapper, packageName,
+                runtimeBeans = fillRuntimeBeans(dataNodeContainer, currentModule, typeProviderWrapper, packageName,
                         moduleLocalNameFromXPath, javaNamePrefix);
             } catch (NameConflictException e) {
                 throw new NameConflictException(e.getConflictingName(), when.getQName(), when.getQName());
@@ -289,14 +293,20 @@ final class ModuleMXBeanEntryBuilder {
         } else {
             throw new IllegalArgumentException("Cannot parse augmentation " + augmentation);
         }
+        boolean hasDummyContainer = choiceCaseNode.equals(dataNodeContainer) == false;
+
+        String nullableDummyContainerName = hasDummyContainer ? dataNodeContainer.getQName().getLocalName() : null;
         if (result.containsKey(moduleLocalNameFromXPath)) {
-            // either fill runtimeBeans or yangToAttributes
+            // either fill runtimeBeans or yangToAttributes, merge
             ModuleMXBeanEntry moduleMXBeanEntry = result.get(moduleLocalNameFromXPath);
             if (yangToAttributes != null && moduleMXBeanEntry.getAttributes() == null) {
                 moduleMXBeanEntry.setYangToAttributes(yangToAttributes);
             } else if (runtimeBeans != null && moduleMXBeanEntry.getRuntimeBeans() == null) {
                 moduleMXBeanEntry.setRuntimeBeans(runtimeBeans);
             }
+            checkState(Objects.equals(nullableDummyContainerName, moduleMXBeanEntry.getNullableDummyContainerName()),
+                    "Mismatch in module " + moduleMXBeanEntry.toString() + " - dummy container must be present/missing in" +
+                            " both state and configuration");
         } else {
             ModuleMXBeanEntry.ModuleMXBeanEntryInitial initial = new ModuleMXBeanEntry.ModuleMXBeanEntryInitialBuilder()
                     .setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix)
@@ -309,6 +319,7 @@ final class ModuleMXBeanEntryBuilder {
 
             moduleMXBeanEntry.setYangModuleName(currentModule.getName());
             moduleMXBeanEntry.setYangModuleLocalname(moduleLocalNameFromXPath);
+            moduleMXBeanEntry.setNullableDummyContainerName(nullableDummyContainerName);
             result.put(moduleLocalNameFromXPath, moduleMXBeanEntry);
         }
     }
@@ -352,29 +363,52 @@ final class ModuleMXBeanEntryBuilder {
     }
 
     private void checkUniqueTOAttr(Map<String, QName> uniqueGeneratedClassNames, QName parentQName, TOAttribute attr) {
-        final String upperCaseCammelCase = attr.getUpperCaseCammelCase();
-        if (uniqueGeneratedClassNames.containsKey(upperCaseCammelCase)) {
-            QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCammelCase);
-            throw new NameConflictException(upperCaseCammelCase, firstDefinedQName, parentQName);
+        final String upperCaseCamelCase = attr.getUpperCaseCammelCase();
+        if (uniqueGeneratedClassNames.containsKey(upperCaseCamelCase)) {
+            QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCamelCase);
+            throw new NameConflictException(upperCaseCamelCase, firstDefinedQName, parentQName);
         } else {
-            uniqueGeneratedClassNames.put(upperCaseCammelCase, parentQName);
+            uniqueGeneratedClassNames.put(upperCaseCamelCase, parentQName);
         }
     }
 
-    private Collection<RuntimeBeanEntry> fillRuntimeBeans(ChoiceCaseNode choiceCaseNode, Module currentModule,
+    private Collection<RuntimeBeanEntry> fillRuntimeBeans(DataNodeContainer dataNodeContainer, Module currentModule,
             TypeProviderWrapper typeProviderWrapper, String packageName, String moduleLocalNameFromXPath,
             String javaNamePrefix) {
 
-        return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, choiceCaseNode, moduleLocalNameFromXPath,
+        return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, dataNodeContainer, moduleLocalNameFromXPath,
                 typeProviderWrapper, javaNamePrefix, currentModule).values();
 
     }
 
-    private Map<String, AttributeIfc> fillConfiguration(ChoiceCaseNode choiceCaseNode, Module currentModule,
+    /**
+     * Since each case statement within a module must provide unique child nodes, it is allowed to wrap
+     * the actual configuration with a container node with name equal to case name.
+     *
+     * @param choiceCaseNode state or configuration case statement
+     * @return either choiceCaseNode or its only child container
+     */
+    private <HAS_CHILDREN_AND_QNAME extends DataNodeContainer & SchemaNode> HAS_CHILDREN_AND_QNAME getDataNodeContainer(ChoiceCaseNode choiceCaseNode) {
+        Set<DataSchemaNode> childNodes = choiceCaseNode.getChildNodes();
+        if (childNodes.size() == 1) {
+            DataSchemaNode onlyChild = childNodes.iterator().next();
+            if (onlyChild instanceof ContainerSchemaNode) {
+                ContainerSchemaNode onlyContainer = (ContainerSchemaNode) onlyChild;
+                if (Objects.equals(onlyContainer.getQName().getLocalName(), choiceCaseNode.getQName().getLocalName())) {
+                    // the actual configuration is inside dummy container
+                    return (HAS_CHILDREN_AND_QNAME) onlyContainer;
+                }
+            }
+        }
+        return (HAS_CHILDREN_AND_QNAME) choiceCaseNode;
+    }
+
+    private Map<String, AttributeIfc> fillConfiguration(DataNodeContainer dataNodeContainer, Module currentModule,
             TypeProviderWrapper typeProviderWrapper, Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
             SchemaContext schemaContext, String packageName) {
         Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
-        for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
+        Set<DataSchemaNode> childNodes = dataNodeContainer.getChildNodes();
+        for (DataSchemaNode attrNode : childNodes) {
             AttributeIfc attributeValue = getAttributeValue(attrNode, currentModule, qNamesToSIEs, typeProviderWrapper,
                     schemaContext, packageName);
             yangToAttributes.put(attributeValue.getAttributeYangName(), attributeValue);
@@ -483,7 +517,7 @@ final class ModuleMXBeanEntryBuilder {
             String prefix = m.group(1);
             ModuleImport moduleImport = findModuleImport(currentModule, prefix);
             foundModule = schemaContext.findModuleByName(moduleImport.getModuleName(), moduleImport.getRevision());
-            checkState(foundModule != null, format("Module not found in SchemaContext by %s", moduleImport));
+            checkNotNull(foundModule, format("Module not found in SchemaContext by %s", moduleImport));
             localSIName = m.group(2);
         } else {
             foundModule = currentModule; // no prefix => SIE is in currentModule
index cd14458b0fe6b44b76bb1e58513628f27ad8a80c..c941d1504ddae409a9fdfa0c14ec4da957d1038e 100644 (file)
@@ -7,9 +7,24 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
@@ -18,7 +33,6 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribu
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -32,22 +46,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
 /**
  * Holds information about runtime bean to be generated. There are two kinds of
  * RuntimeBeanEntry instances: if isRoot flag is set to true, this bean
@@ -68,7 +66,7 @@ public class RuntimeBeanEntry {
 
     @VisibleForTesting
     RuntimeBeanEntry(String packageName,
-            DataSchemaNode nodeForReporting, String yangName,
+            DataNodeContainer nodeForReporting, String yangName,
             String javaNamePrefix, boolean isRoot,
             Optional<String> keyYangName, List<AttributeIfc> attributes,
             List<RuntimeBeanEntry> children, Set<Rpc> rpcs) {
@@ -112,7 +110,7 @@ public class RuntimeBeanEntry {
      *         not contain special configuration for it.
      */
     public static Map<String, RuntimeBeanEntry> extractClassNameToRuntimeBeanMap(
-            String packageName, ChoiceCaseNode container,
+            String packageName, DataNodeContainer container,
             String moduleYangName, TypeProviderWrapper typeProviderWrapper,
             String javaNamePrefix, Module currentModule) {
 
@@ -390,7 +388,7 @@ public class RuntimeBeanEntry {
     }
 
     private static RuntimeBeanEntry createRoot(String packageName,
-            DataSchemaNode nodeForReporting, String attributeYangName,
+            DataNodeContainer nodeForReporting, String attributeYangName,
             List<AttributeIfc> attributes, String javaNamePrefix,
             List<RuntimeBeanEntry> children, Set<Rpc> rpcs) {
         return new RuntimeBeanEntry(packageName, nodeForReporting,
index 76d97703af3722142bf361db63960fac77364d3d..b9f2ba9cd1012c2d861212d9fc50ec02b32d051e 100644 (file)
@@ -7,8 +7,19 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.format;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import org.junit.Assert;
 import org.junit.Before;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.YangModelSearchUtils;
@@ -19,18 +30,6 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.format;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
 public abstract class AbstractYangTest {
     protected SchemaContext context;
     protected Map<String, Module> namesToModules; // are module names globally
index 6dd64441df243c87a90610506211bf4c63104e6c..7765b28bb5c5dc621a768c23fdfc58c16d6f9de8 100644 (file)
@@ -11,27 +11,25 @@ import static org.apache.commons.lang3.StringUtils.capitalize;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
+import com.google.common.base.Optional;
 import java.net.URI;
 import java.util.Collections;
 import java.util.List;
-
 import org.junit.Test;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 
-import com.google.common.base.Optional;
-
 public class RuntimeRegistratorTest {
     // TODO add more tests
     protected RuntimeBeanEntry prepareRootRB(List<RuntimeBeanEntry> children) {
 
-        DataSchemaNode dataSchemaNodeForReporting = mock(DataSchemaNode.class);
-        doReturn("DataSchemaNode").when(dataSchemaNodeForReporting).toString();
-        return new RuntimeBeanEntry("pa.cka.ge", dataSchemaNodeForReporting,
+        DataNodeContainer nodeContainer = mock(DataNodeContainer.class);
+        doReturn("DataSchemaNode").when(nodeContainer).toString();
+        return new RuntimeBeanEntry("pa.cka.ge", nodeContainer,
                 "module-name", "ModuleName", true, Optional.<String> absent(),
                 Collections.<AttributeIfc> emptyList(), children,
                 Collections.<Rpc> emptySet());
@@ -39,9 +37,9 @@ public class RuntimeRegistratorTest {
 
     protected RuntimeBeanEntry prepareChildRB(List<RuntimeBeanEntry> children,
             String prefix) {
-        DataSchemaNode dataSchemaNodeForReporting = mock(DataSchemaNode.class);
-        doReturn("DataSchemaNode").when(dataSchemaNodeForReporting).toString();
-        return new RuntimeBeanEntry("pa.cka.ge", dataSchemaNodeForReporting,
+        DataNodeContainer nodeContainer = mock(DataNodeContainer.class);
+        doReturn("DataSchemaNode").when(nodeContainer).toString();
+        return new RuntimeBeanEntry("pa.cka.ge", nodeContainer,
                 prefix + "child-name", capitalize(prefix) + "ChildName", false,
                 Optional.<String> absent(),
                 Collections.<AttributeIfc> emptyList(), children,
index fca83fd6be0e01ce4f7ac26f7001e8fe5d637e9b..0a011b772caa4b3dcc63eb22468c86518be66763 100644 (file)
@@ -23,20 +23,22 @@ module config-bgp-listener-impl {
     augment "/config:modules/config:module/config:state" {
         case bgp-listener-impl {
             when "/config:modules/config:module/config:type = 'bgp-listener-impl'";
-            list peers {
-                config:inner-state-bean;
-                leaf port {
-                    type inet:port-number;
-                    default 179;
+            container bgp-listener-impl {
+                list peers {
+                    config:inner-state-bean;
+                    leaf port {
+                        type inet:port-number;
+                        default 179;
+                    }
+                    leaf core-size {
+                        type uint32;
+                    }
                 }
-                leaf core-size {
-                    type uint32;
-                }
-            }
 
-           leaf as-number {
-                mandatory true;
-                type inet:as-number;
+                leaf as-number {
+                    mandatory true;
+                    type inet:as-number;
+                }
             }
         }
     }
index 4af5b9569a445dfba4d601d18c7f76bf0f64ba0a..e189ef7d66c65b8bdfe9f905889797d84dbb5e36 100644 (file)
@@ -192,42 +192,44 @@ module config-threads-java {
     augment "/config:modules/config:module/config:configuration" {
         case threadpool-dynamic {
             when "/config:modules/config:module/config:type = 'threadpool-dynamic'";
-            leaf core-size {
-                type uint32;
-            }
+            container threadpool-dynamic {
+                leaf core-size {
+                    type uint32;
+                }
 
-            leaf keep-alive {
-                type uint32;
-                units seconds;
-                default 10;
-            }
+                leaf keep-alive {
+                    type uint32;
+                    units seconds;
+                    default 10;
+                }
 
-            leaf maximum-size {
-                type uint32;
-                description "maximum-size description";
-            }
+                leaf maximum-size {
+                    type uint32;
+                    description "maximum-size description";
+                }
 
-            leaf binary {
-                type binary;
-            }
+                leaf binary {
+                    type binary;
+                }
 
-            container threadfactory {
-                description "threadfactory description";
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity th2:threadfactory;
+                container threadfactory {
+                    description "threadfactory description";
+                    uses config:service-ref {
+                        refine type {
+                            mandatory true;
+                            config:required-identity th2:threadfactory;
+                        }
                     }
                 }
-            }
 
-            leaf-list users  {
-                type string;
-            }
+                leaf-list users  {
+                    type string;
+                }
 
-             leaf-list users-numbers {
-                type uint32;
-                description "numbers of users description";
+                 leaf-list users-numbers {
+                    type uint32;
+                    description "numbers of users description";
+                }
             }
         }
     }
@@ -235,9 +237,11 @@ module config-threads-java {
     augment "/config:modules/config:module/config:state" {
         case threadpool-dynamic {
             when "/config:modules/config:module/config:type = 'threadpool-dynamic'";
-            // root runtime bean
-            leaf created-sessions {
-                type uint32;
+            container threadpool-dynamic {
+                // root runtime bean
+                leaf created-sessions {
+                    type uint32;
+                }
             }
         }
     }
index 78ac362e594e393b2a9128cce895d3e4d2c9f4e7..6046665f45153eb150b40ae69e06eaff015bae44 100644 (file)
@@ -1,5 +1,3 @@
-
-
 package org.opendaylight.controller.config.yang.test.impl;
 public class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule {
     public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
index ddf72f39b4da73d529ddac371b9fc64cd9158a0f..bda3548892cd31b967ea6a0ee30fb22007dd174d 100644 (file)
@@ -1,5 +1,3 @@
-
-
 package org.opendaylight.controller.config.yang.test.impl;
 public class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule {
     public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
index 943fe3b0d7709cc979a84c54ed6c7df8c24d3fc8..ab43dea5e457c3b32897196706c43232b5e402a4 100644 (file)
@@ -1,5 +1,3 @@
-
-
 package org.opendaylight.controller.config.yang.test.impl;
 public class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule {
     public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
index 7b049e7b578e9ae8d94bd85a7e4a18a842a520ca..2880b46d1f56829befc5d7be3714d67c4094f563 100644 (file)
@@ -1,5 +1,3 @@
-
-
 package org.opendaylight.controller.config.yang.test.impl;
 public class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule {
     public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
index c82da58c150ff8067c0d9933b50250228eec0431..4b006bc72e52c3026130db4b556e62fd340523da 100644 (file)
@@ -162,177 +162,179 @@ module config-test-impl {
     augment "/config:modules/config:module/config:configuration" {
         case impl-netconf {
             when "/config:modules/config:module/config:type = 'impl-netconf'";
-            leaf binaryLeaf {
-                type binary;
-                default ZGVmYXVsdEJpbg==;
-            }
-
-            leaf type {
-                type string;
-                default "default-string";
-            }
+            container impl-netconf {
+                leaf binaryLeaf {
+                    type binary;
+                    default ZGVmYXVsdEJpbg==;
+                }
 
-            leaf extended {
-                type tt:extend-once;
-                default 1;
-            }
+                leaf type {
+                    type string;
+                    default "default-string";
+                }
 
-            leaf extended-twice {
-                type tt:extend-twice;
-                default 2;
-            }
+                leaf extended {
+                    type tt:extend-once;
+                    default 1;
+                }
 
-            leaf extended-enum {
-                type tt:extend-enum;
-                default ONE;
-            }
+                leaf extended-twice {
+                    type tt:extend-twice;
+                    default 2;
+                }
 
-            leaf ip {
-                type inet:ip-address;
-                default 0:0:0:0:0:0:0:1;
-            }
+                leaf extended-enum {
+                    type tt:extend-enum;
+                    default ONE;
+                }
 
-            leaf union-test-attr {
-                type tt:unionTest;
-                default 456;
-            }
+                leaf ip {
+                    type inet:ip-address;
+                    default 0:0:0:0:0:0:0:1;
+                }
 
-            leaf sleep-factor {
-                type decimal64 {
-                    fraction-digits 2;
+                leaf union-test-attr {
+                    type tt:unionTest;
+                    default 456;
                 }
-                default 2.00;
-            }
 
-           container dto-c {
-                leaf simple-arg {
-                    type uint32;
+                leaf sleep-factor {
+                    type decimal64 {
+                        fraction-digits 2;
+                    }
+                    default 2.00;
                 }
 
-                container dto-a-inner {
+               container dto-c {
                     leaf simple-arg {
                         type uint32;
                     }
 
-                    container dto-a-inner-inner {
+                    container dto-a-inner {
                         leaf simple-arg {
                             type uint32;
                         }
+
+                        container dto-a-inner-inner {
+                            leaf simple-arg {
+                                type uint32;
+                            }
+                        }
                     }
                 }
-            }
-
-            leaf simpleInt {
-                type uint32;
-            }
-
-            leaf simpleBoolean {
-                type boolean;
-                default false;
-            }
-
-            leaf simple-long {
-                type int64;
-                default -45;
-            }
-
-            leaf simple-long-2 {
-                type uint32;
-                default 445;
-            }
 
-            leaf simple-BigInteger {
-                type uint64;
-                default 545454;
-            }
+                leaf simpleInt {
+                    type uint32;
+                }
 
-            leaf simple-byte {
-                type int8;
-                default -4;
-            }
+                leaf simpleBoolean {
+                    type boolean;
+                    default false;
+                }
 
-            leaf simple-short {
-                type uint8;
-                default 45;
-            }
+                leaf simple-long {
+                    type int64;
+                    default -45;
+                }
 
-            leaf simple-test {
-                type uint16;
-                default 99;
-            }
+                leaf simple-long-2 {
+                    type uint32;
+                    default 445;
+                }
 
-            leaf-list simple-list {
-                type uint16;
-            }
+                leaf simple-BigInteger {
+                    type uint64;
+                    default 545454;
+                }
 
-            container dto_d {
-                leaf simple-int1 {
-                    type uint32;
+                leaf simple-byte {
+                    type int8;
+                    default -4;
                 }
 
-                leaf simple-int2 {
-                    type uint32;
+                leaf simple-short {
+                    type uint8;
+                    default 45;
                 }
 
-                leaf simple-int3 {
+                leaf simple-test {
                     type uint16;
+                    default 99;
                 }
 
                 leaf-list simple-list {
                     type uint16;
                 }
 
-                list complex-dto-bInner {
-                    leaf-list simple-list {
-                        type uint16;
+                container dto_d {
+                    leaf simple-int1 {
+                        type uint32;
                     }
+
+                    leaf simple-int2 {
+                        type uint32;
+                    }
+
                     leaf simple-int3 {
                         type uint16;
                     }
 
-                    container deep {
+                    leaf-list simple-list {
+                        type uint16;
+                    }
+
+                    list complex-dto-bInner {
+                        leaf-list simple-list {
+                            type uint16;
+                        }
                         leaf simple-int3 {
                             type uint16;
-                            default 0;
+                        }
+
+                        container deep {
+                            leaf simple-int3 {
+                                type uint16;
+                                default 0;
+                            }
                         }
                     }
                 }
-            }
 
-            list complex-list {
-                list simple-list {
-                    leaf simple-int3 {
-                        type uint16;
+                list complex-list {
+                    list simple-list {
+                        leaf simple-int3 {
+                            type uint16;
+                        }
                     }
                 }
-            }
 
-            list peers {
-                    leaf port {
-                        type string;
-                    }
-                    leaf core-size {
-                        type uint32;
-                    }
-                    leaf simple-int3 {
-                        type uint16;
-                    }
-            }
+                list peers {
+                        leaf port {
+                            type string;
+                        }
+                        leaf core-size {
+                            type uint32;
+                        }
+                        leaf simple-int3 {
+                            type uint16;
+                        }
+                }
 
-            container testing-dep {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity test:testing;
+                container testing-dep {
+                    uses config:service-ref {
+                        refine type {
+                            mandatory true;
+                            config:required-identity test:testing;
+                        }
                     }
                 }
-            }
 
-            list testing-deps {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity test:testing;
+                list testing-deps {
+                    uses config:service-ref {
+                        refine type {
+                            mandatory true;
+                            config:required-identity test:testing;
+                        }
                     }
                 }
             }
@@ -342,97 +344,99 @@ module config-test-impl {
     augment "/config:modules/config:module/config:state" {
         case impl-netconf {
             when "/config:modules/config:module/config:type = 'impl-netconf'";
-            // rpc
-            rpcx:rpc-context-instance "test-rpc";
-
-            // root runtime bean
-            leaf created-sessions {
-                type uint32;
-            }
-
-            container asdf {
-                leaf simpleInt {
-                    type uint16;
-                }
+            container impl-netconf {
+                // rpc
+                rpcx:rpc-context-instance "test-rpc";
 
-                leaf simpleString {
-                    type string;
+                // root runtime bean
+                leaf created-sessions {
+                    type uint32;
                 }
-            }
 
+                container asdf {
+                    leaf simpleInt {
+                        type uint16;
+                    }
 
-            list inner-running-data-additional {
-                config:inner-state-bean;
+                    leaf simpleString {
+                        type string;
+                    }
+                }
 
-                // rpc
-                rpcx:rpc-context-instance "inner-test-rpc";
 
-                key "simpleString";
+                list inner-running-data-additional {
+                    config:inner-state-bean;
 
-                leaf simple-int3 {
-                        type uint16;
-                }
+                    // rpc
+                    rpcx:rpc-context-instance "inner-test-rpc";
 
-                leaf simpleString {
-                    type string;
-                }
+                    key "simpleString";
 
-                container deep4 {
-                    leaf boool {
-                        type boolean;
+                    leaf simple-int3 {
+                            type uint16;
                     }
-                }
-            }
-
-             list inner-running-data {
-                config:inner-state-bean;
 
-                key "simple-int3";
-
-                leaf simple-int3 {
-                        type uint16;
+                    leaf simpleString {
+                        type string;
                     }
 
-                    container deep2 {
-                    leaf boool {
-                        type boolean;
+                    container deep4 {
+                        leaf boool {
+                            type boolean;
+                        }
                     }
-                 }
+                }
 
-                list inner-inner-running-data {
+                 list inner-running-data {
                     config:inner-state-bean;
 
-                    rpcx:rpc-context-instance "inner-inner-test-rpc";
-                    rpcx:rpc-context-instance "complex-output-rpc";
-
                     key "simple-int3";
 
                     leaf simple-int3 {
-                        type uint16;
-                    }
+                            type uint16;
+                        }
 
-                    leaf-list list-of-strings {
-                        type string;
-                    }
+                        container deep2 {
+                        leaf boool {
+                            type boolean;
+                        }
+                     }
 
-                    list not-state-bean {
-                        leaf element {
-                            type string;
+                    list inner-inner-running-data {
+                        config:inner-state-bean;
+
+                        rpcx:rpc-context-instance "inner-inner-test-rpc";
+                        rpcx:rpc-context-instance "complex-output-rpc";
+
+                        key "simple-int3";
+
+                        leaf simple-int3 {
+                            type uint16;
                         }
 
-                        list not-state-bean-internal {
-                            // This should be ignored
-                            config:inner-state-bean;
+                        leaf-list list-of-strings {
+                            type string;
+                        }
 
-                            leaf element2 {
+                        list not-state-bean {
+                            leaf element {
                                 type string;
                             }
+
+                            list not-state-bean-internal {
+                                // This should be ignored
+                                config:inner-state-bean;
+
+                                leaf element2 {
+                                    type string;
+                                }
+                            }
                         }
-                    }
 
-                    container deep3 {
-                        leaf boool {
-                            type boolean;
+                        container deep3 {
+                            leaf boool {
+                                type boolean;
+                            }
                         }
                     }
                 }
index 1414fac2f33999f02ed9f5c7877530b51d47d7ac..31cdedd5724f89a0da51f2880219b765562b1605 100644 (file)
       <version>${karaf.version}</version>
       <type>kar</type>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
     <!-- scope is runtime so the feature repo is listed in the features
       service config file, and features may be installed using the
       karaf-maven-plugin configuration -->
-    <!-- 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>config-features</artifactId>
+      <version>${config.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <!--<dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>base-features</artifactId>
+      <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 72ce89d14e9c7fced35c16b91577d36d0a503384..52aa6d276b7337a60bbfc891f32393416cccbd8c 100644 (file)
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-monitoring</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-netty-util</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>netconf-ssh</artifactId>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>concepts</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>object-cache-api</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>object-cache-guava</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>restconf-client-api</artifactId>
           <groupId>org.opendaylight.yangtools.model</groupId>
           <artifactId>ietf-inet-types</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools.model</groupId>
+          <artifactId>ietf-restconf</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.yangtools.model</groupId>
           <artifactId>ietf-topology</artifactId>
           <groupId>org.opendaylight.yangtools.model</groupId>
           <artifactId>ietf-yang-types</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools.model</groupId>
+          <artifactId>ietf-yang-types-20130715</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.yangtools.model</groupId>
           <artifactId>opendaylight-l2-types</artifactId>
index c958039b5f0465206626eb009e33385df5b11d2f..f15f8f7404d1420d0efc361551c99b0355d60170 100644 (file)
@@ -13,11 +13,13 @@ osgi.bundles=\
     reference\:file\:../lib/jersey-server-1.17.jar@2:start
 
 # Netconf startup configuration
-netconf.tcp.address=127.0.0.1
-netconf.tcp.port=8383
 
-netconf.tcp.client.address=127.0.0.1
-netconf.tcp.client.port=8383
+# Netconf tcp address:port is optional with default value 127.0.0.1:8383
+#netconf.tcp.address=127.0.0.1
+#netconf.tcp.port=8384
+
+#netconf.tcp.client.address=127.0.0.1
+#netconf.tcp.client.port=8384
 
 netconf.ssh.address=0.0.0.0
 netconf.ssh.port=1830
index 6d90eb39dad12dcc598aa82e3935ced0443c4fe2..8901c2e0b5777cb22c81e1431f3fa10498c746be 100644 (file)
@@ -16,7 +16,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>${bundle.plugin.version}</version>
         <extensions>true</extensions>
         <configuration>
           <instructions>
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>
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.java
new file mode 100644 (file)
index 0000000..b3a89a4
--- /dev/null
@@ -0,0 +1,238 @@
+/**
+ * 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.compatibility;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.controller.sal.discovery.IDiscoveryService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
+import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
+import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
+import org.opendaylight.controller.sal.packet.IPluginInDataPacketService;
+import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService;
+import org.opendaylight.controller.sal.reader.IPluginInReadService;
+import org.opendaylight.controller.sal.reader.IPluginOutReadService;
+import org.opendaylight.controller.sal.topology.IPluginInTopologyService;
+import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.INodeConnectorFactory;
+import org.opendaylight.controller.sal.utils.INodeFactory;
+import org.osgi.framework.BundleContext;
+
+import com.google.common.base.Preconditions;
+
+public class ComponentActivator extends ComponentActivatorAbstractBase {
+    private final INodeConnectorFactory nodeConnectorFactory = new MDSalNodeConnectorFactory();
+    private final DataPacketServiceAdapter dataPacketService = new DataPacketServiceAdapter();
+    private final InventoryAndReadAdapter inventory = new InventoryAndReadAdapter();
+    private final FlowProgrammerAdapter flow = new FlowProgrammerAdapter();
+    private final DataPacketAdapter dataPacket = new DataPacketAdapter();
+    private final TopologyProvider tpProvider = new TopologyProvider();
+    private final INodeFactory nodeFactory = new MDSalNodeFactory();
+    private final TopologyAdapter topology = new TopologyAdapter();
+    private BundleContext context;
+
+    public INodeConnectorFactory getNodeConnectorFactory() {
+        return nodeConnectorFactory;
+    }
+
+    public DataPacketServiceAdapter getDataPacketService() {
+        return dataPacketService;
+    }
+
+    public InventoryAndReadAdapter getInventory() {
+        return inventory;
+    }
+
+    public FlowProgrammerAdapter getFlow() {
+        return flow;
+    }
+
+    public DataPacketAdapter getDataPacket() {
+        return dataPacket;
+    }
+
+    public TopologyProvider getTpProvider() {
+        return tpProvider;
+    }
+
+    public INodeFactory getNodeFactory() {
+        return nodeFactory;
+    }
+
+    public TopologyAdapter getTopology() {
+        return topology;
+    }
+
+    @Override
+    protected void init() {
+        NodeIDType.registerIDType(NodeMapping.MD_SAL_TYPE, String.class);
+        NodeConnectorIDType.registerIDType(NodeMapping.MD_SAL_TYPE, String.class, NodeMapping.MD_SAL_TYPE);
+    }
+
+    @Override
+    public void start(final BundleContext context) {
+        super.start(context);
+        this.context = Preconditions.checkNotNull(context);
+    }
+
+    public ProviderContext setBroker(final BindingAwareBroker broker) {
+        return broker.registerProvider(new SalCompatibilityProvider(this), context);
+    }
+
+    @Override
+    protected Object[] getGlobalImplementations() {
+        return new Object[] {
+                flow,
+                inventory,
+                dataPacket,
+                nodeFactory,
+                nodeConnectorFactory,
+                topology,
+                tpProvider,
+        };
+    }
+
+    @Override
+    protected void configureGlobalInstance(final Component c, final Object imp) {
+        if (imp instanceof DataPacketAdapter) {
+            _configure((DataPacketAdapter)imp, c);
+        } else if (imp instanceof FlowProgrammerAdapter) {
+            _configure((FlowProgrammerAdapter)imp, c);
+        } else if (imp instanceof InventoryAndReadAdapter) {
+            _configure((InventoryAndReadAdapter)imp, c);
+        } else if (imp instanceof ComponentActivator) {
+            _configure((ComponentActivator)imp, c);
+        } else if (imp instanceof MDSalNodeConnectorFactory) {
+            _configure((MDSalNodeConnectorFactory)imp, c);
+        } else if (imp instanceof MDSalNodeFactory) {
+            _configure((MDSalNodeFactory)imp, c);
+        } else if (imp instanceof TopologyAdapter) {
+            _configure((TopologyAdapter)imp, c);
+        } else if (imp instanceof TopologyProvider) {
+            _configure((TopologyProvider)imp, c);
+        } else {
+            throw new IllegalArgumentException(String.format("Unhandled implementation class %s", imp.getClass()));
+        }
+    }
+
+    @Override
+    protected Object[] getImplementations() {
+        return new Object[] {
+                dataPacketService,
+        };
+    }
+
+    @Override
+    protected void configureInstance(final Component c, final Object imp, final String containerName) {
+        if (imp instanceof ComponentActivator) {
+            _instanceConfigure((ComponentActivator)imp, c, containerName);
+        } else if (imp instanceof DataPacketServiceAdapter) {
+            _instanceConfigure((DataPacketServiceAdapter)imp, c, containerName);
+        } else {
+            throw new IllegalArgumentException(String.format("Unhandled implementation class %s", imp.getClass()));
+        }
+    }
+
+    private void _configure(final MDSalNodeFactory imp, final Component it) {
+        it.setInterface(INodeFactory.class.getName(), properties());
+    }
+
+    private void _configure(final MDSalNodeConnectorFactory imp, final Component it) {
+        it.setInterface(INodeConnectorFactory.class.getName(), properties());
+    }
+
+    private void _configure(final ComponentActivator imp, final Component it) {
+        it.add(createServiceDependency()
+                .setService(BindingAwareBroker.class)
+                .setCallbacks("setBroker", "setBroker")
+                .setRequired(true));
+    }
+
+    private void _configure(final DataPacketAdapter imp, final Component it) {
+        it.add(createServiceDependency()
+                .setService(IPluginOutDataPacketService.class)
+                .setCallbacks("setDataPacketPublisher", "setDataPacketPublisher")
+                .setRequired(false));
+    }
+
+    private void _configure(final FlowProgrammerAdapter imp, final Component it) {
+        it.setInterface(IPluginInFlowProgrammerService.class.getName(), properties());
+        it.add(createServiceDependency()
+                .setService(IPluginOutFlowProgrammerService.class)
+                .setCallbacks("setFlowProgrammerPublisher", "setFlowProgrammerPublisher")
+                .setRequired(false));
+        it.add(createServiceDependency()
+                .setService(IClusterGlobalServices.class)
+                .setCallbacks("setClusterGlobalServices", "unsetClusterGlobalServices")
+                .setRequired(false));
+    }
+
+    private void _instanceConfigure(final DataPacketServiceAdapter imp, final Component it, final String containerName) {
+        it.setInterface(IPluginInDataPacketService.class.getName(), properties());
+    }
+
+    private void _instanceConfigure(final ComponentActivator imp, final Component it, final String containerName) {
+        // No-op
+    }
+
+    private void _configure(final InventoryAndReadAdapter imp, final Component it) {
+        it.setInterface(new String[] {
+                IPluginInInventoryService.class.getName(),
+                IPluginInReadService.class.getName(),
+        }, properties());
+
+        it.add(createServiceDependency()
+                .setService(IPluginOutReadService.class)
+                .setCallbacks("setReadPublisher", "unsetReadPublisher")
+                .setRequired(false));
+        it.add(createServiceDependency()
+                .setService(IPluginOutInventoryService.class)
+                .setCallbacks("setInventoryPublisher", "unsetInventoryPublisher")
+                .setRequired(false));
+        it.add(createServiceDependency()
+                .setService(IDiscoveryService.class)
+                .setCallbacks("setDiscoveryPublisher", "setDiscoveryPublisher")
+                .setRequired(false));
+    }
+
+    private void _configure(final TopologyAdapter imp, final Component it) {
+        it.setInterface(IPluginInTopologyService.class.getName(), properties());
+
+        it.add(createServiceDependency()
+                .setService(IPluginOutTopologyService.class)
+                .setCallbacks("setTopologyPublisher", "setTopologyPublisher")
+                .setRequired(false));
+    }
+
+    private void _configure(final TopologyProvider imp, final Component it) {
+        it.add(createServiceDependency()
+                .setService(IPluginOutTopologyService.class)
+                .setCallbacks("setTopologyPublisher", "setTopologyPublisher")
+                .setRequired(false));
+    }
+
+    private Dictionary<String,Object> properties() {
+        final Hashtable<String,Object> props = new Hashtable<String, Object>();
+        props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), NodeMapping.MD_SAL_TYPE);
+        props.put("protocolName", NodeMapping.MD_SAL_TYPE);
+        return props;
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend
deleted file mode 100644 (file)
index 00ce312..0000000
+++ /dev/null
@@ -1,260 +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.compatibility
-
-import java.util.Arrays
-import java.util.Dictionary
-import java.util.Hashtable
-import org.apache.felix.dm.Component
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext
-import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer
-import org.opendaylight.controller.sal.binding.api.NotificationService
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.compatibility.topology.TopologyAdapter
-import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.core.NodeConnector
-import org.opendaylight.controller.sal.discovery.IDiscoveryService
-import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService
-import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService
-import org.opendaylight.controller.sal.inventory.IPluginInInventoryService
-import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService
-import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService
-import org.opendaylight.controller.sal.reader.IPluginInReadService
-import org.opendaylight.controller.sal.reader.IPluginOutReadService
-import org.opendaylight.controller.sal.topology.IPluginInTopologyService
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.controller.sal.utils.GlobalConstants
-import org.opendaylight.controller.sal.utils.INodeConnectorFactory
-import org.opendaylight.controller.sal.utils.INodeFactory
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices
-import org.opendaylight.controller.sal.packet.IPluginInDataPacketService
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService
-import org.osgi.framework.BundleContext
-
-import static org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider
-import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-
-class ComponentActivator extends ComponentActivatorAbstractBase {
-
-    private BundleContext context;
-
-    @Property
-    FlowProgrammerAdapter flow = new FlowProgrammerAdapter;
-
-    @Property
-    InventoryAndReadAdapter inventory = new InventoryAndReadAdapter;
-
-    @Property
-    DataPacketAdapter dataPacket = new DataPacketAdapter;
-
-    @Property
-    INodeFactory nodeFactory = new MDSalNodeFactory
-
-    @Property
-    INodeConnectorFactory nodeConnectorFactory = new MDSalNodeConnectorFactory
-    
-    @Property
-    TopologyAdapter topology = new TopologyAdapter
-    
-    @Property
-    TopologyProvider tpProvider = new TopologyProvider()
-
-    @Property
-    DataPacketServiceAdapter dataPacketService = new DataPacketServiceAdapter()
-
-
-
-    override protected init() {
-        Node.NodeIDType.registerIDType(MD_SAL_TYPE, String);
-        NodeConnector.NodeConnectorIDType.registerIDType(MD_SAL_TYPE, String, MD_SAL_TYPE);
-    }
-
-    override start(BundleContext context) {
-        super.start(context)
-        this.context = context;
-    }
-
-    def setBroker(BindingAwareBroker broker) {
-        broker.registerProvider(new SalCompatibilityProvider(this), context)
-    }
-
-
-    override protected getGlobalImplementations() {
-        return Arrays.asList(this, flow, inventory, dataPacket, nodeFactory, nodeConnectorFactory,topology,tpProvider)
-    }
-
-    override protected configureGlobalInstance(Component c, Object imp) {
-        configure(imp, c);
-    }
-
-    override protected getImplementations() {
-        return Arrays.asList(dataPacketService)
-    }
-
-    override protected configureInstance(Component c, Object imp, String containerName) {
-        instanceConfigure(imp, c, containerName);
-    }
-
-    private def dispatch configure(MDSalNodeFactory imp, Component it) {
-        setInterface(INodeFactory.name, properties);
-    }
-
-    private def dispatch configure(MDSalNodeConnectorFactory imp, Component it) {
-        setInterface(INodeConnectorFactory.name, properties);
-    }
-
-    private def dispatch configure(ComponentActivator imp, Component it) {
-        add(
-            createServiceDependency().setService(BindingAwareBroker) //
-            .setCallbacks("setBroker", "setBroker") //
-            .setRequired(true))
-
-
-    }
-
-    private def dispatch configure(DataPacketAdapter imp, Component it) {
-        add(
-            createServiceDependency() //
-            .setService(IPluginOutDataPacketService) //
-            .setCallbacks("setDataPacketPublisher", "setDataPacketPublisher") //
-            .setRequired(false))
-    }
-
-    private def dispatch configure(FlowProgrammerAdapter imp, Component it) {
-        setInterface(IPluginInFlowProgrammerService.name, properties)
-        add(
-            createServiceDependency() //
-            .setService(IPluginOutFlowProgrammerService) //
-            .setCallbacks("setFlowProgrammerPublisher", "setFlowProgrammerPublisher") //
-            .setRequired(false))
-
-        add(
-            createServiceDependency() //
-            .setService(IClusterGlobalServices) //
-            .setCallbacks("setClusterGlobalServices", "unsetClusterGlobalServices") //
-            .setRequired(false))
-
-    }
-
-    private def dispatch instanceConfigure(DataPacketServiceAdapter imp, Component it, String containerName) {
-        setInterface(IPluginInDataPacketService.name, properties)
-    }
-
-    private def dispatch instanceConfigure(ComponentActivator imp, Component it, String containerName) {
-    }
-
-
-    private def dispatch configure(InventoryAndReadAdapter imp, Component it) {
-        setInterface(Arrays.asList(IPluginInInventoryService.name, IPluginInReadService.name), properties)
-        add(
-            createServiceDependency() //
-            .setService(IPluginOutReadService) //
-            .setCallbacks("setReadPublisher", "unsetReadPublisher") //
-            .setRequired(false))
-        add(
-            createServiceDependency() //
-            .setService(IPluginOutInventoryService) //
-            .setCallbacks("setInventoryPublisher", "unsetInventoryPublisher") //
-            .setRequired(false))
-        add(
-            createServiceDependency() //
-            .setService(IDiscoveryService) //
-            .setCallbacks("setDiscoveryPublisher", "setDiscoveryPublisher") //
-            .setRequired(false))
-
-        
-    }
-    
-    private def dispatch configure (TopologyAdapter imp, Component it) {
-        setInterface(Arrays.asList(IPluginInTopologyService.name), properties)
-        add(
-            createServiceDependency() //
-            .setService(IPluginOutTopologyService) //
-            .setCallbacks("setTopologyPublisher", "setTopologyPublisher") //
-            .setRequired(false))
-    }
-    
-    private def dispatch configure (TopologyProvider imp, Component it) {
-        add(
-            createServiceDependency() //
-            .setService(IPluginOutTopologyService) //
-            .setCallbacks("setTopologyPublisher", "setTopologyPublisher") //
-            .setRequired(false))
-    }
-
-    private def Dictionary<String, Object> properties() {
-        val props = new Hashtable<String, Object>();
-        props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString, MD_SAL_TYPE)
-        props.put("protocolName", MD_SAL_TYPE);
-        return props;
-    }
-}
-package class SalCompatibilityProvider implements BindingAwareProvider {
-    
-    private val ComponentActivator activator;
-    
-    new(ComponentActivator cmpAct) {
-        activator = cmpAct;
-    }
-    
-    override getFunctionality() {
-        // Noop
-    }
-    
-    override getImplementations() {
-        // Noop
-    }
-    
-    
-    override onSessionInitialized(ConsumerContext session) {
-        // Noop
-    }
-    
-    
-    override onSessionInitiated(ProviderContext session) {
-        val it = activator
-                val subscribe = session.getSALService(NotificationService)
-
-        // Registration of Flow Service
-        flow.delegate = session.getRpcService(SalFlowService)
-        flow.dataBrokerService = session.getSALService(DataBrokerService);
-        subscribe.registerNotificationListener(flow);
-
-        // Data Packet Service
-        subscribe.registerNotificationListener(inventory);
-        dataPacketService.delegate = session.getRpcService(PacketProcessingService)
-
-        // Inventory Service
-        inventory.dataService = session.getSALService(DataBrokerService);
-        inventory.flowStatisticsService = session.getRpcService(OpendaylightFlowStatisticsService);
-        inventory.flowTableStatisticsService = session.getRpcService(OpendaylightFlowTableStatisticsService);
-        inventory.nodeConnectorStatisticsService = session.getRpcService(OpendaylightPortStatisticsService);
-        inventory.topologyDiscovery = session.getRpcService(FlowTopologyDiscoveryService);
-        inventory.dataProviderService = session.getSALService(DataProviderService)
-        topology.dataService = session.getSALService(DataProviderService)
-        tpProvider.dataService = session.getSALService(DataProviderService)
-
-        inventory.startAdapter();
-
-        tpProvider.startAdapter();
-
-        subscribe.registerNotificationListener(dataPacket)
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.java
new file mode 100644 (file)
index 0000000..f95f978
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.compatibility;
+
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService;
+import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class DataPacketAdapter implements PacketProcessingListener {
+    private static final Logger LOG = LoggerFactory.getLogger(DataPacketAdapter.class);
+    private IPluginOutDataPacketService dataPacketPublisher;
+
+    @Override
+    public void onPacketReceived(final PacketReceived packet) {
+        try {
+            RawPacket inPacket = toRawPacket(packet);
+            dataPacketPublisher.receiveDataPacket(inPacket);
+        } catch (ConstructionException e) {
+            LOG.warn("Failed to construct raw packet from {}, dropping it", packet, e);
+        }
+    }
+
+    public static RawPacket toRawPacket(final PacketReceived received) throws ConstructionException {
+        final RawPacket ret = new RawPacket(received.getPayload());
+        ret.setIncomingNodeConnector(NodeMapping.toADNodeConnector(received.getIngress()));
+        return ret;
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend
deleted file mode 100644 (file)
index 8581d4a..0000000
+++ /dev/null
@@ -1,31 +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.compatibility
-
-import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived
-import org.opendaylight.controller.sal.packet.RawPacket
-
-class DataPacketAdapter implements PacketProcessingListener {
-
-    @Property
-    IPluginOutDataPacketService dataPacketPublisher;
-
-    override onPacketReceived(PacketReceived packet) {
-        val RawPacket inPacket = packet.toRawPacket();
-        dataPacketPublisher.receiveDataPacket(inPacket);
-    }
-
-    public static def RawPacket toRawPacket(PacketReceived received) {        
-        val ret = new RawPacket(received.payload);
-        ret.setIncomingNodeConnector(NodeMapping.toADNodeConnector(received.ingress))
-        return ret;
-    }
-
-}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.java
new file mode 100644 (file)
index 0000000..e5a9d3e
--- /dev/null
@@ -0,0 +1,302 @@
+/**
+ * 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.compatibility;
+
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+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.cacheMode;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+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.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
+    private final static Logger LOG = LoggerFactory.getLogger(FlowProgrammerAdapter.class);
+
+    // Note: clustering services manipulate this
+    private final Map<Flow, UUID> flowToFlowId = new ConcurrentHashMap<Flow, UUID>();
+    private final static String CACHE_NAME = "flowprogrammeradapter.flowtoid";
+
+    // These are injected via Apache DM (see ComponentActivator)
+    private IPluginOutFlowProgrammerService flowProgrammerPublisher;
+    private IClusterGlobalServices clusterGlobalServices;
+    private DataBrokerService dataBrokerService;
+    private SalFlowService delegate;
+
+    public SalFlowService getDelegate() {
+        return this.delegate;
+    }
+
+    public void setDelegate(final SalFlowService delegate) {
+        this.delegate = delegate;
+    }
+
+    public DataBrokerService getDataBrokerService() {
+        return this.dataBrokerService;
+    }
+
+    public void setDataBrokerService(final DataBrokerService dataBrokerService) {
+        this.dataBrokerService = dataBrokerService;
+    }
+
+    public IPluginOutFlowProgrammerService getFlowProgrammerPublisher() {
+        return this.flowProgrammerPublisher;
+    }
+
+    public void setFlowProgrammerPublisher(final IPluginOutFlowProgrammerService flowProgrammerPublisher) {
+        this.flowProgrammerPublisher = flowProgrammerPublisher;
+    }
+
+    public IClusterGlobalServices getClusterGlobalServices() {
+        return this.clusterGlobalServices;
+    }
+
+    public void setClusterGlobalServices(final IClusterGlobalServices clusterGlobalServices) {
+        this.clusterGlobalServices = clusterGlobalServices;
+    }
+
+    @Override
+    public Status addFlow(final Node node, final Flow flow) {
+        return toFutureStatus(internalAddFlowAsync(node, flow, 0));
+    }
+
+    @Override
+    public Status modifyFlow(final Node node, final Flow oldFlow, final Flow newFlow) {
+        return toFutureStatus(internalModifyFlowAsync(node, oldFlow, newFlow, 0));
+    }
+
+    @Override
+    public Status removeFlow(final Node node, final Flow flow) {
+        return toFutureStatus(internalRemoveFlowAsync(node, flow, 0));
+    }
+
+    @Override
+    public Status addFlowAsync(final Node node, final Flow flow, final long rid) {
+        // FIXME is this correct? What if the future fails?
+        this.internalAddFlowAsync(node, flow, rid);
+        return FlowProgrammerAdapter.toStatus(true);
+    }
+
+    @Override
+    public Status modifyFlowAsync(final Node node, final Flow oldFlow, final Flow newFlow, final long rid) {
+        // FIXME is this correct? What if the future fails?
+        this.internalModifyFlowAsync(node, oldFlow, newFlow, rid);
+        return FlowProgrammerAdapter.toStatus(true);
+    }
+
+    @Override
+    public Status removeFlowAsync(final Node node, final Flow flow, final long rid) {
+        // FIXME is this correct? What if the future fails?
+        this.internalRemoveFlowAsync(node, flow, rid);
+        return FlowProgrammerAdapter.toStatus(true);
+    }
+
+    @Override
+    public Status removeAllFlows(final Node node) {
+        // FIXME: unfinished?
+        return new Status(StatusCode.SUCCESS);
+    }
+
+    @Override
+    public Status syncSendBarrierMessage(final Node node) {
+        // FIXME: unfinished?
+        return null;
+    }
+
+    @Override
+    public Status asyncSendBarrierMessage(final Node node) {
+        // FIXME: unfinished?
+        return null;
+    }
+
+    private static Status toStatus(final boolean successful) {
+        return new Status(successful ? StatusCode.SUCCESS : StatusCode.INTERNALERROR);
+    }
+
+    public static Status toStatus(final RpcResult<? extends Object> result) {
+        return toStatus(result.isSuccessful());
+    }
+
+    @Override
+    public void onFlowAdded(final FlowAdded notification) {
+        // FIXME: unfinished?
+    }
+
+    @Override
+    public void onFlowRemoved(final FlowRemoved notification) {
+        if (notification == null) {
+            return;
+        }
+
+        final NodeRef node = notification.getNode();
+        if (node == null) {
+            LOG.debug("Notification {} has not node, ignoring it", notification);
+            return;
+        }
+
+        Node adNode;
+        try {
+            adNode = NodeMapping.toADNode(notification.getNode());
+        } catch (ConstructionException e) {
+            LOG.warn("Failed to construct AD node for {}, ignoring notification", node, e);
+            return;
+        }
+        flowProgrammerPublisher.flowRemoved(adNode, ToSalConversionsUtils.toFlow(notification, adNode));
+    }
+
+    @Override
+    public void onFlowUpdated(final FlowUpdated notification) {
+        // FIXME: unfinished?
+    }
+
+    @Override
+    public void onSwitchFlowRemoved(final SwitchFlowRemoved notification) {
+        // FIXME: unfinished?
+    }
+
+    @Override
+    public void onNodeErrorNotification(final NodeErrorNotification notification) {
+        // FIXME: unfinished?
+    }
+
+    @Override
+    public void onNodeExperimenterErrorNotification(final NodeExperimenterErrorNotification notification) {
+        // FIXME: unfinished?
+    }
+
+    private static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow> flowPath(
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, final NodeKey nodeKey) {
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, nodeKey)
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(flow.getTableId()))
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow.class, new FlowKey(flow.getId()))
+                .toInstance();
+    }
+
+    private Future<RpcResult<TransactionStatus>> writeFlowAsync(final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, final NodeKey nodeKey) {
+        final DataModificationTransaction modification = this.dataBrokerService.beginTransaction();
+        modification.putConfigurationData(flowPath(flow, nodeKey), flow);
+        return modification.commit();
+    }
+
+    private Future<RpcResult<TransactionStatus>> internalAddFlowAsync(final Node node, final Flow flow, final long rid) {
+        final Map<Flow,UUID> cache = this.getCache();
+        UUID flowId = cache.get(flow);
+        if (flowId != null) {
+            this.removeFlow(node, flow);
+        }
+
+        flowId = UUID.randomUUID();
+        cache.put(flow, flowId);
+        return this.writeFlowAsync(MDFlowMapping.toMDFlow(flow, flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+    }
+
+    private Future<RpcResult<TransactionStatus>> internalModifyFlowAsync(final Node node, final Flow oldFlow, final Flow newFlow, final long rid) {
+        final Map<Flow,UUID> cache = this.getCache();
+
+        UUID flowId = cache.remove(oldFlow);
+        if (flowId == null) {
+            flowId = UUID.randomUUID();
+            cache.put(oldFlow, flowId);
+            LOG.warn("Could not find flow {} in cache, assigned new ID {}", oldFlow.hashCode(), flowId);
+        }
+
+        cache.put(newFlow, flowId);
+        return this.writeFlowAsync(MDFlowMapping.toMDFlow(newFlow, flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+    }
+
+    private Future<RpcResult<TransactionStatus>> internalRemoveFlowAsync(final Node node, final Flow adflow, final long rid) {
+        final Map<Flow,UUID> cache = this.getCache();
+
+        final UUID flowId = cache.remove(adflow);
+        if (flowId == null) {
+            LOG.warn("Could not find flow {} in cache, nothing to do", adflow.hashCode());
+            return null;
+        }
+
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow = MDFlowMapping.toMDFlow(adflow, flowId.toString());
+        final DataModificationTransaction modification = this.dataBrokerService.beginTransaction();
+        modification.removeConfigurationData(flowPath(flow, new NodeKey(new NodeId(node.getNodeIDString()))));
+        return modification.commit();
+    }
+
+    private static Status toFutureStatus(final Future<RpcResult<TransactionStatus>> future) {
+        if (future == null) {
+            // FIXME: really?
+            return FlowProgrammerAdapter.toStatus(true);
+        }
+
+        try {
+            final RpcResult<TransactionStatus> result = future.get();
+            return FlowProgrammerAdapter.toStatus(result);
+        } catch (final InterruptedException e) {
+            FlowProgrammerAdapter.LOG.error("Interrupted while processing flow", e);
+        } catch (ExecutionException e) {
+            FlowProgrammerAdapter.LOG.error("Failed to process flow", e);
+        }
+
+        return new Status(StatusCode.INTERNALERROR);
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<Flow,UUID> getCache() {
+        final IClusterGlobalServices cgs = getClusterGlobalServices();
+        if (cgs == null) {
+            return new ConcurrentHashMap<Flow, UUID>();
+        }
+
+        Map<Flow, UUID> cache = (Map<Flow, UUID>) cgs.getCache(FlowProgrammerAdapter.CACHE_NAME);
+        if (cache != null) {
+            return cache;
+        }
+
+        try {
+            return (Map<Flow, UUID>) cgs.createCache(CACHE_NAME, EnumSet.of(cacheMode.TRANSACTIONAL));
+        } catch (CacheExistException e) {
+            return (Map<Flow, UUID>) cgs.getCache(CACHE_NAME);
+        } catch (CacheConfigException e) {
+            throw new IllegalStateException("Unexpected cache configuration problem", e);
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend
deleted file mode 100644 (file)
index 8a0874e..0000000
+++ /dev/null
@@ -1,269 +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.compatibility
-
-import java.util.Map
-import java.util.UUID
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.Future
-import java.util.EnumSet
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.flowprogrammer.Flow
-import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService
-import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService
-import org.opendaylight.controller.sal.utils.Status
-import org.opendaylight.controller.sal.utils.StatusCode
-import org.opendaylight.controller.clustering.services.CacheExistException
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices
-import org.opendaylight.controller.clustering.services.IClusterServices
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.slf4j.LoggerFactory
-
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-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.FlowKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
-
-
-import static extension org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
-
-import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import static extension org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*
-
-class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
-
-    private static val LOG = LoggerFactory.getLogger(FlowProgrammerAdapter);
-    private static val CACHE_NAME = "flowprogrammeradapter.flowtoid";
-
-    @Property
-    private SalFlowService delegate;
-
-    @Property
-    private DataBrokerService dataBrokerService;
-    
-    @Property
-    private IPluginOutFlowProgrammerService flowProgrammerPublisher;
-
-    @Property
-    private IClusterGlobalServices clusterGlobalServices;
-
-
-    @Property
-    private Map<Flow, UUID> flowToFlowId = new ConcurrentHashMap<Flow, UUID>();
-
-
-    override addFlow(Node node, Flow flow) {
-        return toFutureStatus(internalAddFlowAsync(node,flow,0));
-    }
-
-    override modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
-        return toFutureStatus(internalModifyFlowAsync(node, oldFlow,newFlow,0));
-    }
-
-    override removeFlow(Node node, Flow flow) {
-        return toFutureStatus(internalRemoveFlowAsync(node, flow,0));
-    }
-
-    override addFlowAsync(Node node, Flow flow, long rid) {
-        internalAddFlowAsync(node, flow, rid);
-        return toStatus(true);
-    }
-
-    override modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
-        internalModifyFlowAsync(node, oldFlow, newFlow, rid);
-        return toStatus(true);
-    }
-
-    override removeFlowAsync(Node node, Flow flow, long rid) {
-        internalRemoveFlowAsync(node, flow, rid);
-        return toStatus(true);
-    }
-
-    override removeAllFlows(Node node) {
-        // I know this looks like a copout... but its exactly what the legacy OFplugin did
-        return new Status(StatusCode.SUCCESS);
-    }
-
-    override syncSendBarrierMessage(Node node) {
-
-        // FIXME: Update YANG model
-        return null;
-    }
-
-    override asyncSendBarrierMessage(Node node) {
-
-        // FIXME: Update YANG model
-        return null;
-    }
-
-    private static def toStatus(boolean successful) {
-        if (successful) {
-            return new Status(StatusCode.SUCCESS);
-        } else {
-            return new Status(StatusCode.INTERNALERROR);
-        }
-    }
-
-    public static def toStatus(RpcResult<?> result) {
-        return toStatus(result.isSuccessful());
-    }
-    
-    private static dispatch def Status processException(InterruptedException e) {
-        LOG.error("Interruption occured during processing flow",e);
-        return new Status(StatusCode.INTERNALERROR);
-    }
-    
-    private static dispatch def Status processException(ExecutionException e) {
-        LOG.error("Execution exception occured during processing flow",e.cause);
-        return new Status(StatusCode.INTERNALERROR);
-    }
-    
-    private static dispatch def Status processException(Exception e) {
-        throw new RuntimeException(e);
-    }
-    
-    override onFlowAdded(FlowAdded notification) {
-        // NOOP : Not supported by AD SAL
-    }
-    
-    override onFlowRemoved(FlowRemoved notification) {
-        if(notification != null && notification.node != null) {
-            val adNode = notification.node.toADNode
-            if(adNode != null) {
-                flowProgrammerPublisher.flowRemoved(adNode,notification.toFlow(adNode));
-            }
-        } 
-    }
-    
-    override onFlowUpdated(FlowUpdated notification) {
-        // NOOP : Not supported by AD SAL
-    }
-    
-    override onSwitchFlowRemoved(SwitchFlowRemoved notification) {
-        // NOOP : Not supported by AD SAL
-    }
-    
-     override onNodeErrorNotification(NodeErrorNotification notification) {
-        // NOOP : Not supported by AD SAL
-    }
-    
-     override onNodeExperimenterErrorNotification(
-                NodeExperimenterErrorNotification notification) {
-        // NOOP : Not supported by AD SAL
-    }
-
-    private def Future<RpcResult<TransactionStatus>> writeFlowAsync(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, NodeKey nodeKey){
-        val modification = this._dataBrokerService.beginTransaction();
-        val flowPath = InstanceIdentifier.builder(Nodes)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, nodeKey)
-                .augmentation(FlowCapableNode)
-                .child(Table, new TableKey(flow.getTableId()))
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
-                .build;
-        modification.putConfigurationData(flowPath, flow);
-        return modification.commit();
-    }
-
-    private def Future<RpcResult<TransactionStatus>> internalAddFlowAsync(Node node, Flow flow, long rid){
-        var flowId = getCache().get(flow);
-        if(flowId != null) {
-            removeFlow(node, flow);
-            return internalAddFlowAsync(node, flow, rid);
-        }
-
-        flowId = UUID.randomUUID();
-        getCache().put(flow, flowId);
-
-        return writeFlowAsync(flow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
-    }
-
-    private def Future<RpcResult<TransactionStatus>> internalModifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
-        var flowId = getCache().remove(oldFlow);
-        if(flowId == null){
-            LOG.error("oldFlow not found in cache : " + oldFlow.hashCode);
-            flowId = UUID.randomUUID();
-            getCache().put(oldFlow, flowId);
-        }
-
-        getCache().put(newFlow, flowId);
-        return writeFlowAsync(newFlow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
-    }
-
-
-    private def Future<RpcResult<TransactionStatus>> internalRemoveFlowAsync(Node node, Flow adflow, long rid){
-        val flowId = getCache().remove(adflow);
-        if(flowId == null){
-            //throw new IllegalArgumentException("adflow not found in cache : " + adflow.hashCode);
-            LOG.error("adflow not found in cache : " + adflow.hashCode);
-            return null;
-        }
-        val flow = adflow.toMDFlow(flowId.toString());
-        val modification = this._dataBrokerService.beginTransaction();
-        val flowPath = InstanceIdentifier.builder(Nodes)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, new NodeKey(new NodeId(node.getNodeIDString())))
-                .augmentation(FlowCapableNode)
-                .child(Table, new TableKey(flow.getTableId()))
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
-                .build;
-        modification.removeConfigurationData(flowPath);
-        return modification.commit();
-    }
-
-    private def toFutureStatus(Future<RpcResult<TransactionStatus>> future){
-        if(future == null){
-            return toStatus(true);
-        }
-
-        try {
-            val result = future.get();
-            return toStatus(result);
-        } catch (InterruptedException e) {
-            return processException(e);
-        } catch (ExecutionException e) {
-            return processException(e);
-        } catch (Exception e){
-            processException(e);
-        }
-        return toStatus(false);
-    }
-
-    private def Map<Flow, UUID> getCache(){
-        if(clusterGlobalServices == null){
-            return new ConcurrentHashMap<Flow, UUID>();
-        }
-
-        var cache = clusterGlobalServices.getCache(CACHE_NAME);
-
-        if(cache == null) {
-            try {
-                cache = clusterGlobalServices.createCache(CACHE_NAME, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-            } catch (CacheExistException e) {
-                cache = clusterGlobalServices.getCache(CACHE_NAME);
-            }
-        }
-        return cache as Map<Flow, UUID>;
-
-    }
-
-}
index f54defdf14498960fc73726b541f6775f0110362..8908504f15171ebe2018ee5feb4915fe199b67a6 100644 (file)
@@ -10,11 +10,13 @@ package org.opendaylight.controller.sal.compatibility
 import java.util.ArrayList
 import java.util.Collections
 import java.util.List
+import java.util.Map
 import java.util.Set
-import java.util.ArrayList;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.CopyOnWriteArrayList
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
 import org.opendaylight.controller.sal.core.Edge
@@ -76,10 +78,6 @@ import org.slf4j.LoggerFactory
 
 import static extension org.opendaylight.controller.sal.common.util.Arguments.*
 import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import java.util.concurrent.ConcurrentHashMap
-import java.util.Map
-import java.util.HashMap
 
 class InventoryAndReadAdapter implements IPluginInReadService,
                                              IPluginInInventoryService,
index c4c1ee93519cf4276de26115419e0de187655fca..2c95252ac7f6a3e571dcb8cceb03de24dbc2d0c0 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.sal.compatibility;
 
+import java.math.BigInteger;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
@@ -54,10 +55,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 +81,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 +147,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;
 
@@ -348,8 +335,8 @@ public final class NodeMapping {
 
   public static MacAddress toADMacAddress(final NodeId id) {
     final String nodeId = id.getValue().replaceAll("openflow:", "");
-    long lNodeId = Long.parseLong(nodeId);
-    lNodeId = Long.valueOf(lNodeId).longValue();
+    BigInteger nodeIdRaw = new BigInteger(nodeId);
+    long lNodeId = nodeIdRaw.longValue();
     byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId);
     return new MacAddress(bytesFromDpid);
   }
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java
new file mode 100644 (file)
index 0000000..0ddbcaa
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * 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.compatibility;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.NotificationService;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+import com.google.common.base.Preconditions;
+
+class SalCompatibilityProvider implements BindingAwareProvider {
+    private final ComponentActivator activator;
+
+    public SalCompatibilityProvider(final ComponentActivator cmpAct) {
+        this.activator = Preconditions.checkNotNull(cmpAct);
+    }
+
+    @Override
+    public Collection<? extends ProviderFunctionality> getFunctionality() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Collection<? extends RpcService> getImplementations() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void onSessionInitialized(final ConsumerContext session) {
+        // No-op
+    }
+
+    @Override
+    public void onSessionInitiated(final ProviderContext session) {
+        final NotificationService subscribe = session.getSALService(NotificationService.class);
+
+        final FlowProgrammerAdapter flow = activator.getFlow();
+        flow.setDelegate(session.getRpcService(SalFlowService.class));
+        flow.setDataBrokerService(session.getSALService(DataBrokerService.class));
+        // FIXME: remember registration for clean shutdown
+        subscribe.registerNotificationListener(flow);
+
+        final InventoryAndReadAdapter inv = activator.getInventory();
+        inv.setDataService(session.getSALService(DataBrokerService.class));
+        inv.setFlowStatisticsService(session.getRpcService(OpendaylightFlowStatisticsService.class));
+        inv.setFlowTableStatisticsService(session.getRpcService(OpendaylightFlowTableStatisticsService.class));
+        inv.setNodeConnectorStatisticsService(session.getRpcService(OpendaylightPortStatisticsService.class));
+        inv.setTopologyDiscovery(session.getRpcService(FlowTopologyDiscoveryService.class));
+        inv.setDataProviderService(session.getSALService(DataProviderService.class));
+        // FIXME: remember registration for clean shutdown
+        subscribe.registerNotificationListener(inv);
+
+        final DataPacketServiceAdapter dps = activator.getDataPacketService();
+        dps.setDelegate(session.getRpcService(PacketProcessingService.class));
+
+        final TopologyAdapter topo = activator.getTopology();
+        topo.setDataService(session.getSALService(DataProviderService.class));
+
+        final TopologyProvider tpp = activator.getTpProvider();
+        tpp.setDataService(session.getSALService(DataProviderService.class));
+
+        inv.startAdapter();
+        tpp.startAdapter();
+
+        subscribe.registerNotificationListener(activator.getDataPacket());
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyAdapter.java
new file mode 100644 (file)
index 0000000..b609add
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.compatibility.topology;
+
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.topology.IPluginInTopologyService;
+import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public class TopologyAdapter implements IPluginInTopologyService {
+    private final InstanceIdentifier<Topology> topology = InstanceIdentifier.builder(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId("flow:1"))).toInstance();
+
+    // FIXME: seems to be unused
+    private IPluginOutTopologyService topologyPublisher;
+    private DataProviderService dataService;
+
+    public void setDataService(final DataProviderService dataService) {
+        this.dataService = Preconditions.checkNotNull(dataService);
+    }
+
+    @Override
+    public void sollicitRefresh() {
+        final TypeSafeDataReader reader = TypeSafeDataReader.forReader(dataService);
+        final Topology t = reader.readOperationalData(topology);
+        topologyPublisher.edgeUpdate(TopologyMapping.toADEdgeUpdates(t, reader));
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyAdapter.xtend
deleted file mode 100644 (file)
index 4ce57af..0000000
+++ /dev/null
@@ -1,37 +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.compatibility.topology
-
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.topology.IPluginInTopologyService
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-import static extension org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.*
-
-class TopologyAdapter implements IPluginInTopologyService {
-    
-    @Property
-    DataProviderService dataService;
-    
-    @Property
-    IPluginOutTopologyService topologyPublisher;
-    
-    override sollicitRefresh() {
-        val path = InstanceIdentifier.builder(NetworkTopology).child(Topology,new TopologyKey(new TopologyId("flow:1"))).toInstance;
-        val reader = TypeSafeDataReader.forReader(dataService)
-        val topology = reader.readOperationalData(path)
-        topologyPublisher.edgeUpdate(topology.toADEdgeUpdates(reader))
-    }
-    
-}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.java
new file mode 100644 (file)
index 0000000..476a71a
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.compatibility.topology;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Edge;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
+public final class TopologyMapping {
+    private static final Logger LOG = LoggerFactory.getLogger(TopologyMapping.class);
+
+    private TopologyMapping() {
+        throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
+    }
+
+    public static List<TopoEdgeUpdate> toADEdgeUpdates(final Topology topology,final TypeSafeDataReader reader) {
+        final List<TopoEdgeUpdate> result = new CopyOnWriteArrayList<>();
+        return FluentIterable.from(topology.getLink()).transform(
+                new Function<Link, TopoEdgeUpdate>() {
+                    @Override
+                    public TopoEdgeUpdate apply(final Link input) {
+                        try {
+                            return toTopoEdgeUpdate(toAdEdge(input, topology), reader);
+                        } catch (ConstructionException e) {
+                            throw new IllegalArgumentException(String.format("Failed to construct edge update for {}", input), e);
+                        }
+                    }}
+                ).copyInto(result);
+    }
+
+    public static Edge toAdEdge(final Link link, final Topology topology) throws ConstructionException {
+        final NodeConnector adSrc = toADNodeConnector(link.getSource().getSourceTp(), link.getSource().getSourceNode());
+        final NodeConnector adDst = toADNodeConnector(link.getDestination().getDestTp(), link.getDestination().getDestNode());
+        return new Edge(adSrc, adDst);
+    }
+
+    public static TopoEdgeUpdate toTopoEdgeUpdate(final Edge e, final TypeSafeDataReader reader) {
+        return toTopoEdgeUpdate(e, UpdateType.ADDED, reader);
+    }
+
+    public static TopoEdgeUpdate toTopoEdgeUpdate(final Edge e,final UpdateType type,final TypeSafeDataReader reader) {
+        return new TopoEdgeUpdate(e, toAdEdgeProperties(e, reader), type);
+    }
+
+    public static Set<Property> toAdEdgeProperties(final Edge e,final TypeSafeDataReader reader) {
+        final NodeConnectorRef ncref = NodeMapping.toNodeConnectorRef(e.getTailNodeConnector());
+        if(ncref == null) {
+            LOG.debug("Edge {} ncref {}",e,ncref);
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector> ncInstanceId =
+        (InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector>) ncref.getValue();
+        if(ncInstanceId == null) {
+            LOG.debug("Edge {} ncref {}",e,ncref);
+            return null;
+        }
+
+        final  org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc = reader.readOperationalData(ncInstanceId);
+        if(nc == null) {
+            return null;
+        }
+        return NodeMapping.toADNodeConnectorProperties(nc);
+    }
+
+    public static String toADNodeId(final NodeId nodeId) {
+        return nodeId.getValue();
+    }
+
+    public static NodeConnector toADNodeConnector(final TpId source, final NodeId nodeId) throws ConstructionException {
+        checkNotNull(source);
+        return new NodeConnector(NodeMapping.MD_SAL_TYPE, toADNodeConnectorId(source), toADNode(nodeId));
+    }
+
+    public static String toADNodeConnectorId(final TpId nodeConnectorId) {
+        return nodeConnectorId.getValue();
+    }
+
+    public static Node toADNode(final NodeId nodeId) throws ConstructionException {
+        checkNotNull(nodeId);
+        return new Node(NodeMapping.MD_SAL_TYPE, toADNodeId(nodeId));
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.xtend
deleted file mode 100644 (file)
index 9a19e10..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.sal.compatibility.topology
-
-import com.google.common.collect.FluentIterable
-import java.util.Collections
-import java.util.List
-import java.util.concurrent.CopyOnWriteArrayList
-import org.opendaylight.controller.sal.core.ConstructionException
-import org.opendaylight.controller.sal.core.Edge
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.core.NodeConnector
-import org.opendaylight.controller.sal.core.UpdateType
-import org.opendaylight.controller.sal.topology.TopoEdgeUpdate
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link
-
-import static com.google.common.base.Preconditions.*
-import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
-import org.slf4j.LoggerFactory
-
-class TopologyMapping {
-    private static val LOG = LoggerFactory.getLogger(TopologyMapping);
-    private new() {
-        throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
-    }
-    
-    public static def toADEdgeUpdates(Topology topology,TypeSafeDataReader reader) {
-        val List<TopoEdgeUpdate> result = new CopyOnWriteArrayList<TopoEdgeUpdate>()
-        return FluentIterable.from(topology.link).transform[toAdEdge(topology).toTopoEdgeUpdate(reader)].copyInto(result)
-    }
-    
-    public static def toAdEdge(Link link,Topology topology) {
-        val adSrc = link.source.sourceTp.toADNodeConnector(link.source.sourceNode)
-        val adDst = link.destination.destTp.toADNodeConnector(link.destination.destNode)
-        return new Edge(adSrc,adDst); 
-    }
-    
-    public static def toTopoEdgeUpdate(Edge e,TypeSafeDataReader reader) {
-        return toTopoEdgeUpdate(e,UpdateType.ADDED,reader)
-    }
-    
-    public static def toTopoEdgeUpdate(Edge e,UpdateType type,TypeSafeDataReader reader) {
-        return new TopoEdgeUpdate(e,e.toAdEdgeProperties(reader),type)
-    }
-    
-    public static def toAdEdgeProperties(Edge e,TypeSafeDataReader reader) {
-        val ncref = e.tailNodeConnector.toNodeConnectorRef
-        if(ncref == null) {
-            LOG.debug("Edge {} ncref {}",e,ncref)
-            return null;
-        }
-        val ncInstanceId = (ncref.value as InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector>)
-        if(ncInstanceId == null) {
-            LOG.debug("Edge {} ncref {}",e,ncref)
-            return null;
-        }
-        val nc = reader.readOperationalData(ncInstanceId)
-        if(nc == null) {
-            return null;
-        }
-        return nc.toADNodeConnectorProperties     
-    }
-    
-    public static def toADNodeId(NodeId nodeId) {
-        checkNotNull(nodeId);
-        return nodeId.value
-    }
-    public static def toADNodeConnector(TpId source,NodeId nodeId) throws ConstructionException {
-        checkNotNull(source);
-        return new NodeConnector(MD_SAL_TYPE,source.toADNodeConnectorId,nodeId.toADNode)
-    }
-    
-    public static def toADNodeConnectorId(TpId nodeConnectorId) {
-        return nodeConnectorId.value
-    }
-    
-    public static def toADNode(NodeId nodeId) {
-        checkNotNull(nodeId);
-        return new Node(MD_SAL_TYPE,nodeId.toADNodeId);       
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.java
new file mode 100644 (file)
index 0000000..d78bce4
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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.compatibility.topology;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class TopologyProvider implements AutoCloseable{
+    private static final Logger LOG = LoggerFactory.getLogger(TopologyProvider.class);
+    private static final InstanceIdentifier<Link> PATH = InstanceIdentifier.builder(NetworkTopology.class)
+            .child(Topology.class ,new TopologyKey(new TopologyId("flow:1")))
+            .child(Link.class)
+            .toInstance();
+    private TopologyCommitHandler commitHandler;
+
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+    private IPluginOutTopologyService topologyPublisher;
+    private DataProviderService dataService;
+
+    public void startAdapter() {
+        if(dataService == null){
+            LOG.error("dataService not set");
+            return;
+        }
+        commitHandler = new TopologyCommitHandler(dataService,topologyPublisher);
+        listenerRegistration = dataService.registerDataChangeListener(PATH, commitHandler);
+        LOG.info("TopologyProvider started");
+    }
+
+    @Override
+    public void close() {
+        if (listenerRegistration != null) {
+            listenerRegistration.close();
+        }
+    }
+
+    void setTopologyPublisher(final IPluginOutTopologyService topologyPublisher) {
+        this.topologyPublisher = topologyPublisher;
+        if (commitHandler != null) {
+            commitHandler.setTopologyPublisher(topologyPublisher);
+        }
+    }
+
+    public void setDataService(final DataProviderService dataService) {
+        this.dataService = Preconditions.checkNotNull(dataService);
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.xtend
deleted file mode 100644 (file)
index 21f2b35..0000000
+++ /dev/null
@@ -1,64 +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.compatibility.topology
-
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link
-import org.slf4j.LoggerFactory
-import org.opendaylight.yangtools.concepts.ListenerRegistration
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
-
-class TopologyProvider implements AutoCloseable{
-    static val LOG = LoggerFactory.getLogger(TopologyProvider);
-    TopologyCommitHandler commitHandler
-    
-    @Property
-    IPluginOutTopologyService topologyPublisher;
-    
-    @Property
-    DataProviderService dataService;
-    
-    ListenerRegistration<DataChangeListener> listenerRegistration
-    
-    
-    def void start() {
-
-    }
-    def void startAdapter() {
-        if(dataService == null){
-            LOG.error("dataService not set");
-            return;
-        }
-        commitHandler = new TopologyCommitHandler(dataService,topologyPublisher);
-        val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(NetworkTopology)
-            .child(Topology,new TopologyKey(new TopologyId("flow:1")))
-            .child(Link)
-            .toInstance();
-        listenerRegistration = dataService.registerDataChangeListener(path,commitHandler);
-        LOG.info("TopologyProvider started")
-    }
-    
-    override close() throws Exception {
-        listenerRegistration.close
-    }
-    
-    def setTopologyPublisher(IPluginOutTopologyService topologyPublisher) {
-        _topologyPublisher = topologyPublisher;
-        if(commitHandler != null){
-            commitHandler.setTopologyPublisher(topologyPublisher);
-        }
-    }
-    
-}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java
new file mode 100644 (file)
index 0000000..b9a2f5b
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * 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.compatibility.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.controller.sal.core.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * test of {@link NodeMapping} utility class
+ */
+public class NodeMappingTest {
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toADMacAddress(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId)}
+     * .
+     */
+    @Test
+    public void testToADMacAddress() {
+        NodeId[] nodeIds = new NodeId[] {
+                // 0x0000|0000 0000002a (answer to the ultimate question of life, universe and everything)
+                new NodeId("42"),
+                // 0x7fff|ffff ffffffff (max long -> 2**63 - 1)
+                new NodeId("9223372036854775807"),
+                // 0x7fff|7fff ffffffff
+                new NodeId("9223231299366420479"),
+                // 0x8fff|7fff ffffffff (more than biggest positive long)
+                new NodeId("10376152803973267455"),
+                // 0xca13|764a e9ace65a (BUG-770)
+                new NodeId("14561112084339025498")
+        };
+
+        byte[][] expectedMacs = new byte[][] {
+                {0, 0, 0, 0, 0, 0x2a},
+                {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff},
+                {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff},
+                {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff},
+                {(byte) 0x76, (byte) 0x4a, (byte) 0xe9, (byte) 0xac, (byte) 0xe6, (byte) 0x5a}
+        };
+        
+        Assert.assertEquals(expectedMacs.length, nodeIds.length);
+
+        for (int i = 0; i < expectedMacs.length; i++) {
+            NodeId nodeId = nodeIds[i];
+            MacAddress mac = NodeMapping.toADMacAddress(nodeId);
+            Assert.assertArrayEquals(expectedMacs[i], mac.getMacAddress());
+        }
+    }
+
+}
index 63c5664a0c4b2de63e5b6e90279eb59f37e050ef..81ccb35cd982070bc85a7845dfa10d8787f8e450 100644 (file)
@@ -10,8 +10,8 @@ package org.opendaylight.controller.sal.compatibility.test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
 
@@ -19,17 +19,53 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.junit.Test;
-import org.opendaylight.controller.sal.action.*;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.Flood;
+import org.opendaylight.controller.sal.action.FloodAll;
+import org.opendaylight.controller.sal.action.HwPath;
+import org.opendaylight.controller.sal.action.Loopback;
+import org.opendaylight.controller.sal.action.PopVlan;
+import org.opendaylight.controller.sal.action.PushVlan;
+import org.opendaylight.controller.sal.action.SetDlDst;
+import org.opendaylight.controller.sal.action.SetDlSrc;
+import org.opendaylight.controller.sal.action.SetDlType;
+import org.opendaylight.controller.sal.action.SetNextHop;
+import org.opendaylight.controller.sal.action.SetNwDst;
+import org.opendaylight.controller.sal.action.SetNwSrc;
+import org.opendaylight.controller.sal.action.SetNwTos;
+import org.opendaylight.controller.sal.action.SetTpDst;
+import org.opendaylight.controller.sal.action.SetTpSrc;
+import org.opendaylight.controller.sal.action.SetVlanCfi;
+import org.opendaylight.controller.sal.action.SetVlanId;
+import org.opendaylight.controller.sal.action.SetVlanPcp;
+import org.opendaylight.controller.sal.action.SwPath;
 import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
 import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
@@ -140,7 +176,7 @@ public class TestFromSalConversionsUtils {
             if (layer4Match instanceof SctpMatch) {
                 assertEquals("Sctp source port is incorrect.", 0xffff, (int) ((SctpMatch) layer4Match)
                         .getSctpSourcePort().getValue());
-                assertEquals("Sctp dest port is incorrect.", (int) 0xfffe, (int) ((SctpMatch) layer4Match)
+                assertEquals("Sctp dest port is incorrect.", 0xfffe, (int) ((SctpMatch) layer4Match)
                         .getSctpDestinationPort().getValue());
                 sctpFound = true;
             }
@@ -151,9 +187,9 @@ public class TestFromSalConversionsUtils {
             assertEquals("Wrong protocol", TCP, match.getIpMatch().getIpProtocol().byteValue());
             layer4Match = match.getLayer4Match();
             if (layer4Match instanceof TcpMatch) {
-                assertEquals("Tcp source port is incorrect.", (int) 0xabcd, (int) ((TcpMatch) layer4Match)
+                assertEquals("Tcp source port is incorrect.", 0xabcd, (int) ((TcpMatch) layer4Match)
                         .getTcpSourcePort().getValue());
-                assertEquals("Tcp dest port is incorrect.", (int) 0xdcba, (int) ((TcpMatch) layer4Match)
+                assertEquals("Tcp dest port is incorrect.", 0xdcba, (int) ((TcpMatch) layer4Match)
                         .getTcpDestinationPort().getValue());
                 sctpFound = true;
             }
@@ -164,9 +200,9 @@ public class TestFromSalConversionsUtils {
             assertEquals("Wrong protocol", UDP, match.getIpMatch().getIpProtocol().byteValue());
             layer4Match = match.getLayer4Match();
             if (layer4Match instanceof UdpMatch) {
-                assertEquals("Udp source port is incorrect.", (int) 0xcdef, (int) ((UdpMatch) layer4Match)
+                assertEquals("Udp source port is incorrect.", 0xcdef, (int) ((UdpMatch) layer4Match)
                         .getUdpSourcePort().getValue());
-                assertEquals("Udp dest port is incorrect.", (int) 0xfedc, (int) ((UdpMatch) layer4Match)
+                assertEquals("Udp dest port is incorrect.", 0xfedc, (int) ((UdpMatch) layer4Match)
                         .getUdpDestinationPort().getValue());
                 sctpFound = true;
             }
@@ -227,13 +263,13 @@ public class TestFromSalConversionsUtils {
                     assertEquals("Wrong value of vlad ID in PushVlanAction.", (Integer) 4095,
                             ((PushVlanActionCase) innerAction).getPushVlanAction().getVlanId().getValue());
                 } else if (innerAction instanceof SetDlDstActionCase) {
-                    assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa", 
+                    assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
                             ((SetDlDstActionCase) innerAction).getSetDlDstAction().getAddress().getValue());
                 } else if (innerAction instanceof SetDlSrcActionCase) {
-                    assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa", 
+                    assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
                             ((SetDlSrcActionCase) innerAction).getSetDlSrcAction().getAddress().getValue());
                 } else if (innerAction instanceof SetDlTypeActionCase) {
-                    assertEquals("Wrong data link type in SetDlTypeAction.", (long) 513,
+                    assertEquals("Wrong data link type in SetDlTypeAction.", 513,
                             (long) ((SetDlTypeActionCase) innerAction).getSetDlTypeAction().getDlType().getValue());
                 } else if (innerAction instanceof SetNextHopActionCase) {
                     Address address = ((SetNextHopActionCase) innerAction).getSetNextHopAction().getAddress();
index 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 750defc0e95ac17ad535b299bfad52e4c4a489f2..0f0ce0dc9dd24fb41bc54bde70c196ba2d4d511e 100644 (file)
@@ -26,6 +26,8 @@ import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -36,6 +38,8 @@ import com.google.common.base.Preconditions;
 public final class RuntimeMappingModule extends
         org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractRuntimeMappingModule {
 
+    private static final Logger LOG = LoggerFactory.getLogger(RuntimeMappingModule.class);
+
     private BundleContext bundleContext;
 
     public RuntimeMappingModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
@@ -163,10 +167,17 @@ public final class RuntimeMappingModule extends
         }
 
         @Override
-        public void close() throws Exception {
+        public void close() {
             if(delegate != null) {
                 delegate = null;
-                bundleContext.ungetService(reference);
+
+                try {
+                    bundleContext.ungetService(reference);
+                } catch (IllegalStateException e) {
+                    // Indicates the BundleContext is no longer valid which can happen normally on shutdown.
+                    LOG.debug( "Error unregistering service", e );
+                }
+
                 bundleContext= null;
                 reference = null;
             }
index 846f949375dabc21a112e0dc9c1268e6b04148c4..f1be5c6922ecda45cc75f343b3f6355e402e013d 100644 (file)
@@ -13,18 +13,17 @@ import java.util.AbstractMap.SimpleEntry;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
-import java.util.concurrent.Callable;
 
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
@@ -44,6 +43,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
@@ -149,23 +149,38 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         // 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());
             try {
-                if (!isNotRepresentable(childPath)) {
-                    InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(toBindingImpl(
-                            childPath).get());
-                    int potentialAugmentCount = getAugmentationCount(potentialPath);
-                    if(potentialAugmentCount == normalizedCount) {
-                        return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
-                    }
+                if (isNotRepresentable(childPath)) {
+                    LOG.trace("Path {} is not BI-representable, skipping it", childPath);
+                    continue;
                 }
-            } catch (Exception e) {
-                LOG.trace("Unable to deserialize aug. child path for {}", childPath, e);
+            } catch (DataNormalizationException e) {
+                LOG.warn("Failed to denormalize path {}, skipping it", childPath, e);
+                continue;
+            }
+
+            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);
         }
+
+        LOG.trace("Failed to find augmentation matching {}", normalized);
         return Optional.absent();
     }
 
@@ -349,11 +364,9 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         } else if (List.class.isAssignableFrom(returnType)) {
             try {
                 return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
-                        new Callable<Class>() {
-
-                            @SuppressWarnings("rawtypes")
+                        new Supplier<Class>() {
                             @Override
-                            public Class call() throws Exception {
+                            public Class get() {
                                 Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
                                         .getGenericReturnType());
                                 if (listResult instanceof Class
index ddc79ae075e7551cfd369a81795da0f040b427e6..e08e9a4e0580556d038cbe01e6de2dc0ed064735 100644 (file)
@@ -443,9 +443,6 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
     }
 
     private static class BackwardsCompatibleConfigurationDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
-
-
-        @SuppressWarnings("rawtypes")
         private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
 
         public BackwardsCompatibleConfigurationDataChangeInvoker(final DataChangeListener listener) {
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.java
new file mode 100644 (file)
index 0000000..22b6f6f
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * 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.codegen;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public final class RuntimeCodeSpecification {
+    public final static String DIRECT_PROXY_SUFFIX = "DirectProxy";
+    public final static String INVOKER_SUFFIX = "ListenerInvoker";
+    public final static String ROUTER_SUFFIX = "Router";
+
+    public final static String DELEGATE_FIELD = "_delegate";
+    public final static String ROUTING_TABLE_FIELD_PREFIX = "_routes_";
+
+    private RuntimeCodeSpecification() {
+        throw new UnsupportedOperationException("Utility class");
+    }
+
+    /**
+     * Returns a name for generated interface
+     */
+    private static String getGeneratedName(final Class<? extends Object> cls, final String suffix) {
+        return cls.getName() + "$$Broker$" + suffix;
+    }
+
+    public static String getInvokerName(final Class<? extends NotificationListener> listener) {
+        return getGeneratedName(listener, RuntimeCodeSpecification.INVOKER_SUFFIX);
+    }
+
+    /**
+     * Returns a name for DirectProxy implementation
+     */
+    public static String getDirectProxyName(final Class<? extends RpcService> base) {
+        return getGeneratedName(base, RuntimeCodeSpecification.DIRECT_PROXY_SUFFIX);
+    }
+
+    /**
+     * Returns a name for Router implementation
+     */
+    public static String getRouterName(final Class<? extends RpcService> base) {
+        return getGeneratedName(base, RuntimeCodeSpecification.ROUTER_SUFFIX);
+    }
+
+    /**
+     * Returns a field name for specified routing context
+     */
+    public static String getRoutingTableField(final Class<? extends BaseIdentity> routingContext) {
+        return "_routes_" + routingContext.getSimpleName();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend
deleted file mode 100644 (file)
index c5648ad..0000000
+++ /dev/null
@@ -1,65 +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.codegen
-
-import org.opendaylight.yangtools.yang.binding.RpcService
-import org.opendaylight.yangtools.yang.binding.BaseIdentity
-import org.opendaylight.yangtools.yang.binding.NotificationListener
-
-/**
- * 
- * 
- */
-class RuntimeCodeSpecification {
-
-    //public static val PACKAGE_PREFIX = "_gen.";
-
-    public static val DIRECT_PROXY_SUFFIX = "DirectProxy";
-    public static val ROUTER_SUFFIX = "Router";
-    public static val INVOKER_SUFFIX = "ListenerInvoker";
-
-    public static val DELEGATE_FIELD = "_delegate"
-    public static val ROUTING_TABLE_FIELD_PREFIX = "_routes_"
-
-    public static def getInvokerName(Class<? extends NotificationListener> listener) {
-        getGeneratedName(listener, INVOKER_SUFFIX);
-    }
-
-    /**
-     * Returns a name for DirectProxy implementation
-     * 
-     * 
-     */
-    public static def getDirectProxyName(Class<? extends RpcService> base) {
-        getGeneratedName(base, DIRECT_PROXY_SUFFIX);
-    }
-
-    /**
-     * Returns a name for Router implementation
-     * 
-     */
-    public static def getRouterName(Class<? extends RpcService> base) {
-        getGeneratedName(base, ROUTER_SUFFIX);
-    }
-
-    /**
-     * Returns a name for generated interface
-     * 
-     */
-    public static def getGeneratedName(Class<?> cls, String suffix) {
-        '''«cls.name»$$Broker$«suffix»'''.toString()
-    }
-
-    /**
-     * Returns a field name for specified routing context
-     * 
-     */
-    public static def getRoutingTableField(Class<? extends BaseIdentity> routingContext) {
-        return '''_routes_«routingContext.simpleName»'''.toString;
-    }
-}
index 0bc11d9b3547298d321dee112014963f3ff676d2..4ad0bb0558a37bcdd6827fdb0a63c1d047553bba 100644 (file)
@@ -5,18 +5,19 @@
  * 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.codegen;
 
 import java.lang.reflect.Method;
+
 import org.opendaylight.yangtools.yang.binding.Notification;
 
-@SuppressWarnings("all")
-public class YangtoolsMappingHelper {
-  public static boolean isNotificationCallback(final Method it) {
-      return it.getName().startsWith("on") && (it.getParameterTypes().length == 1) &&
-              Notification.class.isAssignableFrom(it.getParameterTypes()[0]);
-  }
+public final class YangtoolsMappingHelper {
+    private YangtoolsMappingHelper() {
+        throw new UnsupportedOperationException("Utility class");
+    }
 
+    public static boolean isNotificationCallback(final Method it) {
+        return it.getName().startsWith("on") && (it.getParameterTypes().length == 1) &&
+                Notification.class.isAssignableFrom(it.getParameterTypes()[0]);
+    }
 }
\ No newline at end of file
index b27c80d784e39fce232ae227a752f3dd3b77ab99..5bbebe6f1b00544021bb64d5cdf0ea4bf77c82a5 100644 (file)
@@ -62,7 +62,6 @@ import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
 import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
@@ -73,12 +72,11 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.slf4j.Logger;
@@ -87,7 +85,6 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.common.util.concurrent.Futures;
@@ -736,224 +733,13 @@ public class BindingIndependentConnector implements //
                         }
                     }
                     checkState(targetMethod != null, "Rpc method not found");
-                    Optional<Class<?>> outputClass = BindingReflections.resolveRpcOutputClass(targetMethod);
-                    Optional<Class<? extends DataContainer>> inputClass = BindingReflections
-                            .resolveRpcInputClass(targetMethod);
-
-                    RpcInvocationStrategy strategy = null;
-                    if (outputClass.isPresent()) {
-                        if (inputClass.isPresent()) {
-                            strategy = new DefaultInvocationStrategy(rpc, targetMethod, outputClass.get(), inputClass
-                                    .get());
-                        } else {
-                            strategy = new NoInputInvocationStrategy(rpc, targetMethod, outputClass.get());
-                        }
-                    } else if (inputClass.isPresent()) {
-                        strategy = new NoOutputInvocationStrategy(rpc, targetMethod, inputClass.get());
-                    } else {
-                        strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod);
-                    }
-                    return strategy;
+                    return  new RpcInvocationStrategy(rpc,targetMethod, mappingService, biRpcRegistry);
                 }
 
             });
         }
     }
 
-    private abstract class RpcInvocationStrategy {
-
-        protected final Method targetMethod;
-        protected final QName rpc;
-
-        public RpcInvocationStrategy(final QName rpc, final Method targetMethod) {
-            this.targetMethod = targetMethod;
-            this.rpc = rpc;
-        }
-
-        public abstract Future<RpcResult<?>> forwardToDomBroker(DataObject input);
-
-        public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
-                throws Exception;
-
-        public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            return uncheckedInvoke(rpcService, domInput);
-        }
-    }
-
-    private class DefaultInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> inputClass;
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> outputClass;
-
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public DefaultInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass,
-                final Class<? extends DataContainer> inputClass) {
-            super(rpc, targetMethod);
-            this.outputClass = new WeakReference(outputClass);
-            this.inputClass = new WeakReference(inputClass);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
-            Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
-            if (futureResult == null) {
-                return Rpcs.getRpcResult(false);
-            }
-            RpcResult<?> bindingResult = futureResult.get();
-            final Object resultObj = bindingResult.getResult();
-            if (resultObj instanceof DataObject) {
-                final CompositeNode output = mappingService.toDataDom((DataObject) resultObj);
-                return Rpcs.getRpcResult(true, output, Collections.<RpcError> emptySet());
-            }
-            return Rpcs.getRpcResult(true);
-        }
-
-        @Override
-        public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if (biRpcRegistry == null) {
-                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
-            }
-
-            CompositeNode xml = mappingService.toDataDom(input);
-            CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-
-            return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
-                    new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
-                        @Override
-                        public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
-                            Object baResultValue = null;
-                            if (input.getResult() != null) {
-                                baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(),
-                                        input.getResult());
-                            }
-                            return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors());
-                        }
-                    });
-        }
-    }
-
-    private class NoInputInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> outputClass;
-
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public NoInputInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass) {
-            super(rpc, targetMethod);
-            this.outputClass = new WeakReference(outputClass);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
-            if (futureResult == null) {
-                return Rpcs.getRpcResult(false);
-            }
-            RpcResult<?> bindingResult = futureResult.get();
-            final Object resultObj = bindingResult.getResult();
-            if (resultObj instanceof DataObject) {
-                final CompositeNode output = mappingService.toDataDom((DataObject) resultObj);
-                return Rpcs.getRpcResult(true, output, Collections.<RpcError> emptySet());
-            }
-            return Rpcs.getRpcResult(true);
-        }
-
-        @Override
-        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if (biRpcRegistry != null) {
-                CompositeNode xml = mappingService.toDataDom(input);
-                CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-                return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
-                        new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
-                            @Override
-                            public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
-                                Object baResultValue = null;
-                                if (input.getResult() != null) {
-                                    baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(),
-                                            input.getResult());
-                                }
-                                return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors());
-                            }
-                        });
-            } else {
-                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
-            }
-        }
-    }
-
-    private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
-
-        public NoInputNoOutputInvocationStrategy(final QName rpc, final Method targetMethod) {
-            super(rpc, targetMethod);
-        }
-
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            @SuppressWarnings("unchecked")
-            Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
-            RpcResult<Void> bindingResult = result.get();
-            return Rpcs.getRpcResult(bindingResult.isSuccessful(), bindingResult.getErrors());
-        }
-
-        @Override
-        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            return Futures.immediateFuture(null);
-        }
-    }
-
-    private class NoOutputInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private final WeakReference<Class> inputClass;
-
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public NoOutputInvocationStrategy(final QName rpc, final Method targetMethod,
-                final Class<? extends DataContainer> inputClass) {
-            super(rpc, targetMethod);
-            this.inputClass = new WeakReference(inputClass);
-        }
-
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
-                throws Exception {
-            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
-            Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
-            if (result == null) {
-                return Rpcs.getRpcResult(false);
-            }
-            RpcResult<?> bindingResult = result.get();
-            return Rpcs.getRpcResult(true);
-        }
-
-        @Override
-        public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if (biRpcRegistry == null) {
-                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
-            }
-
-            CompositeNode xml = mappingService.toDataDom(input);
-            CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-
-            return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
-                    new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
-                        @Override
-                        public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
-                            return Rpcs.<Void> getRpcResult(input.isSuccessful(), null, input.getErrors());
-                        }
-                    });
-        }
-    }
-
     public boolean isRpcForwarding() {
         return rpcForwarding;
     }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategy.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategy.java
new file mode 100644 (file)
index 0000000..d08b217
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ ** Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ **
+ ** This program and the accompanying materials are made available under the
+ ** terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ** and is available at http://www.eclipse.org/legal/epl-v10.html
+ **/
+
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/*
+ * RPC's can have both input, output, one or the other, or neither.
+ *
+ * This class handles the permutations and provides two means of invocation:
+ * 1. forwardToDomBroker
+ * 2.
+ *
+ * Weak References to the input and output classes are used to allow these classes to
+ * be from another OSGi bundle/class loader which may come and go.
+ *
+ */
+public class RpcInvocationStrategy {
+
+    private final BindingIndependentMappingService mappingService;
+    private final RpcProvisionRegistry biRpcRegistry;
+    protected final Method targetMethod;
+    protected final QName rpc;
+
+    @SuppressWarnings("rawtypes")
+    private final WeakReference<Class> inputClass;
+
+    @SuppressWarnings("rawtypes")
+    private final WeakReference<Class> outputClass;
+
+    @SuppressWarnings({ "rawtypes" })
+    public RpcInvocationStrategy(final QName rpc,
+                                 final Method targetMethod,
+                                 final BindingIndependentMappingService mappingService,
+                                 final RpcProvisionRegistry biRpcRegistry ) {
+
+        this.targetMethod = targetMethod;
+        this.rpc = rpc;
+
+        Optional<Class<?>> outputClassOption = BindingReflections.resolveRpcOutputClass(targetMethod);
+        Optional<Class<? extends DataContainer>> inputClassOption = BindingReflections.resolveRpcInputClass(targetMethod);
+
+        if ( outputClassOption != null && outputClassOption.isPresent() ) {
+            this.outputClass = new WeakReference(outputClassOption.get() ) ;
+        } else {
+            this.outputClass = null ;
+        }
+        if ( inputClassOption != null && inputClassOption.isPresent() ) {
+            this.inputClass = new WeakReference(inputClassOption.get() ) ;
+        } else {
+            this.inputClass = null ;
+        }
+
+        this.mappingService = mappingService;
+        this.biRpcRegistry = biRpcRegistry;
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
+
+        if(biRpcRegistry == null) {
+            return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
+        }
+
+        CompositeNode inputXml = null;
+        if( input != null ) {
+            CompositeNode xml = mappingService.toDataDom(input);
+            inputXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
+        } else {
+            inputXml = ImmutableCompositeNode.create( rpc, Collections.<Node<?>>emptyList() );
+        }
+
+        Function<RpcResult<CompositeNode>, RpcResult<?>> transformationFunction =
+                                       new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
+            @Override
+            public RpcResult<?> apply(RpcResult<CompositeNode> result) {
+
+                Object output = null;
+
+                if( getOutputClass() != null ) {
+                    if (result.getResult() != null) {
+                        output = mappingService.dataObjectFromDataDom(getOutputClass().get(),
+                                                                    result.getResult());
+                    }
+                }
+
+                return Rpcs.getRpcResult(result.isSuccessful(), output, result.getErrors());
+            }
+        };
+
+        return Futures.transform(biRpcRegistry.invokeRpc(rpc, inputXml), transformationFunction);
+    }
+
+    @SuppressWarnings("unchecked")
+    private RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+
+        Future<RpcResult<?>> futureResult = null;
+
+        if( inputClass != null ){
+            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
+            futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
+
+        } else {
+            futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
+        }
+
+        if (futureResult == null) {
+            return Rpcs.getRpcResult(false);
+        }
+
+        RpcResult<?> bindingResult = futureResult.get();
+
+        Collection<RpcError> errors = bindingResult.getErrors();
+        if( errors == null ) {
+            errors = Collections.<RpcError>emptySet();
+        }
+
+        final Object resultObj = bindingResult.getResult();
+        CompositeNode output = null;
+        if (resultObj instanceof DataObject) {
+            output = mappingService.toDataDom((DataObject)resultObj);
+        }
+        return Rpcs.getRpcResult( bindingResult.isSuccessful(), output, errors);
+    }
+
+    public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+        return uncheckedInvoke(rpcService, domInput);
+    }
+
+    @SuppressWarnings("rawtypes")
+    public WeakReference<Class> getOutputClass() {
+        return outputClass;
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategyTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/impl/connect/dom/RpcInvocationStrategyTest.java
new file mode 100644 (file)
index 0000000..c5aea8f
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class RpcInvocationStrategyTest {
+
+    @Mock
+    private BindingIndependentMappingService mockMappingService;
+    @Mock
+    private RpcProvisionRegistry mockbiRpcRegistry;
+
+    private RpcInvocationStrategy rpcInvocationStrategy;
+    private ListenableFuture<RpcResult<DataObject>> futureDataObj;
+    private ListenableFuture<RpcResult<CompositeNode>> futureCompNode;
+    private final RpcError rpcError = mock(RpcError.class);
+    private final Collection<RpcError> errors = new ArrayList<RpcError>();
+
+    private final CompositeNode inputInvokeOn = mock(CompositeNode.class);
+    private final CompositeNode outputInvokeOn = mock(CompositeNode.class);
+
+    private final DataObject toDataDomInput = mock(DataObject.class);
+    private final CompositeNode toDataDomReturn = mock(CompositeNode.class);
+    private final CompositeNode invokeRpcResult = mock(CompositeNode.class);
+
+    private final DataObject inputForward = mock(DataObject.class);
+    private final DataObject outputForward = mock(DataObject.class);
+
+    private QName mockQName;
+    private URI urn;
+
+    private final MockRpcService mockRpcService = new MockRpcService();
+
+    public class MockRpcService implements RpcService {
+
+        public Future<?> rpcnameWithInputNoOutput(DataObject input) {
+            return futureDataObj;
+        }
+
+        public Future<RpcResult<DataObject>> rpcnameWithInputWithOutput(DataObject input) {
+            return futureDataObj;
+        }
+
+        public Future<RpcResult<DataObject>> rpcnameNoInputWithOutput() {
+            return futureDataObj;
+        }
+
+        public Future<?> rpcnameNoInputNoOutput() {
+            return futureDataObj;
+        }
+    }
+
+    public RpcInvocationStrategyTest() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Before
+    public void testInit() throws Exception {
+        urn = new URI(new String("urn:a:valid:urn"));
+    }
+
+    private void setupForForwardToDom(boolean hasOutput, boolean hasInput, int expectedErrorSize) {
+
+        if (expectedErrorSize > 0)
+            errors.add(rpcError);
+        RpcResult<CompositeNode> result = Rpcs.getRpcResult(true, invokeRpcResult, errors);
+        futureCompNode = Futures.immediateFuture(result);
+        if( hasInput )
+        {
+            when(mockMappingService.toDataDom(inputForward)).thenReturn(toDataDomReturn);
+        }
+        when(mockbiRpcRegistry.invokeRpc(eq(mockQName), any(CompositeNode.class))).thenReturn(
+                futureCompNode);
+        if (hasOutput) {
+            when(
+                    mockMappingService.dataObjectFromDataDom(eq(rpcInvocationStrategy
+                            .getOutputClass().get()), any(CompositeNode.class))).thenReturn(
+                    outputForward);
+        }
+
+    }
+
+    private void validateForwardToDomBroker(ListenableFuture<RpcResult<?>> forwardToDomBroker,
+            boolean expectedSuccess, DataObject expectedResult, int expectedErrorSize)
+            throws InterruptedException, ExecutionException {
+        assertNotNull(forwardToDomBroker);
+        assertEquals(expectedSuccess, forwardToDomBroker.get().isSuccessful());
+        assertEquals(expectedResult, forwardToDomBroker.get().getResult());
+        assertEquals(expectedErrorSize, forwardToDomBroker.get().getErrors().size());
+    }
+
+    private void setupTestMethod(String rpcName, String testMethodName, boolean hasInput)
+            throws NoSuchMethodException {
+        mockQName = new QName(urn, new Date(0L), new String("prefix"), new String(rpcName));
+        java.lang.reflect.Method rpcMethod = hasInput ? MockRpcService.class.getMethod(rpcName,
+                DataObject.class) : MockRpcService.class.getMethod(rpcName);
+        rpcInvocationStrategy = new RpcInvocationStrategy(mockQName, rpcMethod, mockMappingService,
+                mockbiRpcRegistry);
+    }
+
+    /*
+     * forwardToDomBroker tests
+     */
+    @Test
+    public void testForwardToDomBroker_WithInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputNoOutput", "testForwardToDomBroker_WithInputNoOutput",
+                true);
+        setupForForwardToDom(false, true, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(inputForward);
+
+        validateForwardToDomBroker(forwardToDomBroker, true, null, 0);
+    }
+
+    @Test
+    public void testForwardToDomBroker_WithInputNoOutput_error() throws Exception {
+        setupTestMethod("rpcnameWithInputNoOutput",
+                "testForwardToDomBroker_WithInputNoOutput_error", true);
+        setupForForwardToDom(false, true, 1);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(inputForward);
+
+        validateForwardToDomBroker(forwardToDomBroker, true, null, 1);
+    }
+
+    @Test
+    public void testForwardToDomBroker_WithInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputWithOutput", "testForwardToDomBroker_WithInputWithOutput",
+                true);
+        setupForForwardToDom(true, true, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(inputForward);
+        validateForwardToDomBroker(forwardToDomBroker, true, outputForward, 0);
+    }
+
+    @Test
+    public void testForwardToDomBroker_NoInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputWithOutput", "testForwardToDomBroker_NoInputWithOutput",
+                false);
+        setupForForwardToDom(true, false, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(null);
+        validateForwardToDomBroker(forwardToDomBroker, true, outputForward, 0);
+    }
+
+    @Test
+    public void testForwardToDomBroker_NoInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputNoOutput", "testForwardToDomBroker_NoInputNoOutput", false);
+        setupForForwardToDom(false, false, 0);
+        ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+                .forwardToDomBroker(null);
+        validateForwardToDomBroker(forwardToDomBroker, true, null, 0);
+    }
+
+    /*
+     * invokeOn Tests
+     */
+    private void setupRpcResultsWithOutput(int expectedErrorSize) {
+        if (expectedErrorSize > 0)
+            errors.add(rpcError);
+        RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+        futureCompNode = Futures.immediateFuture(resultCompNode);
+        RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, toDataDomInput, errors);
+        futureDataObj = Futures.immediateFuture(resultDataObj);
+
+        when(mockMappingService.toDataDom(toDataDomInput)).thenReturn(outputInvokeOn);
+    }
+
+    private void setupRpcResultsNoOutput(int expectedErrorSize) {
+        if (expectedErrorSize > 0)
+            errors.add(rpcError);
+        RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+        futureCompNode = Futures.immediateFuture(resultCompNode);
+        RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, null, errors);
+        futureDataObj = Futures.immediateFuture(resultDataObj);
+    }
+
+    private void validateReturnedImmediateFuture(
+            ListenableFuture<RpcResult<CompositeNode>> immediateFuture, boolean expectedSuccess,
+            CompositeNode expectedReturn, int expectedErrorSize) throws InterruptedException,
+            ExecutionException {
+        assertNotNull(immediateFuture);
+        assertEquals(expectedSuccess, immediateFuture.get().isSuccessful());
+        assertEquals(expectedReturn, immediateFuture.get().getResult());
+        assertEquals(expectedErrorSize, immediateFuture.get().getErrors().size());
+    }
+
+    @Test
+    public void testInvokeOn_NoInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputNoOutput", "testInvokeOn_NoInputNoOutput", false);
+        setupRpcResultsNoOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, null, 0);
+    }
+
+    @Test
+    public void testInvokeOn_NoInputNoOutput_errors() throws Exception {
+        setupTestMethod("rpcnameNoInputNoOutput", "testInvokeOn_NoInputNoOutput", false);
+        setupRpcResultsNoOutput(1);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, null, 1);
+    }
+
+    @Test
+    public void testInvokeOn_WithInputNoOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputNoOutput", "testInvokeOn_WithInputNoOutput", true);
+        setupRpcResultsNoOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, null, 0);
+    }
+
+    @Test
+    public void testInvokeOn_WithInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameWithInputWithOutput", "testInvokeOn_WithInputWithOutput", true);
+        setupRpcResultsWithOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, outputInvokeOn, 0);
+    }
+
+    @Test
+    public void testInvokeOn_NoInputWithOutput() throws Exception {
+        setupTestMethod("rpcnameNoInputWithOutput", "testInvokeOn_NoInputWithOutput", false);
+        setupRpcResultsWithOutput(0);
+        ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+                .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+        validateReturnedImmediateFuture(immediateFuture, true, outputInvokeOn, 0);
+    }
+}
@@ -48,7 +48,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-public class MultipleAugmentationPuts extends AbstractDataServiceTest implements DataChangeListener {
+public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implements DataChangeListener {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
     private static final String NODE_ID = "openflow:1";
@@ -76,7 +76,7 @@ public class MultipleAugmentationPuts extends AbstractDataServiceTest implements
      *
      * @throws Exception
      */
-    @Test
+    @Test( timeout = 15000)
     public void testAugmentSerialization() throws Exception {
 
         baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
index 734733a19cdde4179a776a3c20c181dc0b3ea6f3..57b4960145b7560c3e19e7dae0d8e2e578e8b43d 100644 (file)
@@ -7,15 +7,15 @@
  */
 package org.opendaylight.controller.test.sal.binding.it;
 
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.options.DefaultCompositeOption;
-import org.ops4j.pax.exam.util.PathUtils;
-
 import static org.ops4j.pax.exam.CoreOptions.frameworkProperty;
 import static org.ops4j.pax.exam.CoreOptions.junitBundles;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
 
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.util.PathUtils;
+
 public class TestHelper {
 
     public static final String CONTROLLER = "org.opendaylight.controller";
@@ -68,6 +68,7 @@ public class TestHelper {
 
                 mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "netconf-util").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "netconf-netty-util").versionAsInProject(), //
                 mavenBundle("org.openexi", "nagasena").versionAsInProject(), //
                 mavenBundle("org.openexi", "nagasena-rta").versionAsInProject(), //
                 mavenBundle(CONTROLLER + ".thirdparty", "ganymed").versionAsInProject(), //
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 f869254dcf1efa2832f792005c7f22f02d9be033..a7c6b0c66fe4e688a9d868a89b7c761e64c962fc 100644 (file)
@@ -285,7 +285,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             ImmutableMap.Builder<QName, Object> keys = ImmutableMap.builder();
             for (QName key : keyDefinition) {
 
@@ -325,7 +325,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -343,7 +343,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -377,7 +377,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -397,7 +397,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
         }
 
@@ -602,7 +602,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+        protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
             return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
         }
 
index 33a9869a6b8d9f74605ef1362432cb4f9026f269..f30c8ddcaabf5c8c7cff69744b9ee3e8f936ebf8 100644 (file)
@@ -92,11 +92,11 @@ public class DataNormalizer {
         }
 
         // Write Augmentation data resolution
-        if (legacyData.getChildren().size() == 1) {
+        if (legacyData.getValue().size() == 1) {
             final DataNormalizationOperation<?> potentialOp;
 
             try {
-                final QName childType = legacyData.getChildren().get(0).getNodeType();
+                final QName childType = legacyData.getValue().get(0).getNodeType();
                 potentialOp = currentOp.getChild(childType);
             } catch (DataNormalizationException e) {
                 throw new IllegalArgumentException(String.format("Failed to get child operation for %s", legacyData), e);
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 162b66bda18c6bb6252c73d5046997ba750f2996..f73ee5c285100511562c810a7d5897923e867b68 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.eclipse.xtend</groupId>
-      <artifactId>org.eclipse.xtend.lib</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-api</artifactId>
           </instructions>
         </configuration>
       </plugin>
-      <plugin>
-        <groupId>org.eclipse.xtend</groupId>
-        <artifactId>xtend-maven-plugin</artifactId>
-      </plugin>
       <!-- TODO - unite yang-maven-plugin configuration in md-sal-->
       <plugin>
         <groupId>org.opendaylight.yangtools</groupId>
index ba7414d42e26cbac61eb97a836cf89343f461969..fd24944018c69b3b9480a7018e0fea1c23986719 100644 (file)
@@ -16,28 +16,29 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-/**
-*
-*/
 public final class SchemaServiceImplSingletonModule extends
-        org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImplSingletonModule {
+org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImplSingletonModule {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SchemaServiceImplSingletonModule.class);
 
     BundleContext bundleContext;
 
-    public SchemaServiceImplSingletonModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    public SchemaServiceImplSingletonModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public SchemaServiceImplSingletonModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
-            SchemaServiceImplSingletonModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public SchemaServiceImplSingletonModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            final SchemaServiceImplSingletonModule oldModule, final java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
     @Override
-    public boolean canReuseInstance(AbstractSchemaServiceImplSingletonModule oldModule) {
+    public boolean canReuseInstance(final AbstractSchemaServiceImplSingletonModule oldModule) {
         return true;
     }
 
@@ -45,7 +46,7 @@ public final class SchemaServiceImplSingletonModule extends
         return bundleContext;
     }
 
-    public void setBundleContext(BundleContext bundleContext) {
+    public void setBundleContext(final BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
 
@@ -61,8 +62,7 @@ public final class SchemaServiceImplSingletonModule extends
             return new GlobalSchemaServiceProxy(getBundleContext(), ref);
         }
 
-        GlobalBundleScanningSchemaServiceImpl newInstance = new GlobalBundleScanningSchemaServiceImpl();
-        newInstance.setContext(getBundleContext());
+        GlobalBundleScanningSchemaServiceImpl newInstance = new GlobalBundleScanningSchemaServiceImpl(getBundleContext());
         newInstance.start();
         return newInstance;
     }
@@ -73,7 +73,7 @@ public final class SchemaServiceImplSingletonModule extends
         private ServiceReference<SchemaService> reference;
         private SchemaService delegate;
 
-        public GlobalSchemaServiceProxy(BundleContext bundleContext, ServiceReference<SchemaService> ref) {
+        public GlobalSchemaServiceProxy(final BundleContext bundleContext, final ServiceReference<SchemaService> ref) {
             this.bundleContext = bundleContext;
             this.reference = ref;
             this.delegate = bundleContext.getService(reference);
@@ -83,29 +83,42 @@ public final class SchemaServiceImplSingletonModule extends
         public void close() throws Exception {
             if (delegate != null) {
                 delegate = null;
-                bundleContext.ungetService(reference);
+
+                try {
+                    bundleContext.ungetService(reference);
+                } catch (IllegalStateException e) {
+                    // Indicates the service was already unregistered which can happen normally
+                    // on shutdown.
+                    LOG.debug( "Error unregistering service", e );
+                }
+
                 reference = null;
                 bundleContext = null;
             }
         }
 
-        public void addModule(Module arg0) {
+        @Override
+        public void addModule(final Module arg0) {
             delegate.addModule(arg0);
         }
 
+        @Override
         public SchemaContext getGlobalContext() {
             return delegate.getGlobalContext();
         }
 
+        @Override
         public SchemaContext getSessionContext() {
             return delegate.getSessionContext();
         }
 
-        public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener arg0) {
+        @Override
+        public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(final SchemaServiceListener arg0) {
             return delegate.registerSchemaServiceListener(arg0);
         }
 
-        public void removeModule(Module arg0) {
+        @Override
+        public void removeModule(final Module arg0) {
             delegate.removeModule(arg0);
         }
 
index b2217a6f0a0ba70cb7947a0b825c8e77f7d65648..5b34fba69ac1b0eaebabaf8a82c801082eacc864 100644 (file)
@@ -1,36 +1,28 @@
 package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
 
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.core.api.data.DataProviderService;
 import org.opendaylight.controller.sal.core.api.data.DataValidator;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 
 public class BackwardsCompatibleDataBroker implements DataProviderService, SchemaContextListener {
 
-    DOMDataBroker backingBroker;
-    DataNormalizer normalizer;
-    private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
-
+    private final DOMDataBroker backingBroker;
+    private DataNormalizer normalizer;
 
     public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl) {
         backingBroker = newBiDataImpl;
@@ -43,7 +35,7 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
 
     @Override
     public CompositeNode readConfigurationData(final InstanceIdentifier legacyPath) {
-        BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+        final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
         try {
             return tx.readConfigurationData(legacyPath);
         } finally {
@@ -53,7 +45,7 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
 
     @Override
     public CompositeNode readOperationalData(final InstanceIdentifier legacyPath) {
-        BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+        final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
         try {
             return tx.readOperationalData(legacyPath);
         } finally {
@@ -67,9 +59,19 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
     }
 
     @Override
-    public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier path,
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier legacyPath,
             final DataChangeListener listener) {
-        return fakeRegistry .register(listener);
+        final InstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
+
+        final TranslatingListenerInvoker translatingCfgListener =
+                TranslatingListenerInvoker.createConfig(listener, normalizer);
+        translatingCfgListener.register(backingBroker, normalizedPath);
+
+        final TranslatingListenerInvoker translatingOpListener =
+                TranslatingListenerInvoker.createOperational(listener, normalizer);
+        translatingOpListener.register(backingBroker, normalizedPath);
+
+        return new DelegateListenerRegistration(translatingCfgListener, translatingOpListener, listener);
     }
 
     @Override
@@ -90,7 +92,7 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
         return null;
     }
 
-    // Obsolote functionality
+    // Obsolete functionality
 
     @Override
     public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
@@ -124,25 +126,26 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
         throw new UnsupportedOperationException("Data Reader contract is not supported.");
     }
 
-    private final class TranslatingListenerInvoker implements DOMDataChangeListener, Delegator<DataChangeListener> {
-
+    private static class DelegateListenerRegistration implements ListenerRegistration<DataChangeListener> {
+        private final TranslatingListenerInvoker translatingCfgListener;
+        private final TranslatingListenerInvoker translatingOpListener;
+        private final DataChangeListener listener;
 
-        private DataChangeListener delegate;
+        public DelegateListenerRegistration(final TranslatingListenerInvoker translatingCfgListener, final TranslatingListenerInvoker translatingOpListener, final DataChangeListener listener) {
+            this.translatingCfgListener = translatingCfgListener;
+            this.translatingOpListener = translatingOpListener;
+            this.listener = listener;
+        }
 
         @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
-
-            DataChangeEvent<InstanceIdentifier, CompositeNode> legacyChange = null;
-            delegate.onDataChanged(legacyChange);
+        public void close() {
+            translatingCfgListener.close();
+            translatingOpListener.close();
         }
 
         @Override
-        public DataChangeListener getDelegate() {
-
-            return delegate;
+        public DataChangeListener getInstance() {
+            return listener;
         }
-
-
     }
-
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java
new file mode 100644 (file)
index 0000000..3de07fc
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.collect.Maps;
+
+public abstract class TranslatingDataChangeEvent implements
+DataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
+
+    private TranslatingDataChangeEvent() {
+    }
+
+    public static DataChangeEvent<InstanceIdentifier, CompositeNode> createOperational(
+            final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+        return new OperationalChangeEvent(change, normalizer);
+    }
+
+    public static DataChangeEvent<InstanceIdentifier, CompositeNode> createConfiguration(
+            final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+        return new ConfigurationChangeEvent(change, normalizer);
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public CompositeNode getOriginalConfigurationSubtree() {
+        return null;
+    }
+
+    @Override
+    public CompositeNode getOriginalOperationalSubtree() {
+        return null;
+    }
+
+    @Override
+    public CompositeNode getUpdatedConfigurationSubtree() {
+        return null;
+    }
+
+    @Override
+    public CompositeNode getUpdatedOperationalSubtree() {
+        return null;
+    }
+
+    private final static class OperationalChangeEvent extends TranslatingDataChangeEvent {
+
+        private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+        private final DataNormalizer normalizer;
+        private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+        public OperationalChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+                final DataNormalizer normalizer) {
+            this.delegate = change;
+            this.normalizer = normalizer;
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+            return transformToLegacy(normalizer, delegate.getCreatedData());
+        }
+
+
+        @Override
+        public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+            return delegate.getRemovedPaths();
+        }
+
+        @Override
+        public CompositeNode getOriginalOperationalSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+        }
+
+        @Override
+        public CompositeNode getUpdatedOperationalSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+            return transformToLegacy(normalizer, delegate.getOriginalData());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+            if(updatedCache == null) {
+                final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+                final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+                final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+                updatedComposite.putAll(created);
+                updatedComposite.putAll(updated);
+                updatedCache = Collections.unmodifiableMap(updatedComposite);
+            }
+            return updatedCache;
+        }
+
+        @Override
+        public String toString() {
+            return "OperationalChangeEvent [delegate=" + delegate + "]";
+        }
+
+    }
+
+    private static Map<InstanceIdentifier, CompositeNode> transformToLegacy(final DataNormalizer normalizer, final Map<InstanceIdentifier, ? extends NormalizedNode<?, ?>> nodes) {
+        final Map<InstanceIdentifier, CompositeNode> legacy = Maps.newHashMap();
+
+        for (final Map.Entry<InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : nodes.entrySet()) {
+            try {
+                legacy.put(normalizer.toLegacy(entry.getKey()), normalizer.toLegacy(entry.getKey(), entry.getValue()));
+            } catch (final DataNormalizationException e) {
+                throw new IllegalStateException("Unable to transform data change event to legacy format", e);
+            }
+        }
+        return legacy;
+    }
+
+    private final static class ConfigurationChangeEvent extends TranslatingDataChangeEvent {
+
+        private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+        private final DataNormalizer normalizer;
+        private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+        public ConfigurationChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+                final DataNormalizer normalizer) {
+            this.delegate = change;
+            this.normalizer = normalizer;
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+            return transformToLegacy(normalizer, delegate.getCreatedData());
+        }
+
+
+        @Override
+        public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+            return delegate.getRemovedPaths();
+        }
+
+        @Override
+        public CompositeNode getOriginalConfigurationSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+        }
+
+        @Override
+        public CompositeNode getUpdatedConfigurationSubtree() {
+            // first argument is unused
+            return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+            return transformToLegacy(normalizer, delegate.getOriginalData());
+        }
+
+        @Override
+        public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+            if(updatedCache == null) {
+                final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+                final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+                final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+                updatedComposite.putAll(created);
+                updatedComposite.putAll(updated);
+                updatedCache = Collections.unmodifiableMap(updatedComposite);
+            }
+            return updatedCache;
+        }
+
+        @Override
+        public String toString() {
+            return "ConfigurationChangeEvent [delegate=" + delegate + "]";
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingListenerInvoker.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingListenerInvoker.java
new file mode 100644 (file)
index 0000000..1ce252d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+abstract class TranslatingListenerInvoker implements AutoCloseable, DOMDataChangeListener, Delegator<DataChangeListener> {
+
+    private final DataChangeListener delegate;
+    private final DataNormalizer normalizer;
+    protected ListenerRegistration<DOMDataChangeListener> reg;
+
+    protected TranslatingListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+        this.delegate = listener;
+        this.normalizer = normalizer;
+    }
+
+    static TranslatingListenerInvoker createConfig(final DataChangeListener listener, final DataNormalizer normalizer) {
+        return new TranslatingConfigListenerInvoker(listener, normalizer);
+    }
+
+    static TranslatingListenerInvoker createOperational(final DataChangeListener listener, final DataNormalizer normalizer) {
+        return new TranslatingOperationalListenerInvoker(listener, normalizer);
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+        delegate.onDataChanged(getLegacyEvent(normalizer, normalizedChange));
+    }
+
+    abstract DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer,
+                                                                               final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange);
+
+    @Override
+    public DataChangeListener getDelegate() {
+        return delegate;
+    }
+
+    abstract void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath);
+
+    @Override
+    public void close() {
+        if (reg != null) {
+            reg.close();
+        }
+    }
+
+    static final class TranslatingConfigListenerInvoker extends TranslatingListenerInvoker {
+
+        public TranslatingConfigListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+            super(listener, normalizer);
+        }
+
+        DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+            return TranslatingDataChangeEvent.createConfiguration(normalizedChange, normalizer);
+        }
+
+        @Override
+        void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+            reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, normalizedPath, this,
+                    AsyncDataBroker.DataChangeScope.SUBTREE);
+        }
+    }
+
+    static final class TranslatingOperationalListenerInvoker extends TranslatingListenerInvoker {
+
+        public TranslatingOperationalListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+            super(listener, normalizer);
+        }
+
+        DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+            return TranslatingDataChangeEvent.createOperational(normalizedChange, normalizer);
+        }
+
+        @Override
+        void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+            reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, normalizedPath, this,
+                    AsyncDataBroker.DataChangeScope.SUBTREE);
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/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 b540eea..0000000
+++ /dev/null
@@ -1,87 +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 StoreMetadataNode metadataTree;
-        private SchemaContext schemaContext;
-
-        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
deleted file mode 100644 (file)
index 6baf764..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.sal.dom.store.impl;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-public class DataPreconditionFailedException extends Exception {
-
-    /**
-     *
-     */
-    private static final long serialVersionUID = 596430355175413427L;
-    private final InstanceIdentifier path;
-
-    public DataPreconditionFailedException(final InstanceIdentifier path) {
-        this.path = path;
-    }
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final String message) {
-        super(message);
-        this.path = path;
-    }
-
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final Throwable cause) {
-        super(cause);
-        this.path = path;
-    }
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause) {
-        super(message, cause);
-        this.path = path;
-    }
-
-    public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause, final boolean enableSuppression,
-            final boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
-        this.path = path;
-    }
-
-    public InstanceIdentifier getPath() {
-        return path;
-    }
-
-}
index e848a51a66ee84eb05f743acab9fbd82a21ab008..00df6580effda8da33e80a648653935049010c47 100644 (file)
@@ -9,19 +9,20 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
-import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.increase;
 
 import java.util.Collections;
 import java.util.concurrent.Callable;
 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;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.InMemoryDataTreeFactory;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
@@ -32,9 +33,7 @@ import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
@@ -44,32 +43,21 @@ import com.google.common.base.Objects;
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
 public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, SchemaContextListener {
-
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
-    private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
-
+    private final DataTree dataTree = InMemoryDataTreeFactory.getInstance().create();
+    private final ListenerTree listenerTree = ListenerTree.create();
+    private final AtomicLong txCounter = new AtomicLong(0);
     private final ListeningExecutorService executor;
     private final String name;
-    private final AtomicLong txCounter = new AtomicLong(0);
-    private final ListenerTree listenerTree;
-    private final AtomicReference<DataAndMetadataSnapshot> snapshot;
-
-    private ModificationApplyOperation operationTree;
-
-    private SchemaContext schemaContext;
 
     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
@@ -79,23 +67,22 @@ 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);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new SnapshotBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
+        return new SnapshotBackedWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this);
     }
 
     @Override
     public synchronized void onGlobalContextUpdated(final SchemaContext ctx) {
-        operationTree = SchemaAwareApplyOperationRoot.from(ctx);
-        schemaContext = ctx;
+        dataTree.setSchemaContext(ctx);
     }
 
     @Override
@@ -115,9 +102,9 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
             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) //
@@ -146,35 +133,6 @@ 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());
-
-        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.
-         */
-        synchronized (this) {
-            final boolean success = snapshot.compareAndSet(currentSnapshot, newSnapshot);
-            checkState(success, "Store snapshot and transaction snapshot differ. This should never happen.");
-
-            for (ChangeListenerNotifyTask task : listenerResolver.call()) {
-                LOG.trace("Scheduling invocation of listeners: {}", task);
-                executor.submit(task);
-            }
-        }
-    }
-
     private static abstract class AbstractDOMStoreTransaction implements DOMStoreTransaction {
         private final Object identifier;
 
@@ -204,15 +162,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 DataTreeSnapshot stableSnapshot;
 
-        public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) {
+        public SnapshotBackedReadTransaction(final Object identifier, final DataTreeSnapshot snapshot) {
             super(identifier);
             this.stableSnapshot = Preconditions.checkNotNull(snapshot);
-            LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree()
-                    .getSubtreeVersion());
+            LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot);
         }
 
         @Override
@@ -225,23 +182,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 MutableDataTree mutableTree;
+    DOMStoreWriteTransaction {
+        private DataTreeModification mutableTree;
         private InMemoryDOMDataStore store;
         private boolean ready = false;
 
-        public SnapshotBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
-                final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
+        public SnapshotBackedWriteTransaction(final Object identifier, final DataTreeSnapshot snapshot,
+                final InMemoryDOMDataStore store) {
             super(identifier);
-            mutableTree = MutableDataTree.from(snapshot, applyOper);
+            mutableTree = snapshot.newModification();
             this.store = store;
-            LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree()
-                    .getSubtreeVersion());
+            LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot);
         }
 
         @Override
@@ -305,7 +261,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
             return store.submit(this);
         }
 
-        protected MutableDataTree getMutatedView() {
+        protected DataTreeModification getMutatedView() {
             return mutableTree;
         }
 
@@ -316,18 +272,18 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     }
 
     private static class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements
-            DOMStoreReadWriteTransaction {
+    DOMStoreReadWriteTransaction {
 
-        protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
-                final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
-            super(identifier, snapshot, store, applyOper);
+        protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataTreeSnapshot snapshot,
+                final InMemoryDOMDataStore store) {
+            super(identifier, snapshot, store);
         }
 
         @Override
         public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
             LOG.trace("Tx: {} Read: {}", getIdentifier(), path);
             try {
-                return Futures.immediateFuture(getMutatedView().read(path));
+                return Futures.immediateFuture(getMutatedView().readNode(path));
             } catch (Exception e) {
                 LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
                 throw e;
@@ -338,63 +294,40 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     private class ThreePhaseCommitImpl implements DOMStoreThreePhaseCommitCohort {
 
         private final SnapshotBackedWriteTransaction transaction;
-        private final NodeModification modification;
+        private final DataTreeModification modification;
 
-        private DataAndMetadataSnapshot storeSnapshot;
-        private Optional<StoreMetadataNode> proposedSubtree;
         private ResolveDataChangeEventsTask listenerResolver;
+        private DataTreeCandidate candidate;
 
         public ThreePhaseCommitImpl(final SnapshotBackedWriteTransaction writeTransaction) {
             this.transaction = writeTransaction;
-            this.modification = transaction.getMutatedView().getRootModification();
+            this.modification = transaction.getMutatedView();
         }
 
         @Override
         public ListenableFuture<Boolean> canCommit() {
-            final DataAndMetadataSnapshot snapshotCapture = snapshot.get();
-            final ModificationApplyOperation snapshotOperation = operationTree;
-
             return executor.submit(new Callable<Boolean>() {
-
                 @Override
-                public Boolean call() throws Exception {
-                    Boolean applicable = false;
+                public Boolean call() {
                     try {
-                        snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification,
-                            Optional.of(snapshotCapture.getMetadataTree()));
-                        applicable = true;
+                        dataTree.validate(modification);
+                        LOG.debug("Store Transaction: {} can be committed", transaction.getIdentifier());
+                        return true;
                     } catch (DataPreconditionFailedException e) {
                         LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e);
-                        applicable = false;
+                        return false;
                     }
-                    LOG.debug("Store Transaction: {} : canCommit : {}", transaction.getIdentifier(), applicable);
-                    return applicable;
                 }
             });
         }
 
         @Override
         public ListenableFuture<Void> preCommit() {
-            storeSnapshot = snapshot.get();
-            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();
-
-                    proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
-                            increase(metadataTree.getSubtreeVersion()));
-
-                    listenerResolver = ResolveDataChangeEventsTask.create() //
-                            .setRootPath(PUBLIC_ROOT_PATH) //
-                            .setBeforeRoot(Optional.of(metadataTree)) //
-                            .setAfterRoot(proposedSubtree) //
-                            .setModificationRoot(modification) //
-                            .setListenerRoot(listenerTree);
-
+                public Void call() {
+                    candidate = dataTree.prepare(modification);
+                    listenerResolver = ResolveDataChangeEventsTask.create(candidate, listenerTree);
                     return null;
                 }
             });
@@ -402,48 +335,28 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
 
         @Override
         public ListenableFuture<Void> abort() {
-            storeSnapshot = null;
-            proposedSubtree = null;
-            return Futures.<Void> immediateFuture(null);
+            candidate = null;
+            return Futures.immediateFuture(null);
         }
 
         @Override
         public ListenableFuture<Void> commit() {
-            if (modification.getModificationType() == ModificationType.UNMODIFIED) {
-                return Futures.immediateFuture(null);
+            checkState(candidate != null, "Proposed subtree must be computed");
+
+            /*
+             * The commit has to occur atomically with regard to listener
+             * registrations.
+             */
+            synchronized (this) {
+                dataTree.commit(candidate);
+
+                for (ChangeListenerNotifyTask task : listenerResolver.call()) {
+                    LOG.trace("Scheduling invocation of listeners: {}", task);
+                    executor.submit(task);
+                }
             }
 
-            checkState(proposedSubtree != null, "Proposed subtree must be computed");
-            checkState(storeSnapshot != null, "Proposed subtree must be computed");
-            // return ImmediateFuture<>;
-            InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(), listenerResolver);
-            return Futures.<Void> immediateFuture(null);
-        }
-
-    }
-
-    private static final class AlwaysFailOperation implements ModificationApplyOperation {
-
-        @Override
-        public Optional<StoreMetadataNode> apply(final NodeModification modification,
-                final Optional<StoreMetadataNode> storeMeta, final UnsignedLong subtreeVersion) {
-            throw new IllegalStateException("Schema Context is not available.");
+            return Futures.immediateFuture(null);
         }
-
-        @Override
-        public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
-            throw new IllegalStateException("Schema Context is not available.");
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-            throw new IllegalStateException("Schema Context is not available.");
-        }
-
-        @Override
-        public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
-            throw new IllegalStateException("Schema Context is not available.");
-        }
-
     }
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java
deleted file mode 100644 (file)
index b711163..0000000
+++ /dev/null
@@ -1,144 +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 static com.google.common.base.Preconditions.checkState;
-
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-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.TreeNodeUtils;
-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.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-/*
- * FIXME: the thread safety of concurrent write/delete/read/seal operations
- *        needs to be evaluated.
- */
-class MutableDataTree {
-    private static final Logger LOG = LoggerFactory.getLogger(MutableDataTree.class);
-    private final AtomicBoolean sealed = new AtomicBoolean();
-    private final ModificationApplyOperation strategyTree;
-    private final DataAndMetadataSnapshot snapshot;
-    private final NodeModification rootModification;
-
-    private MutableDataTree(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation strategyTree) {
-        this.snapshot = snapshot;
-        this.strategyTree = strategyTree;
-        this.rootModification = NodeModification.createUnmodified(snapshot.getMetadataTree());
-    }
-
-    public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
-        checkSealed();
-        resolveModificationFor(path).write(value);
-    }
-
-    public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
-        checkSealed();
-        mergeImpl(resolveModificationFor(path),data);
-    }
-
-    private void mergeImpl(final OperationWithModification op,final NormalizedNode<?,?> data) {
-
-        if(data instanceof NormalizedNodeContainer<?,?,?>) {
-            @SuppressWarnings({ "rawtypes", "unchecked" })
-            NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
-            for(NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
-                PathArgument childId = child.getIdentifier();
-                mergeImpl(op.forChild(childId), child);
-            }
-        }
-        op.merge(data);
-    }
-
-    public void delete(final InstanceIdentifier path) {
-        checkSealed();
-        resolveModificationFor(path).delete();
-    }
-
-    public Optional<NormalizedNode<?, ?>> read(final InstanceIdentifier path) {
-        Entry<InstanceIdentifier, NodeModification> modification = TreeNodeUtils.findClosestsOrFirstMatch(rootModification, path, NodeModification.IS_TERMINAL_PREDICATE);
-
-        Optional<StoreMetadataNode> result = resolveSnapshot(modification);
-        if (result.isPresent()) {
-            NormalizedNode<?, ?> data = result.get().getData();
-            return NormalizedNodeUtils.findNode(modification.getKey(), data, path);
-        }
-        return Optional.absent();
-    }
-
-    private Optional<StoreMetadataNode> resolveSnapshot(
-            final Entry<InstanceIdentifier, NodeModification> keyModification) {
-        InstanceIdentifier path = keyModification.getKey();
-        NodeModification modification = keyModification.getValue();
-        return resolveSnapshot(path, modification);
-    }
-
-    private Optional<StoreMetadataNode> resolveSnapshot(final InstanceIdentifier path,
-            final NodeModification modification) {
-        try {
-            Optional<Optional<StoreMetadataNode>> potentialSnapshot = modification.getSnapshotCache();
-            if(potentialSnapshot.isPresent()) {
-                return potentialSnapshot.get();
-            }
-            return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
-                    StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion()));
-        } catch (Exception e) {
-            LOG.error("Could not create snapshot for {}:{}", path,modification,e);
-            throw e;
-        }
-    }
-
-    private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
-        LOG.trace("Resolving modification apply strategy for {}", path);
-        return TreeNodeUtils.findNodeChecked(strategyTree, path);
-    }
-
-    private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
-        NodeModification modification = rootModification;
-        // We ensure strategy is present.
-        ModificationApplyOperation operation = resolveModificationStrategy(path);
-        for (PathArgument pathArg : path.getPath()) {
-            modification = modification.modifyChild(pathArg);
-        }
-        return OperationWithModification.from(operation, modification);
-    }
-
-    public static MutableDataTree from(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation resolver) {
-        return new MutableDataTree(snapshot, resolver);
-    }
-
-    public void seal() {
-        final boolean success = sealed.compareAndSet(false, true);
-        Preconditions.checkState(success, "Attempted to seal an already-sealed Data Tree.");
-        rootModification.seal();
-    }
-
-    private void checkSealed() {
-        checkState(!sealed.get(), "Data Tree is sealed. No further modifications allowed.");
-    }
-
-    protected NodeModification getRootModification() {
-        return rootModification;
-    }
-
-    @Override
-    public String toString() {
-        return "MutableDataTree [modification=" + rootModification + "]";
-    }
-}
index 44d50166af21df772f478d057fa479d879e0b829..b36ef3dd7c16250bfcc101ab4567be3feaaadbc4 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
-import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.append;
+import static org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils.append;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -22,11 +22,12 @@ import java.util.concurrent.Callable;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.SimpleEventFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Node;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
@@ -38,6 +39,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
@@ -62,60 +64,17 @@ import com.google.common.collect.Multimap;
  * </ul>
  *
  */
-public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
+final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
     private static final Logger LOG = LoggerFactory.getLogger(ResolveDataChangeEventsTask.class);
     private static final DOMImmutableDataChangeEvent NO_CHANGE = builder(DataChangeScope.BASE).build();
 
-    private InstanceIdentifier rootPath;
-    private ListenerTree listenerRoot;
-    private NodeModification modificationRoot;
-    private Optional<StoreMetadataNode> beforeRoot;
-    private Optional<StoreMetadataNode> afterRoot;
     private final Multimap<ListenerTree.Node, DOMImmutableDataChangeEvent> events = HashMultimap.create();
+    private final DataTreeCandidate candidate;
+    private final ListenerTree listenerRoot;
 
-    protected InstanceIdentifier getRootPath() {
-        return rootPath;
-    }
-
-    protected ResolveDataChangeEventsTask setRootPath(final InstanceIdentifier rootPath) {
-        this.rootPath = rootPath;
-        return this;
-    }
-
-    protected ListenerTree getListenerRoot() {
-        return listenerRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setListenerRoot(final ListenerTree listenerRoot) {
-        this.listenerRoot = listenerRoot;
-        return this;
-    }
-
-    protected NodeModification getModificationRoot() {
-        return modificationRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setModificationRoot(final NodeModification modificationRoot) {
-        this.modificationRoot = modificationRoot;
-        return this;
-    }
-
-    protected Optional<StoreMetadataNode> getBeforeRoot() {
-        return beforeRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setBeforeRoot(final Optional<StoreMetadataNode> beforeRoot) {
-        this.beforeRoot = beforeRoot;
-        return this;
-    }
-
-    protected Optional<StoreMetadataNode> getAfterRoot() {
-        return afterRoot;
-    }
-
-    protected ResolveDataChangeEventsTask setAfterRoot(final Optional<StoreMetadataNode> afterRoot) {
-        this.afterRoot = afterRoot;
-        return this;
+    public ResolveDataChangeEventsTask(DataTreeCandidate candidate, ListenerTree listenerTree) {
+        this.candidate = Preconditions.checkNotNull(candidate);
+        this.listenerRoot = Preconditions.checkNotNull(listenerTree);
     }
 
     /**
@@ -129,11 +88,8 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
      */
     @Override
     public Iterable<ChangeListenerNotifyTask> call() {
-        LOG.trace("Resolving events for {}", modificationRoot);
-
         try (final Walker w = listenerRoot.getWalker()) {
-            resolveAnyChangeEvent(rootPath, Collections.singleton(w.getRootNode()), modificationRoot, beforeRoot,
-                    afterRoot);
+            resolveAnyChangeEvent(candidate.getRootPath(), Collections.singleton(w.getRootNode()), candidate.getRootNode());
             return createNotificationTasks();
         }
     }
@@ -298,29 +254,38 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
      * @return Data Change Event of this node and all it's children
      */
     private DOMImmutableDataChangeEvent resolveAnyChangeEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final NodeModification modification,
-            final Optional<StoreMetadataNode> before, final Optional<StoreMetadataNode> after) {
-        // No listeners are present in listener registration subtree
-        // no before and after state is present
-        if (!before.isPresent() && !after.isPresent()) {
+            final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode node) {
+
+        if (node.getModificationType() != ModificationType.UNMODIFIED &&
+                !node.getDataAfter().isPresent() && !node.getDataBefore().isPresent()) {
+            LOG.debug("Modification at {} has type {}, but no before- and after-data. Assuming unchanged.",
+                    path, node.getModificationType());
             return NO_CHANGE;
         }
-        switch (modification.getModificationType()) {
+
+        // no before and after state is present
+
+        switch (node.getModificationType()) {
         case SUBTREE_MODIFIED:
-            return resolveSubtreeChangeEvent(path, listeners, modification, before.get(), after.get());
+            return resolveSubtreeChangeEvent(path, listeners, node);
         case MERGE:
         case WRITE:
-            if (before.isPresent()) {
-                return resolveReplacedEvent(path, listeners, before.get().getData(), after.get().getData());
+            Preconditions.checkArgument(node.getDataAfter().isPresent(),
+                    "Modification at {} has type {} but no after-data", path, node.getModificationType());
+            if (node.getDataBefore().isPresent()) {
+                return resolveReplacedEvent(path, listeners, node.getDataBefore().get(), node.getDataAfter().get());
             } else {
-                return resolveCreateEvent(path, listeners, after.get());
+                return resolveCreateEvent(path, listeners, node.getDataAfter().get());
             }
         case DELETE:
-            return resolveDeleteEvent(path, listeners, before.get());
-        default:
+            Preconditions.checkArgument(node.getDataBefore().isPresent(),
+                    "Modification at {} has type {} but no before-data", path, node.getModificationType());
+            return resolveDeleteEvent(path, listeners, node.getDataBefore().get());
+        case UNMODIFIED:
             return NO_CHANGE;
         }
 
+        throw new IllegalStateException(String.format("Unhandled node state %s at %s", node.getModificationType(), path));
     }
 
     private DOMImmutableDataChangeEvent resolveReplacedEvent(final InstanceIdentifier path,
@@ -355,7 +320,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
     private DOMImmutableDataChangeEvent resolveNodeContainerReplaced(final InstanceIdentifier path,
             final Collection<Node> listeners,
             final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont,
-            final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
+                    final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
         final Set<PathArgument> alreadyProcessed = new HashSet<>();
         final List<DOMImmutableDataChangeEvent> childChanges = new LinkedList<>();
 
@@ -430,17 +395,17 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
      * @return
      */
     private DOMImmutableDataChangeEvent resolveCreateEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final StoreMetadataNode afterState) {
+            final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> afterState) {
         @SuppressWarnings({ "unchecked", "rawtypes" })
-        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState.getData();
+        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState;
         return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getCreateEventFactory());
     }
 
     private DOMImmutableDataChangeEvent resolveDeleteEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final StoreMetadataNode beforeState) {
+            final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> beforeState) {
 
         @SuppressWarnings({ "unchecked", "rawtypes" })
-        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState.getData();
+        final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState;
         return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getRemoveEventFactory());
     }
 
@@ -450,7 +415,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
         final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
         DOMImmutableDataChangeEvent propagateEvent = event;
         // We have listeners for this node or it's children, so we will try
-            // to do additional processing
+        // to do additional processing
         if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
             LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory);
 
@@ -481,30 +446,31 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
     }
 
     private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
-            final Collection<ListenerTree.Node> listeners, final NodeModification modification,
-            final StoreMetadataNode before, final StoreMetadataNode after) {
+            final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode modification) {
 
-        Builder one = builder(DataChangeScope.ONE).setBefore(before.getData()).setAfter(after.getData());
+        Preconditions.checkArgument(modification.getDataBefore().isPresent(), "Subtree change with before-data not present at path %s", path);
+        Preconditions.checkArgument(modification.getDataAfter().isPresent(), "Subtree change with after-data not present at path %s", path);
 
-        Builder subtree = builder(DataChangeScope.SUBTREE).setBefore(before.getData()).setAfter(after.getData());
+        Builder one = builder(DataChangeScope.ONE).
+                setBefore(modification.getDataBefore().get()).
+                setAfter(modification.getDataAfter().get());
+        Builder subtree = builder(DataChangeScope.SUBTREE).
+                setBefore(modification.getDataBefore().get()).
+                setAfter(modification.getDataAfter().get());
 
-        for (NodeModification childMod : modification.getModifications()) {
+        for (DataTreeCandidateNode childMod : modification.getChildNodes()) {
             PathArgument childId = childMod.getIdentifier();
             InstanceIdentifier childPath = append(path, childId);
             Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
 
-            Optional<StoreMetadataNode> childBefore = before.getChild(childId);
-            Optional<StoreMetadataNode> childAfter = after.getChild(childId);
-
             switch (childMod.getModificationType()) {
             case WRITE:
             case MERGE:
             case DELETE:
-                one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod, childBefore, childAfter));
+                one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod));
                 break;
             case SUBTREE_MODIFIED:
-                subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod, childBefore.get(),
-                        childAfter.get()));
+                subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod));
                 break;
             case UNMODIFIED:
                 // no-op
@@ -556,7 +522,7 @@ public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeList
         }
     }
 
-    public static ResolveDataChangeEventsTask create() {
-        return new ResolveDataChangeEventsTask();
+    public static ResolveDataChangeEventsTask create(DataTreeCandidate candidate, ListenerTree listenerTree) {
+        return new ResolveDataChangeEventsTask(candidate, listenerTree);
     }
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java
deleted file mode 100644 (file)
index afe9653..0000000
+++ /dev/null
@@ -1,759 +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 static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
-import org.opendaylight.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;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-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 com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.primitives.UnsignedLong;
-
-public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
-
-    public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
-        if (schemaNode instanceof ContainerSchemaNode) {
-            return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
-        } else if (schemaNode instanceof ListSchemaNode) {
-            return fromListSchemaNode((ListSchemaNode) schemaNode);
-        } else if (schemaNode instanceof ChoiceNode) {
-            return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
-        } else if (schemaNode instanceof LeafListSchemaNode) {
-            return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
-        } else if (schemaNode instanceof LeafSchemaNode) {
-            return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
-        }
-        throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
-    }
-
-    private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
-        List<QName> keyDefinition = schemaNode.getKeyDefinition();
-        if (keyDefinition == null || keyDefinition.isEmpty()) {
-            return new UnkeyedListModificationStrategy(schemaNode);
-        }
-        if (schemaNode.isUserOrdered()) {
-            return new OrderedMapModificationStrategy(schemaNode);
-        }
-
-        return new UnorderedMapModificationStrategy(schemaNode);
-    }
-
-    private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
-        if(schemaNode.isUserOrdered()) {
-            return new OrderedLeafSetModificationStrategy(schemaNode);
-        } else {
-            return new UnorderedLeafSetModificationStrategy(schemaNode);
-        }
-    }
-
-
-    public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
-            final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
-        AugmentationSchema augSchema = null;
-        allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
-            boolean containsAll = true;
-            for (DataSchemaNode child : potential.getChildNodes()) {
-                if (identifier.getPossibleChildNames().contains(child.getQName())) {
-                    augSchema = potential;
-                    break allAugments;
-                }
-            }
-        }
-        if (augSchema != null) {
-            return new AugmentationModificationStrategy(augSchema, resolvedTree);
-        }
-        return null;
-    }
-
-    protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
-        Optional<ModificationApplyOperation> potential = getChild(child);
-        checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
-        return potential.get();
-    }
-
-    @Override
-    public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
-        if (modification.getModificationType() == ModificationType.WRITE) {
-            verifyWritenStructure(modification.getWritenValue());
-        }
-    }
-
-    protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
-
-    @Override
-    public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-        switch (modification.getModificationType()) {
-        case DELETE:
-            checkDeleteApplicable(modification, current);
-        case SUBTREE_MODIFIED:
-            checkSubtreeModificationApplicable(path,modification, current);
-            return;
-        case WRITE:
-            checkWriteApplicable(path,modification, current);
-            return;
-        case MERGE:
-            checkMergeApplicable(path,modification,current);
-            return;
-        case UNMODIFIED:
-            return;
-        default:
-            throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
-        }
-
-    }
-
-    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()) {
-            /*
-             * 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());
-            }
-        }
-    }
-
-    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()) {
-            checkNotConflicting(path,original.get(), current.get());
-        } else if(original.isPresent()) {
-            throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
-        }
-    }
-
-    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 void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
-            final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
-
-    private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
-    }
-
-    @Override
-    public final Optional<StoreMetadataNode> apply(final NodeModification modification,
-            final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-
-        switch (modification.getModificationType()) {
-        case DELETE:
-            return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
-        case SUBTREE_MODIFIED:
-            Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
-                    modification);
-            return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
-                    subtreeVersion)));
-        case MERGE:
-            if(currentMeta.isPresent()) {
-                return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
-            } // Fallback to write is intentional - if node is not preexisting merge is same as write
-        case WRITE:
-            return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
-        case UNMODIFIED:
-            return currentMeta;
-        default:
-            throw new IllegalArgumentException("Provided modification type is not supported.");
-        }
-    }
-
-    protected abstract StoreMetadataNode applyMerge(NodeModification modification,
-            StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
-
-    protected abstract StoreMetadataNode applyWrite(NodeModification modification,
-            Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
-
-    protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
-            StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
-
-    public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
-            SchemaAwareApplyOperation {
-
-        private final T schema;
-        private final Class<? extends NormalizedNode<?, ?>> nodeClass;
-
-        protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
-            super();
-            this.schema = schema;
-            this.nodeClass = nodeClass;
-        }
-
-        @Override
-        protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
-            checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-            throw new UnsupportedOperationException("Node " + schema.getPath()
-                    + "is leaf type node. Child nodes not allowed");
-        }
-
-        @Override
-        protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
-                final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
-            throw new UnsupportedOperationException("Node " + schema.getPath()
-                    + "is leaf type node. Subtree change is not allowed.");
-        }
-
-        @Override
-        protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
-                final UnsignedLong subtreeVersion) {
-            return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
-        }
-
-        @Override
-        protected StoreMetadataNode applyWrite(final NodeModification modification,
-                final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-            UnsignedLong nodeVersion = subtreeVersion;
-            return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
-                    .setData(modification.getWritenValue()).build();
-        }
-
-        @Override
-        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
-                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-            throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
-        }
-
-    }
-
-    public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
-
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
-            super(schema, (Class) LeafSetEntryNode.class);
-        }
-    }
-
-    public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
-
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        protected LeafModificationStrategy(final LeafSchemaNode schema) {
-            super(schema, (Class) LeafNode.class);
-        }
-    }
-
-    public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
-
-        private final Class<? extends NormalizedNode<?, ?>> nodeClass;
-
-        protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
-            this.nodeClass = nodeClass;
-        }
-
-        @Override
-        public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
-            if (modification.getModificationType() == ModificationType.WRITE) {
-
-            }
-            for (NodeModification childModification : modification.getModifications()) {
-                resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
-            }
-        }
-
-        @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) {
-            checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
-            checkArgument(writenValue instanceof NormalizedNodeContainer);
-            NormalizedNodeContainer writenCont = (NormalizedNodeContainer) writenValue;
-            for (Object child : writenCont.getValue()) {
-                checkArgument(child instanceof NormalizedNode);
-                NormalizedNode childNode = (NormalizedNode) child;
-            }
-        }
-
-        @Override
-        protected StoreMetadataNode applyWrite(final NodeModification modification,
-                final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-
-            NormalizedNode<?, ?> newValue = modification.getWritenValue();
-
-            final UnsignedLong nodeVersion;
-            if (currentMeta.isPresent()) {
-                nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
-            } else {
-                nodeVersion = subtreeVersion;
-            }
-
-            final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
-            if (!modification.hasAdditionalModifications()) {
-                return newValueMeta;
-            }
-
-            @SuppressWarnings("rawtypes")
-            NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
-            StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
-                    .setNodeVersion(nodeVersion) //
-                    .setSubtreeVersion(subtreeVersion);
-
-            return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
-        }
-
-        @Override
-        protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
-                final UnsignedLong subtreeVersion) {
-            // For Node Containers - merge is same as subtree change - we only replace children.
-            return applySubtreeChange(modification, currentMeta, subtreeVersion);
-        }
-
-        @Override
-        public StoreMetadataNode applySubtreeChange(final NodeModification modification,
-                final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
-            // Bump subtree version to its new target
-            final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
-
-            @SuppressWarnings("rawtypes")
-            NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
-            StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder, currentMeta)
-                    .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
-                    .setSubtreeVersion(updatedSubtreeVersion);
-
-            return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion);
-        }
-
-        private StoreMetadataNode mutateChildren(final Iterable<NodeModification> modifications, final StoreMetadataNode meta,
-                final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) {
-
-            for (NodeModification mod : modifications) {
-                final PathArgument id = mod.getIdentifier();
-                final Optional<StoreMetadataNode> cm = meta.getChild(id);
-
-                Optional<StoreMetadataNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
-                if (result.isPresent()) {
-                    builder.add(result.get());
-                } else {
-                    builder.remove(id);
-                }
-            }
-
-            return builder.build();
-        }
-
-        @Override
-        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);
-                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);
-            }
-        }
-
-        @SuppressWarnings("rawtypes")
-        protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
-    }
-
-    public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
-            NormalizedNodeContainerModificationStrategy {
-
-        private final T schema;
-        private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
-                .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
-
-                    @Override
-                    public ModificationApplyOperation apply(final PathArgument identifier) {
-                        if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
-                            return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
-                        }
-
-                        DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
-                        if (child == null) {
-                            return null;
-                        }
-                        return from(child);
-                    }
-                }));
-
-        protected DataNodeContainerModificationStrategy(final T schema,
-                final Class<? extends NormalizedNode<?, ?>> nodeClass) {
-            super(nodeClass);
-            this.schema = schema;
-        }
-
-        protected T getSchema() {
-            return schema;
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            try {
-                return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
-            } catch (ExecutionException e) {
-                return Optional.absent();
-            }
-        }
-
-        @Override
-        @SuppressWarnings("rawtypes")
-        protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
-
-        @Override
-        public String toString() {
-            return getClass().getSimpleName() + " [" + schema + "]";
-        }
-
-    }
-
-    public static class ContainerModificationStrategy extends
-            DataNodeContainerModificationStrategy<ContainerSchemaNode> {
-
-        public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
-            super(schemaNode, ContainerNode.class);
-        }
-
-        @Override
-        @SuppressWarnings("rawtypes")
-        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof ContainerNode);
-            return ImmutableContainerNodeBuilder.create((ContainerNode) original);
-        }
-    }
-
-    public static class UnkeyedListItemModificationStrategy extends
-            DataNodeContainerModificationStrategy<ListSchemaNode> {
-
-        public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
-            super(schemaNode, UnkeyedListEntryNode.class);
-        }
-
-        @Override
-        @SuppressWarnings("rawtypes")
-        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof UnkeyedListEntryNode);
-            return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
-        }
-    }
-
-    public static class AugmentationModificationStrategy extends
-            DataNodeContainerModificationStrategy<AugmentationSchema> {
-
-        protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
-            super(createAugmentProxy(schema,resolved), AugmentationNode.class);
-        }
-
-        @Override
-        @SuppressWarnings("rawtypes")
-        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof AugmentationNode);
-            return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
-        }
-    }
-
-    public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
-        private final ChoiceNode schema;
-        private final Map<PathArgument, ModificationApplyOperation> childNodes;
-
-        public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
-            super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
-            this.schema = schemaNode;
-            ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
-
-            for (ChoiceCaseNode caze : schemaNode.getCases()) {
-                for (DataSchemaNode cazeChild : caze.getChildNodes()) {
-                    SchemaAwareApplyOperation childNode = from(cazeChild);
-                    child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
-                }
-            }
-            childNodes = child.build();
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-            return Optional.fromNullable(childNodes.get(child));
-        }
-
-        @Override
-        @SuppressWarnings("rawtypes")
-        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
-            return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
-        }
-    }
-
-    public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
-
-        protected ListEntryModificationStrategy(final ListSchemaNode schema) {
-            super(schema, MapEntryNode.class);
-        }
-
-        @Override
-        @SuppressWarnings("rawtypes")
-        protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof MapEntryNode);
-            return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
-        }
-    }
-
-    public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
-        private final Optional<ModificationApplyOperation> entryStrategy;
-
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
-            super((Class) LeafSetNode.class);
-            entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
-        }
-
-        @SuppressWarnings("rawtypes")
-        @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof LeafSetNode<?>);
-            return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeWithValue) {
-                return entryStrategy;
-            }
-            return Optional.absent();
-        }
-    }
-
-    public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
-        private final Optional<ModificationApplyOperation> entryStrategy;
-
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
-            super((Class) LeafSetNode.class);
-            entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
-        }
-
-        @SuppressWarnings("rawtypes")
-        @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof OrderedLeafSetNode<?>);
-            return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeWithValue) {
-                return entryStrategy;
-            }
-            return Optional.absent();
-        }
-    }
-
-    public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
-
-        private final Optional<ModificationApplyOperation> entryStrategy;
-
-        protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
-            entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
-        }
-
-        @Override
-        protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
-                final UnsignedLong subtreeVersion) {
-            return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
-        }
-
-        @Override
-        protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
-                final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
-            throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
-        }
-
-        @Override
-        protected StoreMetadataNode applyWrite(final NodeModification modification,
-                final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-            return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-            if (child instanceof NodeIdentifier) {
-                return entryStrategy;
-            }
-            return Optional.absent();
-        }
-
-        @Override
-        protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
-
-        }
-
-        @Override
-        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
-                final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
-            throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
-        }
-
-    }
-
-    public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
-        private final Optional<ModificationApplyOperation> entryStrategy;
-
-        protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
-            super(MapNode.class);
-            entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
-        }
-
-        @SuppressWarnings("rawtypes")
-        @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof MapNode);
-            return ImmutableMapNodeBuilder.create((MapNode) original);
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeIdentifierWithPredicates) {
-                return entryStrategy;
-            }
-            return Optional.absent();
-        }
-
-        @Override
-        public String toString() {
-            return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
-        }
-    }
-
-    public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
-        private final Optional<ModificationApplyOperation> entryStrategy;
-
-        protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
-            super(OrderedMapNode.class);
-            entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
-        }
-
-        @SuppressWarnings("rawtypes")
-        @Override
-        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
-            checkArgument(original instanceof OrderedMapNode);
-            return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeIdentifierWithPredicates) {
-                return entryStrategy;
-            }
-            return Optional.absent();
-        }
-
-        @Override
-        public String toString() {
-            return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
-        }
-    }
-
-    public void verifyIdentifier(final PathArgument identifier) {
-
-    }
-
-    public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
-        Set<DataSchemaNode> realChildSchemas = new HashSet<>();
-        for(DataSchemaNode augChild : schema.getChildNodes()) {
-            realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
-        }
-        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;
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataPreconditionFailedException.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataPreconditionFailedException.java
new file mode 100644 (file)
index 0000000..bb2111e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public class DataPreconditionFailedException extends Exception {
+    private static final long serialVersionUID = 1L;
+    private final InstanceIdentifier path;
+
+    public DataPreconditionFailedException(final InstanceIdentifier path, final String message) {
+        super(message);
+        this.path = Preconditions.checkNotNull(path);
+    }
+
+    public DataPreconditionFailedException(final InstanceIdentifier path, final String message, final Throwable cause) {
+        super(message, cause);
+        this.path = Preconditions.checkNotNull(path);
+    }
+
+    public InstanceIdentifier getPath() {
+        return path;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTree.java
new file mode 100644 (file)
index 0000000..ee9726a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Interface representing a data tree which can be modified in an MVCC fashion.
+ */
+public interface DataTree {
+    /**
+     * Take a read-only point-in-time snapshot of the tree.
+     *
+     * @return Data tree snapshot.
+     */
+    DataTreeSnapshot takeSnapshot();
+
+    /**
+     * Make the data tree use a new schema context. The context will be used
+     * only by subsequent operations.
+     *
+     * @param newSchemaContext new SchemaContext
+     * @throws IllegalArgumentException if the new context is incompatible
+     */
+    void setSchemaContext(SchemaContext newSchemaContext);
+
+    /**
+     * Validate whether a particular modification can be applied to the data tree.
+     */
+    void validate(DataTreeModification modification) throws DataPreconditionFailedException;
+
+    /**
+     * Prepare a modification for commit.
+     *
+     * @param modification
+     * @return candidate data tree
+     */
+    DataTreeCandidate prepare(DataTreeModification modification);
+
+    /**
+     * Commit a data tree candidate.
+     *
+     * @param candidate data tree candidate
+     */
+    void commit(DataTreeCandidate candidate);
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidate.java
new file mode 100644 (file)
index 0000000..906e284
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public interface DataTreeCandidate {
+    DataTreeCandidateNode getRootNode();
+    InstanceIdentifier getRootPath();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidateNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidateNode.java
new file mode 100644 (file)
index 0000000..b1ca45b
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+public interface DataTreeCandidateNode {
+    PathArgument getIdentifier();
+    Iterable<DataTreeCandidateNode> getChildNodes();
+
+    ModificationType getModificationType();
+    Optional<NormalizedNode<?, ?>> getDataAfter();
+    Optional<NormalizedNode<?, ?>> getDataBefore();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeFactory.java
new file mode 100644 (file)
index 0000000..7422c11
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+/**
+ * Factory interface for creating data trees.
+ */
+public interface DataTreeFactory {
+       /**
+        * Create a new data tree.
+        *
+        * @return A data tree instance.
+        */
+       DataTree create();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeModification.java
new file mode 100644 (file)
index 0000000..cff90a4
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Class encapsulation of set of modifications to a base tree. This tree is backed
+ * by a read-only snapshot and tracks modifications on top of that. The modification
+ * has the ability to rebase itself to a new snapshot.
+ */
+public interface DataTreeModification extends DataTreeSnapshot {
+       void delete(InstanceIdentifier path);
+       void merge(InstanceIdentifier path, NormalizedNode<?, ?> data);
+       void write(InstanceIdentifier path, NormalizedNode<?, ?> data);
+       void seal();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeSnapshot.java
new file mode 100644 (file)
index 0000000..a94acc5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+/**
+ * Read-only snapshot of a {@link DataTree}. The snapshot is stable and isolated,
+ * e.g. data tree changes occurring after the snapshot has been taken are not
+ * visible through the snapshot.
+ */
+public interface DataTreeSnapshot {
+    /**
+     * Read a particular node from the snapshot.
+     *
+     * @param path Path of the node
+     * @return Optional result encapsulating the presence and value of the node
+     */
+    Optional<NormalizedNode<?, ?>> readNode(InstanceIdentifier path);
+
+    /**
+     * Create a new data tree modification based on this snapshot, using the
+     * specified data application strategy.
+     *
+     * @param strategy data modification strategy
+     * @return A new data tree modification
+     */
+    DataTreeModification newModification();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java
deleted file mode 100644 (file)
index b8ad736..0000000
+++ /dev/null
@@ -1,192 +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.tree;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-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.primitives.UnsignedLong;
-
-public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
-
-    private final UnsignedLong nodeVersion;
-    private final UnsignedLong subtreeVersion;
-    private final NormalizedNode<?, ?> data;
-
-    private final Map<PathArgument, StoreMetadataNode> children;
-
-    /**
-     *
-     * @param data
-     * @param nodeVersion
-     * @param subtreeVersion
-     * @param children Map of children, must not be modified externally
-     */
-    protected StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
-            final UnsignedLong subtreeVersion, final Map<PathArgument, StoreMetadataNode> children) {
-        this.nodeVersion = nodeVersion;
-        this.subtreeVersion = subtreeVersion;
-        this.data = data;
-        this.children = Preconditions.checkNotNull(children);
-    }
-
-    public static StoreMetadataNode createEmpty(final NormalizedNode<?, ?> data) {
-        return new StoreMetadataNode(data, UnsignedLong.ZERO, UnsignedLong.ZERO,
-                Collections.<PathArgument, StoreMetadataNode>emptyMap());
-    }
-
-    public StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
-            final UnsignedLong subtreeVersion) {
-        this(data, nodeVersion, subtreeVersion, Collections.<PathArgument, StoreMetadataNode>emptyMap());
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static Builder builder(StoreMetadataNode node) {
-        return new Builder(node);
-    }
-
-    public UnsignedLong getNodeVersion() {
-        return this.nodeVersion;
-    }
-
-    @Override
-    public PathArgument getIdentifier() {
-        return data.getIdentifier();
-    }
-
-    public UnsignedLong getSubtreeVersion() {
-        return subtreeVersion;
-    }
-
-    public NormalizedNode<?, ?> getData() {
-        return this.data;
-    }
-
-    @Override
-    public Optional<StoreMetadataNode> getChild(final PathArgument key) {
-        return Optional.fromNullable(children.get(key));
-    }
-
-    @Override
-    public String toString() {
-        return "StoreMetadataNode [identifier=" + getIdentifier() + ", nodeVersion=" + nodeVersion + "]";
-    }
-
-    public static Optional<UnsignedLong> getVersion(final Optional<StoreMetadataNode> currentMetadata) {
-        if (currentMetadata.isPresent()) {
-            return Optional.of(currentMetadata.get().getNodeVersion());
-        }
-        return Optional.absent();
-    }
-
-    public static Optional<StoreMetadataNode> getChild(final Optional<StoreMetadataNode> parent,
-            final PathArgument child) {
-        if (parent.isPresent()) {
-            return parent.get().getChild(child);
-        }
-        return Optional.absent();
-    }
-
-    public static final StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node,
-            final UnsignedLong nodeVersion, final UnsignedLong subtreeVersion) {
-        Builder builder = builder() //
-                .setNodeVersion(nodeVersion) //
-                .setSubtreeVersion(subtreeVersion) //
-                .setData(node);
-        if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
-
-            @SuppressWarnings("unchecked")
-            NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> nodeContainer = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) node;
-            for (NormalizedNode<?, ?> subNode : nodeContainer.getValue()) {
-                builder.add(createRecursively(subNode, nodeVersion, subtreeVersion));
-            }
-        }
-        return builder.build();
-    }
-
-    public static class Builder {
-
-        private UnsignedLong nodeVersion;
-        private UnsignedLong subtreeVersion;
-        private NormalizedNode<?, ?> data;
-        private Map<PathArgument, StoreMetadataNode> children;
-        private boolean dirty = false;
-
-        private Builder() {
-            children = new HashMap<>();
-        }
-
-        public Builder(StoreMetadataNode node) {
-            children = new HashMap<>(node.children);
-        }
-
-        public UnsignedLong getVersion() {
-            return nodeVersion;
-
-        }
-
-        public Builder setNodeVersion(final UnsignedLong version) {
-            this.nodeVersion = version;
-            return this;
-        }
-
-        public Builder setSubtreeVersion(final UnsignedLong version) {
-            this.subtreeVersion = version;
-            return this;
-        }
-
-        public Builder setData(final NormalizedNode<?, ?> data) {
-            this.data = data;
-            return this;
-        }
-
-        public Builder add(final StoreMetadataNode node) {
-            if (dirty) {
-                children = new HashMap<>(children);
-                dirty = false;
-            }
-            children.put(node.getIdentifier(), node);
-            return this;
-        }
-
-        public Builder remove(final PathArgument id) {
-            if (dirty) {
-                children = new HashMap<>(children);
-                dirty = false;
-            }
-            children.remove(id);
-            return this;
-        }
-
-        public StoreMetadataNode build() {
-            checkState(data != null, "Data node should not be null.");
-            checkState(subtreeVersion.compareTo(nodeVersion) >= 0,
-                    "Subtree version must be equals or greater than node version.");
-            dirty = true;
-            return new StoreMetadataNode(data, nodeVersion, subtreeVersion, children);
-        }
-    }
-
-    public static StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node, final UnsignedLong version) {
-        return createRecursively(node, version, version);
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java
deleted file mode 100644 (file)
index a66a1d5..0000000
+++ /dev/null
@@ -1,80 +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.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-
-import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
-
-/**
- *
- * Helper builder
- *
- *
- */
-@SuppressWarnings("rawtypes")
-public class StoreNodeCompositeBuilder {
-
-    private final StoreMetadataNode.Builder metadata;
-
-    private final NormalizedNodeContainerBuilder data;
-
-    private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder) {
-        this.metadata = StoreMetadataNode.builder();
-        this.data = Preconditions.checkNotNull(nodeBuilder);
-    }
-
-    public StoreNodeCompositeBuilder(NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
-        this.metadata = StoreMetadataNode.builder(currentMeta);
-        this.data = Preconditions.checkNotNull(nodeBuilder);
-    }
-
-    @SuppressWarnings("unchecked")
-    public StoreNodeCompositeBuilder add(final StoreMetadataNode node) {
-        metadata.add(node);
-        data.addChild(node.getData());
-        return this;
-    }
-
-    @SuppressWarnings("unchecked")
-    public StoreNodeCompositeBuilder remove(PathArgument id) {
-        metadata.remove(id);
-        data.removeChild(id);
-        return this;
-    }
-
-    public StoreMetadataNode build() {
-        return metadata.setData(data.build()).build();
-    }
-
-    public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder) {
-        return new StoreNodeCompositeBuilder(nodeBuilder);
-    }
-
-    public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
-        return new StoreNodeCompositeBuilder(nodeBuilder, currentMeta);
-    }
-
-    @SuppressWarnings("unchecked")
-    public StoreNodeCompositeBuilder setIdentifier(final PathArgument identifier) {
-        data.withNodeIdentifier(identifier);
-        return this;
-    }
-
-    public StoreNodeCompositeBuilder setNodeVersion(final UnsignedLong nodeVersion) {
-        metadata.setNodeVersion(nodeVersion);
-        return this;
-    }
-
-    public StoreNodeCompositeBuilder setSubtreeVersion(final UnsignedLong updatedSubtreeVersion) {
-        metadata.setSubtreeVersion(updatedSubtreeVersion);
-        return this;
-    }
-}
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.md.sal.dom.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
 
 import java.util.Set;
 
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AbstractDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AbstractDataTreeCandidate.java
new file mode 100644 (file)
index 0000000..cddda5c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+abstract class AbstractDataTreeCandidate implements DataTreeCandidate {
+    private final InstanceIdentifier rootPath;
+
+    protected AbstractDataTreeCandidate(final InstanceIdentifier rootPath) {
+        this.rootPath = Preconditions.checkNotNull(rootPath);
+    }
+
+    @Override
+    public final InstanceIdentifier getRootPath() {
+        return rootPath;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java
new file mode 100644 (file)
index 0000000..15479be
--- /dev/null
@@ -0,0 +1,37 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Optional;
+
+/**
+ * An implementation of apply operation which fails to do anything,
+ * consistently. An instance of this class is used by the data tree
+ * if it does not have a SchemaContext attached and hence cannot
+ * perform anything meaningful.
+ */
+final class AlwaysFailOperation implements ModificationApplyOperation {
+    @Override
+    public Optional<TreeNode> apply(final ModifiedNode modification,
+            final Optional<TreeNode> storeMeta, final Version subtreeVersion) {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+
+    @Override
+    public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> storeMetadata) {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+
+    @Override
+    public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+
+    @Override
+    public void verifyStructure(final ModifiedNode modification) {
+        throw new IllegalStateException("Schema Context is not available.");
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java
new file mode 100644 (file)
index 0000000..dc89148
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+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.ListSchemaNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+
+/**
+ * Base strategy for applying changes to a ContainerNode, irrespective of its
+ * actual type.
+ *
+ * @param <T> Type of the container node
+ */
+abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends NormalizedNodeContainerModificationStrategy {
+
+    private final T schema;
+    private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
+            .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
+
+                @Override
+                public ModificationApplyOperation apply(final PathArgument identifier) {
+                    if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
+                        return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
+                    }
+
+                    DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
+                    if (child == null) {
+                        return null;
+                    }
+                    return from(child);
+                }
+            }));
+
+    protected DataNodeContainerModificationStrategy(final T schema,
+            final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+        super(nodeClass);
+        this.schema = schema;
+    }
+
+    protected T getSchema() {
+        return schema;
+    }
+
+    @Override
+    public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+        try {
+            return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
+        } catch (ExecutionException e) {
+            return Optional.absent();
+        }
+    }
+
+    @Override
+    @SuppressWarnings("rawtypes")
+    protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " [" + schema + "]";
+    }
+
+    public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy<AugmentationSchema> {
+
+        protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
+            super(createAugmentProxy(schema,resolved), AugmentationNode.class);
+        }
+
+        @Override
+        @SuppressWarnings("rawtypes")
+        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof AugmentationNode);
+            return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
+        }
+
+
+        private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
+            Set<DataSchemaNode> realChildSchemas = new HashSet<>();
+            for(DataSchemaNode augChild : schema.getChildNodes()) {
+                realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
+            }
+            return new AugmentationSchemaProxy(schema, realChildSchemas);
+        }
+    }
+
+    public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
+
+        public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
+            super(schemaNode, ContainerNode.class);
+        }
+
+        @Override
+        @SuppressWarnings("rawtypes")
+        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof ContainerNode);
+            return ImmutableContainerNodeBuilder.create((ContainerNode) original);
+        }
+    }
+
+    public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
+
+        protected ListEntryModificationStrategy(final ListSchemaNode schema) {
+            super(schema, MapEntryNode.class);
+        }
+
+        @Override
+        @SuppressWarnings("rawtypes")
+        protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof MapEntryNode);
+            return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
+        }
+    }
+
+    public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
+
+        public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
+            super(schemaNode, UnkeyedListEntryNode.class);
+        }
+
+        @Override
+        @SuppressWarnings("rawtypes")
+        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof UnkeyedListEntryNode);
+            return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java
new file mode 100644 (file)
index 0000000..d3495b5
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * Read-only snapshot of the data tree.
+ */
+final class InMemoryDataTree implements DataTree {
+    private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTree.class);
+    private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
+
+    private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
+    private ModificationApplyOperation applyOper = new AlwaysFailOperation();
+    private SchemaContext currentSchemaContext;
+    private TreeNode rootNode;
+
+    public InMemoryDataTree(final TreeNode rootNode, final SchemaContext schemaContext) {
+        this.rootNode = Preconditions.checkNotNull(rootNode);
+
+        if (schemaContext != null) {
+            // Also sets applyOper
+            setSchemaContext(schemaContext);
+        }
+    }
+
+    @Override
+    public synchronized void setSchemaContext(final SchemaContext newSchemaContext) {
+        Preconditions.checkNotNull(newSchemaContext);
+
+        LOG.info("Attepting to install schema context {}", newSchemaContext);
+
+        /*
+         * FIXME: we should walk the schema contexts, both current and new and see
+         *        whether they are compatible here. Reject incompatible changes.
+         */
+
+        // Instantiate new apply operation, this still may fail
+        final ModificationApplyOperation newApplyOper = SchemaAwareApplyOperation.from(newSchemaContext);
+
+        // Ready to change the context now, make sure no operations are running
+        rwLock.writeLock().lock();
+        try {
+            this.applyOper = newApplyOper;
+            this.currentSchemaContext = newSchemaContext;
+        } finally {
+            rwLock.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public InMemoryDataTreeSnapshot takeSnapshot() {
+        rwLock.readLock().lock();
+        try {
+            return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, applyOper);
+        } finally {
+            rwLock.readLock().unlock();
+        }
+    }
+
+    @Override
+    public void validate(final DataTreeModification modification) throws DataPreconditionFailedException {
+        Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
+
+        final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
+        m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.<TreeNode>of(rootNode));
+    }
+
+    @Override
+    public synchronized DataTreeCandidate prepare(final DataTreeModification modification) {
+        Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
+
+        final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
+        final ModifiedNode root = m.getRootModification();
+
+        if (root.getType() == ModificationType.UNMODIFIED) {
+            return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root);
+        }
+
+        rwLock.writeLock().lock();
+        try {
+            final Optional<TreeNode> newRoot = m.getStrategy().apply(m.getRootModification(),
+                    Optional.<TreeNode>of(rootNode), rootNode.getSubtreeVersion().next());
+            Preconditions.checkState(newRoot.isPresent(), "Apply strategy failed to produce root node");
+            return new InMemoryDataTreeCandidate(PUBLIC_ROOT_PATH, root, rootNode, newRoot.get());
+        } finally {
+            rwLock.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public synchronized void commit(final DataTreeCandidate candidate) {
+        if (candidate instanceof NoopDataTreeCandidate) {
+            return;
+        }
+
+        Preconditions.checkArgument(candidate instanceof InMemoryDataTreeCandidate, "Invalid candidate class %s", candidate.getClass());
+        final InMemoryDataTreeCandidate c = (InMemoryDataTreeCandidate)candidate;
+
+        LOG.debug("Updating datastore from {} to {}", rootNode, c.getAfterRoot());
+
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Data Tree is {}", StoreUtils.toStringTree(c.getAfterRoot().getData()));
+        }
+
+        // Ready to change the context now, make sure no operations are running
+        rwLock.writeLock().lock();
+        try {
+            Preconditions.checkState(c.getBeforeRoot() == rootNode,
+                    String.format("Store tree %s and candidate base %s differ.", rootNode, c.getBeforeRoot()));
+            this.rootNode = c.getAfterRoot();
+        } finally {
+            rwLock.writeLock().unlock();
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java
new file mode 100644 (file)
index 0000000..bafea6b
--- /dev/null
@@ -0,0 +1,125 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
+    private static abstract class AbstractNode implements DataTreeCandidateNode {
+        private final ModifiedNode mod;
+        private final TreeNode newMeta;
+        private final TreeNode oldMeta;
+
+        protected AbstractNode(final ModifiedNode mod,
+                final TreeNode oldMeta, final TreeNode newMeta) {
+            this.newMeta = newMeta;
+            this.oldMeta = oldMeta;
+            this.mod = Preconditions.checkNotNull(mod);
+        }
+
+        protected final ModifiedNode getMod() {
+            return mod;
+        }
+
+        protected final TreeNode getNewMeta() {
+            return newMeta;
+        }
+
+        protected final TreeNode getOldMeta() {
+            return oldMeta;
+        }
+
+        private static final TreeNode childMeta(final TreeNode parent, final PathArgument id) {
+            if (parent != null) {
+                return parent.getChild(id).orNull();
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public Iterable<DataTreeCandidateNode> getChildNodes() {
+            return Iterables.transform(mod.getChildren(), new Function<ModifiedNode, DataTreeCandidateNode>() {
+                @Override
+                public DataTreeCandidateNode apply(final ModifiedNode input) {
+                    final PathArgument id = input.getIdentifier();
+                    return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
+                }
+            });
+        }
+
+        @Override
+        public ModificationType getModificationType() {
+            return mod.getType();
+        }
+
+        private Optional<NormalizedNode<?, ?>> optionalData(final TreeNode meta) {
+            if (meta != null) {
+                return Optional.<NormalizedNode<?,?>>of(meta.getData());
+            } else {
+                return Optional.absent();
+            }
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataAfter() {
+            return optionalData(newMeta);
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataBefore() {
+            return optionalData(oldMeta);
+        }
+    }
+
+    private static final class ChildNode extends AbstractNode {
+        public ChildNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
+            super(mod, oldMeta, newMeta);
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            return getMod().getIdentifier();
+        }
+    }
+
+    private static final class RootNode extends AbstractNode {
+        public RootNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
+            super(mod, oldMeta, newMeta);
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            throw new IllegalStateException("Attempted to get identifier of the root node");
+        }
+    }
+
+    private final RootNode root;
+
+    InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot,
+            final TreeNode beforeRoot, final TreeNode afterRoot) {
+        super(rootPath);
+        this.root = new RootNode(modificationRoot, beforeRoot, afterRoot);
+    }
+
+    TreeNode getAfterRoot() {
+        return root.getNewMeta();
+    }
+
+    TreeNode getBeforeRoot() {
+        return root.getOldMeta();
+    }
+
+    @Override
+    public DataTreeCandidateNode getRootNode() {
+        return root;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java
new file mode 100644 (file)
index 0000000..4640be4
--- /dev/null
@@ -0,0 +1,37 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * A factory for creating in-memory data trees.
+ */
+public final class InMemoryDataTreeFactory implements DataTreeFactory {
+    private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory();
+
+    private InMemoryDataTreeFactory() {
+        // Never instantiated externally
+    }
+
+    @Override
+    public InMemoryDataTree create() {
+        final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
+        final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
+
+        return new InMemoryDataTree(TreeNodeFactory.createTreeNode(data, Version.initial()), null);
+    }
+
+    /**
+     * Get an instance of this factory. This method cannot fail.
+     *
+     * @return Data tree factory instance.
+     */
+    public static final InMemoryDataTreeFactory getInstance() {
+        return INSTANCE;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java
new file mode 100644 (file)
index 0000000..c05ed4b
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import java.util.Map.Entry;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+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.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class InMemoryDataTreeModification implements DataTreeModification {
+    private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
+    private final ModificationApplyOperation strategyTree;
+    private final InMemoryDataTreeSnapshot snapshot;
+    private final ModifiedNode rootNode;
+
+    @GuardedBy("this")
+    private boolean sealed = false;
+
+    InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
+        this.snapshot = Preconditions.checkNotNull(snapshot);
+        this.strategyTree = Preconditions.checkNotNull(resolver);
+        this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode());
+    }
+
+    ModifiedNode getRootModification() {
+        return rootNode;
+    }
+
+    ModificationApplyOperation getStrategy() {
+        return strategyTree;
+    }
+
+    @Override
+    public synchronized void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
+        checkSealed();
+        resolveModificationFor(path).write(value);
+    }
+
+    @Override
+    public synchronized void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
+        checkSealed();
+        mergeImpl(resolveModificationFor(path),data);
+    }
+
+    private void mergeImpl(final OperationWithModification op,final NormalizedNode<?,?> data) {
+
+        if(data instanceof NormalizedNodeContainer<?,?,?>) {
+            @SuppressWarnings({ "rawtypes", "unchecked" })
+            NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
+            for(NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
+                PathArgument childId = child.getIdentifier();
+                mergeImpl(op.forChild(childId), child);
+            }
+        }
+        op.merge(data);
+    }
+
+    @Override
+    public synchronized void delete(final InstanceIdentifier path) {
+        checkSealed();
+        resolveModificationFor(path).delete();
+    }
+
+    @Override
+    public synchronized Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+        /*
+         * Walk the tree from the top, looking for the first node between root and
+         * the requested path which has been modified. If no such node exists,
+         * we use the node itself.
+         */
+        final Entry<InstanceIdentifier, ModifiedNode> entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE);
+        final InstanceIdentifier key = entry.getKey();
+        final ModifiedNode mod = entry.getValue();
+
+        final Optional<TreeNode> result = resolveSnapshot(key, mod);
+        if (result.isPresent()) {
+            NormalizedNode<?, ?> data = result.get().getData();
+            return NormalizedNodeUtils.findNode(key, data, path);
+        } else {
+            return Optional.absent();
+        }
+    }
+
+    private Optional<TreeNode> resolveSnapshot(final InstanceIdentifier path,
+            final ModifiedNode modification) {
+        final Optional<Optional<TreeNode>> potentialSnapshot = modification.getSnapshotCache();
+        if(potentialSnapshot.isPresent()) {
+            return potentialSnapshot.get();
+        }
+
+        try {
+            return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
+                    snapshot.getRootNode().getSubtreeVersion().next());
+        } catch (Exception e) {
+            LOG.error("Could not create snapshot for {}:{}", path,modification,e);
+            throw e;
+        }
+    }
+
+    private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
+        LOG.trace("Resolving modification apply strategy for {}", path);
+        return TreeNodeUtils.findNodeChecked(strategyTree, path);
+    }
+
+    private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
+        ModifiedNode modification = rootNode;
+        // We ensure strategy is present.
+        ModificationApplyOperation operation = resolveModificationStrategy(path);
+        for (PathArgument pathArg : path.getPath()) {
+            modification = modification.modifyChild(pathArg);
+        }
+        return OperationWithModification.from(operation, modification);
+    }
+
+    @Override
+    public synchronized void seal() {
+        Preconditions.checkState(!sealed, "Attempted to seal an already-sealed Data Tree.");
+        sealed = true;
+        rootNode.seal();
+    }
+
+    @GuardedBy("this")
+    private void checkSealed() {
+        Preconditions.checkState(!sealed, "Data Tree is sealed. No further modifications allowed.");
+    }
+
+    @Override
+    public String toString() {
+        return "MutableDataTree [modification=" + rootNode + "]";
+    }
+
+    @Override
+    public synchronized DataTreeModification newModification() {
+        Preconditions.checkState(sealed, "Attempted to chain on an unsealed modification");
+
+        // FIXME: transaction chaining
+        throw new UnsupportedOperationException("Implement this as part of transaction chaining");
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java
new file mode 100644 (file)
index 0000000..ee91e62
--- /dev/null
@@ -0,0 +1,48 @@
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
+    private final ModificationApplyOperation applyOper;
+    private final SchemaContext schemaContext;
+    private final TreeNode rootNode;
+
+    InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final TreeNode rootNode,
+            final ModificationApplyOperation applyOper) {
+        this.schemaContext = Preconditions.checkNotNull(schemaContext);
+        this.rootNode = Preconditions.checkNotNull(rootNode);
+        this.applyOper = Preconditions.checkNotNull(applyOper);
+    }
+
+    TreeNode getRootNode() {
+        return rootNode;
+    }
+
+    SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    @Override
+    public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+        return NormalizedNodeUtils.findNode(rootNode.getData(), path);
+    }
+
+    @Override
+    public InMemoryDataTreeModification newModification() {
+        return new InMemoryDataTreeModification(this, applyOper);
+    }
+
+    @Override
+    public String toString() {
+        return rootNode.getSubtreeVersion().toString();
+    }
+
+}
\ No newline at end of file
@@ -5,20 +5,20 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.md.sal.dom.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 
 import com.google.common.base.Optional;
-import com.google.common.primitives.UnsignedLong;
 
 /**
  *
- * Operation responsible for applying {@link NodeModification} on tree.
+ * Operation responsible for applying {@link ModifiedNode} on tree.
  *
  * Operation is composite - operation on top level node consists of
  * suboperations on child nodes. This allows to walk operation hierarchy and
@@ -30,7 +30,7 @@ import com.google.common.primitives.UnsignedLong;
  * Implementations MUST expose all nested suboperations which operates on child
  * nodes expose via {@link #getChild(PathArgument)} method.
  * <li>Same suboperations SHOULD be used when invoked via
- * {@link #apply(NodeModification, Optional)} if applicable.
+ * {@link #apply(ModifiedNode, Optional)} if applicable.
  *
  *
  * Hierarchical composite operation which is responsible for applying
@@ -38,7 +38,7 @@ import com.google.common.primitives.UnsignedLong;
  *
  *
  */
-public interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
+interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
 
     /**
      *
@@ -55,10 +55,10 @@ public interface ModificationApplyOperation extends StoreTreeNode<ModificationAp
      *             If it is not possible to apply Operation on provided Metadata
      *             node
      * @return new {@link StoreMetadataNode} if operation resulted in updating
-     *         node, {@link Optional#absent()} if {@link NodeModification}
+     *         node, {@link Optional#absent()} if {@link ModifiedNode}
      *         resulted in deletion of this node.
      */
-    Optional<StoreMetadataNode> apply(NodeModification modification, Optional<StoreMetadataNode> storeMeta, UnsignedLong subtreeVersion);
+    Optional<TreeNode> apply(ModifiedNode modification, Optional<TreeNode> storeMeta, Version subtreeVersion);
 
     /**
      *
@@ -68,7 +68,7 @@ public interface ModificationApplyOperation extends StoreTreeNode<ModificationAp
      * @param modification to be verified.
      * @throws IllegalArgumentException If provided NodeModification does not adhere to the structure.
      */
-    void verifyStructure(NodeModification modification) throws IllegalArgumentException;
+    void verifyStructure(ModifiedNode modification) throws IllegalArgumentException;
 
     /**
      * Returns a suboperation for specified tree node
@@ -80,14 +80,14 @@ public interface ModificationApplyOperation extends StoreTreeNode<ModificationAp
     Optional<ModificationApplyOperation> getChild(PathArgument child);
 
     /**
-    *
-    * Checks if provided node modification could be applied to current metadata node.
-    *
-    * @param modification Modification
-    * @param current Metadata Node to which modification should be applied
-    * @return true if modification is applicable
-    *         false if modification is no applicable
+     *
+     * Checks if provided node modification could be applied to current metadata node.
+     *
+     * @param modification Modification
+     * @param current Metadata Node to which modification should be applied
+     * @return true if modification is applicable
+     *         false if modification is no applicable
      * @throws DataPreconditionFailedException
-    */
-    void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
+     */
+    void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<TreeNode> current) throws DataPreconditionFailedException;
 }
@@ -5,15 +5,16 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.md.sal.dom.store.impl.tree;
-
-import static com.google.common.base.Preconditions.checkState;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
 
 import javax.annotation.concurrent.GuardedBy;
 
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -29,37 +30,36 @@ import com.google.common.base.Predicate;
  *
  * This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
  * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
- *
  */
-public class NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
+final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<PathArgument>, NodeModification {
 
-    public static final Predicate<NodeModification> IS_TERMINAL_PREDICATE = new Predicate<NodeModification>() {
+    public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
         @Override
-        public boolean apply(final NodeModification input) {
-            return input.getModificationType() == ModificationType.WRITE //
-                    || input.getModificationType() == ModificationType.DELETE //
-                    || input.getModificationType() == ModificationType.MERGE;
+        public boolean apply(final ModifiedNode input) {
+            switch (input.getType()) {
+            case DELETE:
+            case MERGE:
+            case WRITE:
+                return true;
+            case SUBTREE_MODIFIED:
+            case UNMODIFIED:
+                return false;
+            }
+
+            throw new IllegalArgumentException(String.format("Unhandled modification type %s", input.getType()));
         }
     };
+
+    private final Map<PathArgument, ModifiedNode> children = new LinkedHashMap<>();
+    private final Optional<TreeNode> original;
     private final PathArgument identifier;
     private ModificationType modificationType = ModificationType.UNMODIFIED;
-
-
-    private final Optional<StoreMetadataNode> original;
-
+    private Optional<TreeNode> snapshotCache;
     private NormalizedNode<?, ?> value;
 
-    private Optional<StoreMetadataNode> snapshotCache;
-
-    private final Map<PathArgument, NodeModification> childModification;
-
-    @GuardedBy("this")
-    private boolean sealed = false;
-
-    protected NodeModification(final PathArgument identifier, final Optional<StoreMetadataNode> original) {
+    private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original) {
         this.identifier = identifier;
         this.original = original;
-        childModification = new LinkedHashMap<>();
     }
 
     /**
@@ -67,7 +67,7 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
      *
      * @return
      */
-    public NormalizedNode<?, ?> getWritenValue() {
+    public NormalizedNode<?, ?> getWrittenValue() {
         return value;
     }
 
@@ -81,7 +81,8 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
      * Returns original store metadata
      * @return original store metadata
      */
-    public final Optional<StoreMetadataNode> getOriginal() {
+    @Override
+    public Optional<TreeNode> getOriginal() {
         return original;
     }
 
@@ -90,7 +91,8 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
      *
      * @return modification type
      */
-    public final ModificationType getModificationType() {
+    @Override
+    public ModificationType getType() {
         return modificationType;
     }
 
@@ -103,38 +105,42 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
      *
      */
     @Override
-    public Optional<NodeModification> getChild(final PathArgument child) {
-        return Optional.<NodeModification> fromNullable(childModification.get(child));
+    public Optional<ModifiedNode> getChild(final PathArgument child) {
+        return Optional.<ModifiedNode> fromNullable(children.get(child));
     }
 
     /**
      *
-     * Returns child modification if child was modified, creates {@link NodeModification}
+     * Returns child modification if child was modified, creates {@link ModifiedNode}
      * for child otherwise.
      *
      * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED}
      * changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
      *
      * @param child
-     * @return {@link NodeModification} for specified child, with {@link #getOriginal()}
-     *  containing child metadata if child was present in original data.
+     * @return {@link ModifiedNode} for specified child, with {@link #getOriginal()}
+     *         containing child metadata if child was present in original data.
      */
-    public synchronized NodeModification modifyChild(final PathArgument child) {
-        checkSealed();
+    public ModifiedNode modifyChild(final PathArgument child) {
         clearSnapshot();
-        if(modificationType == ModificationType.UNMODIFIED) {
+        if (modificationType == ModificationType.UNMODIFIED) {
             updateModificationType(ModificationType.SUBTREE_MODIFIED);
         }
-        final NodeModification potential = childModification.get(child);
+        final ModifiedNode potential = children.get(child);
         if (potential != null) {
             return potential;
         }
-        Optional<StoreMetadataNode> currentMetadata = Optional.absent();
-        if(original.isPresent()) {
-            currentMetadata = original.get().getChild(child);
+
+        final Optional<TreeNode> currentMetadata;
+        if (original.isPresent()) {
+            final TreeNode orig = original.get();
+            currentMetadata = orig.getChild(child);
+        } else {
+            currentMetadata = Optional.absent();
         }
-        NodeModification newlyCreated = new NodeModification(child,currentMetadata);
-        childModification.put(child, newlyCreated);
+
+        ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata);
+        children.put(child, newlyCreated);
         return newlyCreated;
     }
 
@@ -144,21 +150,20 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
      *
      * @return all recorded direct child modifications
      */
-    public Iterable<NodeModification> getModifications() {
-        return childModification.values();
+    @Override
+    public Iterable<ModifiedNode> getChildren() {
+        return children.values();
     }
 
-
     /**
      *
      * Records a delete for associated node.
      *
      */
-    public synchronized void delete() {
-        checkSealed();
+    public void delete() {
         clearSnapshot();
         updateModificationType(ModificationType.DELETE);
-        childModification.clear();
+        children.clear();
         this.value = null;
     }
 
@@ -168,31 +173,23 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
      *
      * @param value
      */
-    public synchronized void write(final NormalizedNode<?, ?> value) {
-        checkSealed();
+    public void write(final NormalizedNode<?, ?> value) {
         clearSnapshot();
         updateModificationType(ModificationType.WRITE);
-        childModification.clear();
+        children.clear();
         this.value = value;
     }
 
-    public synchronized void merge(final NormalizedNode<?, ?> data) {
-        checkSealed();
+    public void merge(final NormalizedNode<?, ?> data) {
         clearSnapshot();
         updateModificationType(ModificationType.MERGE);
         // FIXME: Probably merge with previous value.
         this.value = data;
     }
 
-    @GuardedBy("this")
-    private void checkSealed() {
-        checkState(!sealed, "Node Modification is sealed. No further changes allowed.");
-    }
-
-    public synchronized void seal() {
-        sealed = true;
+    void seal() {
         clearSnapshot();
-        for(NodeModification child : childModification.values()) {
+        for (ModifiedNode child : children.values()) {
             child.seal();
         }
     }
@@ -201,19 +198,15 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
         snapshotCache = null;
     }
 
-    public Optional<StoreMetadataNode> storeSnapshot(final Optional<StoreMetadataNode> snapshot) {
+    public Optional<TreeNode> storeSnapshot(final Optional<TreeNode> snapshot) {
         snapshotCache = snapshot;
         return snapshot;
     }
 
-    public Optional<Optional<StoreMetadataNode>> getSnapshotCache() {
+    public Optional<Optional<TreeNode>> getSnapshotCache() {
         return Optional.fromNullable(snapshotCache);
     }
 
-    public boolean hasAdditionalModifications() {
-        return !childModification.isEmpty();
-    }
-
     @GuardedBy("this")
     private void updateModificationType(final ModificationType type) {
         modificationType = type;
@@ -223,11 +216,10 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
     @Override
     public String toString() {
         return "NodeModification [identifier=" + identifier + ", modificationType="
-                + modificationType + ", childModification=" + childModification + "]";
+                + modificationType + ", childModification=" + children + "]";
     }
 
-    public static NodeModification createUnmodified(final StoreMetadataNode metadataTree) {
-        return new NodeModification(metadataTree.getIdentifier(), Optional.of(metadataTree));
+    public static ModifiedNode createUnmodified(final TreeNode metadataTree) {
+        return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree));
     }
-
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java
new file mode 100644 (file)
index 0000000..2639d05
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Optional;
+
+interface NodeModification extends Identifiable<PathArgument> {
+    ModificationType getType();
+    Optional<TreeNode> getOriginal();
+    Iterable<? extends NodeModification> getChildren();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java
new file mode 100644 (file)
index 0000000..2ef85cb
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class NoopDataTreeCandidate extends AbstractDataTreeCandidate {
+    private static final DataTreeCandidateNode ROOT = new DataTreeCandidateNode() {
+        @Override
+        public ModificationType getModificationType() {
+            return ModificationType.UNMODIFIED;
+        }
+
+        @Override
+        public Iterable<DataTreeCandidateNode> getChildNodes() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            throw new IllegalStateException("Attempted to read identifier of the no-operation change");
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataAfter() {
+            return Optional.absent();
+        }
+
+        @Override
+        public Optional<NormalizedNode<?, ?>> getDataBefore() {
+            return Optional.absent();
+        }
+    };
+
+    protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot) {
+        super(rootPath);
+        Preconditions.checkArgument(modificationRoot.getType() == ModificationType.UNMODIFIED);
+    }
+
+    @Override
+    public DataTreeCandidateNode getRootNode() {
+        return ROOT;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java
new file mode 100644 (file)
index 0000000..3a3af5e
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ListEntryModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafSetEntryModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.MutableTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
+
+    private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+
+    protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+        this.nodeClass = nodeClass;
+    }
+
+    @Override
+    public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+        if (modification.getType() == ModificationType.WRITE) {
+
+        }
+        for (ModifiedNode childModification : modification.getChildren()) {
+            resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
+        }
+    }
+
+    @Override
+    protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> 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 verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+        checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+        checkArgument(writtenValue instanceof NormalizedNodeContainer);
+
+        NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
+        for (Object child : container.getValue()) {
+            checkArgument(child instanceof NormalizedNode);
+
+            /*
+             * FIXME: fail-fast semantics:
+             *
+             * We can validate the data structure here, aborting the commit
+             * before it ever progresses to being committed.
+             */
+        }
+    }
+
+    @Override
+    protected TreeNode applyWrite(final ModifiedNode modification,
+            final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+        final Version nodeVersion;
+        if (currentMeta.isPresent()) {
+            nodeVersion = currentMeta.get().getVersion().next();
+        } else {
+            nodeVersion = subtreeVersion;
+        }
+
+        final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
+        final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, nodeVersion);
+
+        if (Iterables.isEmpty(modification.getChildren())) {
+            return newValueMeta;
+        }
+
+        /*
+         * This is where things get interesting. The user has performed a write and
+         * then she applied some more modifications to it. So we need to make sense
+         * of that an apply the operations on top of the written value. We could have
+         * done it during the write, but this operation is potentially expensive, so
+         * we have left it out of the fast path.
+         *
+         * As it turns out, once we materialize the written data, we can share the
+         * code path with the subtree change. So let's create an unsealed TreeNode
+         * and run the common parts on it -- which end with the node being sealed.
+         */
+        final MutableTreeNode mutable = newValueMeta.mutable();
+        mutable.setSubtreeVersion(subtreeVersion);
+
+        @SuppressWarnings("rawtypes")
+        final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
+
+        return mutateChildren(mutable, dataBuilder, nodeVersion, modification.getChildren());
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
+            final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
+
+        for (ModifiedNode mod : modifications) {
+            final PathArgument id = mod.getIdentifier();
+            final Optional<TreeNode> cm = meta.getChild(id);
+
+            Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+            if (result.isPresent()) {
+                final TreeNode tn = result.get();
+                meta.addChild(tn);
+                data.addChild(tn.getData());
+            } else {
+                meta.removeChild(id);
+                data.removeChild(id);
+            }
+        }
+
+        meta.setData(data.build());
+        return meta.seal();
+    }
+
+    @Override
+    protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+            final Version subtreeVersion) {
+        // For Node Containers - merge is same as subtree change - we only replace children.
+        return applySubtreeChange(modification, currentMeta, subtreeVersion);
+    }
+
+    @Override
+    public TreeNode applySubtreeChange(final ModifiedNode modification,
+            final TreeNode currentMeta, final Version subtreeVersion) {
+        // Bump subtree version to its new target
+        final Version updatedSubtreeVersion = currentMeta.getSubtreeVersion().next();
+
+        final MutableTreeNode newMeta = currentMeta.mutable();
+        newMeta.setSubtreeVersion(updatedSubtreeVersion);
+
+        @SuppressWarnings("rawtypes")
+        NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
+
+        return mutateChildren(newMeta, dataBuilder, updatedSubtreeVersion, modification.getChildren());
+    }
+
+    @Override
+    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> 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<TreeNode> current) throws DataPreconditionFailedException {
+        final TreeNode currentMeta = current.get();
+        for (NodeModification childMod : modification.getChildren()) {
+            final PathArgument childId = childMod.getIdentifier();
+            final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
+
+            InstanceIdentifier childPath = StoreUtils.append(path, childId);
+            resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
+        }
+    }
+
+    @Override
+    protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        if(current.isPresent()) {
+            checkChildPreconditions(path, modification,current);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
+
+    public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+        private final Map<PathArgument, ModificationApplyOperation> childNodes;
+
+        public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
+            super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
+            ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
+
+            for (ChoiceCaseNode caze : schemaNode.getCases()) {
+                for (DataSchemaNode cazeChild : caze.getChildNodes()) {
+                    SchemaAwareApplyOperation childNode = from(cazeChild);
+                    child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
+                }
+            }
+            childNodes = child.build();
+        }
+
+        @Override
+        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+            return Optional.fromNullable(childNodes.get(child));
+        }
+
+        @Override
+        @SuppressWarnings("rawtypes")
+        protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
+            return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
+        }
+    }
+
+    public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+        private final Optional<ModificationApplyOperation> entryStrategy;
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+            super((Class) LeafSetNode.class);
+            entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Override
+        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof OrderedLeafSetNode<?>);
+            return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
+        }
+
+        @Override
+        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+            if (identifier instanceof NodeWithValue) {
+                return entryStrategy;
+            }
+            return Optional.absent();
+        }
+    }
+
+    public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+        private final Optional<ModificationApplyOperation> entryStrategy;
+
+        protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
+            super(OrderedMapNode.class);
+            entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Override
+        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof OrderedMapNode);
+            return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
+        }
+
+        @Override
+        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+            if (identifier instanceof NodeIdentifierWithPredicates) {
+                return entryStrategy;
+            }
+            return Optional.absent();
+        }
+
+        @Override
+        public String toString() {
+            return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
+        }
+    }
+
+    public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+        private final Optional<ModificationApplyOperation> entryStrategy;
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+            super((Class) LeafSetNode.class);
+            entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Override
+        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof LeafSetNode<?>);
+            return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
+        }
+
+        @Override
+        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+            if (identifier instanceof NodeWithValue) {
+                return entryStrategy;
+            }
+            return Optional.absent();
+        }
+    }
+
+    public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+        private final Optional<ModificationApplyOperation> entryStrategy;
+
+        protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
+            super(MapNode.class);
+            entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Override
+        protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+            checkArgument(original instanceof MapNode);
+            return ImmutableMapNodeBuilder.create((MapNode) original);
+        }
+
+        @Override
+        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+            if (identifier instanceof NodeIdentifierWithPredicates) {
+                return entryStrategy;
+            }
+            return Optional.absent();
+        }
+
+        @Override
+        public String toString() {
+            return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
+        }
+    }
+}
@@ -5,23 +5,22 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.md.sal.dom.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
-import com.google.common.primitives.UnsignedLong;
 
-public class OperationWithModification {
+final class OperationWithModification {
 
-    private final NodeModification modification;
+    private final ModifiedNode modification;
 
     private final ModificationApplyOperation applyOperation;
 
-    private OperationWithModification(final ModificationApplyOperation op, final NodeModification mod) {
+    private OperationWithModification(final ModificationApplyOperation op, final ModifiedNode mod) {
         this.modification = mod;
         this.applyOperation = op;
     }
@@ -37,7 +36,7 @@ public class OperationWithModification {
         return this;
     }
 
-    public NodeModification getModification() {
+    public ModifiedNode getModification() {
         return modification;
     }
 
@@ -45,12 +44,12 @@ public class OperationWithModification {
         return applyOperation;
     }
 
-    public Optional<StoreMetadataNode> apply(final Optional<StoreMetadataNode> data, final UnsignedLong subtreeVersion) {
+    public Optional<TreeNode> apply(final Optional<TreeNode> data, final Version subtreeVersion) {
         return applyOperation.apply(modification, data, subtreeVersion);
     }
 
     public static OperationWithModification from(final ModificationApplyOperation operation,
-            final NodeModification modification) {
+            final ModifiedNode modification) {
         return new OperationWithModification(operation, modification);
 
     }
@@ -62,7 +61,7 @@ public class OperationWithModification {
     }
 
     public OperationWithModification forChild(final PathArgument childId) {
-        NodeModification childMod = modification.modifyChild(childId);
+        ModifiedNode childMod = modification.modifyChild(childId);
         Optional<ModificationApplyOperation> childOp = applyOperation.getChild(childId);
         return from(childOp.get(),childMod);
     }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java
new file mode 100644 (file)
index 0000000..bdf5667
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ContainerModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.ChoiceModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedLeafSetModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedMapModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.UnorderedLeafSetModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+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.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
+    private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class);
+
+    public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
+        if (schemaNode instanceof ContainerSchemaNode) {
+            return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
+        } else if (schemaNode instanceof ListSchemaNode) {
+            return fromListSchemaNode((ListSchemaNode) schemaNode);
+        } else if (schemaNode instanceof ChoiceNode) {
+            return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
+        } else if (schemaNode instanceof LeafListSchemaNode) {
+            return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
+        } else if (schemaNode instanceof LeafSchemaNode) {
+            return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
+        }
+        throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
+    }
+
+    public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
+            final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
+        AugmentationSchema augSchema = null;
+
+        allAugments:
+            for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
+                for (DataSchemaNode child : potential.getChildNodes()) {
+                    if (identifier.getPossibleChildNames().contains(child.getQName())) {
+                        augSchema = potential;
+                        break allAugments;
+                    }
+                }
+            }
+
+        if (augSchema != null) {
+            return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(augSchema, resolvedTree);
+        }
+        return null;
+    }
+
+    public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
+        if(!condition) {
+            throw new DataPreconditionFailedException(path, message);
+        }
+        return condition;
+    }
+
+    private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
+        List<QName> keyDefinition = schemaNode.getKeyDefinition();
+        if (keyDefinition == null || keyDefinition.isEmpty()) {
+            return new UnkeyedListModificationStrategy(schemaNode);
+        }
+        if (schemaNode.isUserOrdered()) {
+            return new OrderedMapModificationStrategy(schemaNode);
+        }
+
+        return new NormalizedNodeContainerModificationStrategy.UnorderedMapModificationStrategy(schemaNode);
+    }
+
+    private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
+        if(schemaNode.isUserOrdered()) {
+            return new OrderedLeafSetModificationStrategy(schemaNode);
+        } else {
+            return new UnorderedLeafSetModificationStrategy(schemaNode);
+        }
+    }
+
+    private static final void checkNotConflicting(final InstanceIdentifier path, final TreeNode original, final TreeNode current) throws DataPreconditionFailedException {
+        checkDataPrecondition(path, original.getVersion().equals(current.getVersion()),
+                "Node was replaced by other transaction.");
+        checkDataPrecondition(path, original.getSubtreeVersion().equals(current.getSubtreeVersion()),
+                "Node children was modified by other transaction");
+    }
+
+    protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
+        Optional<ModificationApplyOperation> potential = getChild(child);
+        checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
+        return potential.get();
+    }
+
+    @Override
+    public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+        if (modification.getType() == ModificationType.WRITE) {
+            verifyWrittenStructure(modification.getWrittenValue());
+        }
+    }
+
+    @Override
+    public final void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        switch (modification.getType()) {
+        case DELETE:
+            checkDeleteApplicable(modification, current);
+        case SUBTREE_MODIFIED:
+            checkSubtreeModificationApplicable(path, modification, current);
+            return;
+        case WRITE:
+            checkWriteApplicable(path, modification, current);
+            return;
+        case MERGE:
+            checkMergeApplicable(path, modification, current);
+            return;
+        case UNMODIFIED:
+            return;
+        default:
+            throw new UnsupportedOperationException("Suplied modification type "+ modification.getType()+ "is not supported.");
+        }
+
+    }
+
+    protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        Optional<TreeNode> original = modification.getOriginal();
+        if (original.isPresent() && current.isPresent()) {
+            /*
+             * 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());
+            }
+        }
+    }
+
+    protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        Optional<TreeNode> original = modification.getOriginal();
+        if (original.isPresent() && current.isPresent()) {
+            checkNotConflicting(path, original.get(), current.get());
+        } else if(original.isPresent()) {
+            throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
+        }
+    }
+
+    private void checkDeleteApplicable(final NodeModification modification, final Optional<TreeNode> current) {
+        // Delete is always applicable, we do not expose it to subclasses
+        if (current.isPresent()) {
+            LOG.trace("Delete operation turned to no-op on missing node {}", modification);
+        }
+    }
+
+    @Override
+    public final Optional<TreeNode> apply(final ModifiedNode modification,
+            final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+
+        switch (modification.getType()) {
+        case DELETE:
+            return modification.storeSnapshot(Optional.<TreeNode> absent());
+        case SUBTREE_MODIFIED:
+            Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
+                    modification);
+            return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
+                    subtreeVersion)));
+        case MERGE:
+            if(currentMeta.isPresent()) {
+                return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
+            } // Fallback to write is intentional - if node is not preexisting merge is same as write
+        case WRITE:
+            return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
+        case UNMODIFIED:
+            return currentMeta;
+        default:
+            throw new IllegalArgumentException("Provided modification type is not supported.");
+        }
+    }
+
+    protected abstract TreeNode applyMerge(ModifiedNode modification,
+            TreeNode currentMeta, Version subtreeVersion);
+
+    protected abstract TreeNode applyWrite(ModifiedNode modification,
+            Optional<TreeNode> currentMeta, Version subtreeVersion);
+
+    protected abstract TreeNode applySubtreeChange(ModifiedNode modification,
+            TreeNode currentMeta, Version subtreeVersion);
+
+    protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> current) throws DataPreconditionFailedException;
+
+    protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
+
+    public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
+
+        private final Optional<ModificationApplyOperation> entryStrategy;
+
+        protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
+            entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
+        }
+
+        @Override
+        protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+                final Version subtreeVersion) {
+            return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
+        }
+
+        @Override
+        protected TreeNode applySubtreeChange(final ModifiedNode modification,
+                final TreeNode currentMeta, final Version subtreeVersion) {
+            throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
+        }
+
+        @Override
+        protected TreeNode applyWrite(final ModifiedNode modification,
+                final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+            return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion);
+        }
+
+        @Override
+        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+            if (child instanceof NodeIdentifier) {
+                return entryStrategy;
+            }
+            return Optional.absent();
+        }
+
+        @Override
+        protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+
+        }
+
+        @Override
+        protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+                final Optional<TreeNode> current) throws DataPreconditionFailedException {
+            throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java
new file mode 100644 (file)
index 0000000..5f68782
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+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.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+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 com.google.common.base.Optional;
+
+abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
+
+    private final T schema;
+    private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+
+    protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+        super();
+        this.schema = schema;
+        this.nodeClass = nodeClass;
+    }
+
+    @Override
+    protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+        checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+    }
+
+    @Override
+    public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+        throw new UnsupportedOperationException("Node " + schema.getPath()
+                + "is leaf type node. Child nodes not allowed");
+    }
+
+    @Override
+    protected TreeNode applySubtreeChange(final ModifiedNode modification,
+            final TreeNode currentMeta, final Version subtreeVersion) {
+        throw new UnsupportedOperationException("Node " + schema.getPath()
+                + "is leaf type node. Subtree change is not allowed.");
+    }
+
+    @Override
+    protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+            final Version subtreeVersion) {
+        // Just overwrite whatever was there
+        return applyWrite(modification, null, subtreeVersion);
+    }
+
+    @Override
+    protected TreeNode applyWrite(final ModifiedNode modification,
+            final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+        return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion);
+    }
+
+    @Override
+    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> current) throws DataPreconditionFailedException {
+        throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
+    }
+
+    public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
+            super(schema, (Class) LeafSetEntryNode.class);
+        }
+    }
+
+    public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        protected LeafModificationStrategy(final LeafSchemaNode schema) {
+            super(schema, (Class) LeafNode.class);
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java
new file mode 100644 (file)
index 0000000..1444f0c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Preconditions;
+
+/*
+ * A very basic data tree node.
+ */
+abstract class AbstractTreeNode implements TreeNode {
+    private final NormalizedNode<?, ?> data;
+    private final Version version;
+
+    protected AbstractTreeNode(final NormalizedNode<?, ?> data, final Version version) {
+        this.data = Preconditions.checkNotNull(data);
+        this.version = Preconditions.checkNotNull(version);
+    }
+
+    @Override
+    public PathArgument getIdentifier() {
+        return data.getIdentifier();
+    }
+
+    @Override
+    public final Version getVersion() {
+        return version;
+    }
+
+    @Override
+    public final NormalizedNode<?, ?> getData() {
+        return data;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java
new file mode 100644 (file)
index 0000000..8f74f60
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * A TreeNode capable of holding child nodes. The fact that any of the children
+ * changed is tracked by the subtree version.
+ */
+final class ContainerNode extends AbstractTreeNode {
+    private final Map<PathArgument, TreeNode> children;
+    private final Version subtreeVersion;
+
+    protected ContainerNode(final NormalizedNode<?, ?> data, final Version version,
+            final Map<PathArgument, TreeNode> children, final Version subtreeVersion) {
+        super(data, version);
+        this.children = Preconditions.checkNotNull(children);
+        this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+    }
+
+    @Override
+    public Version getSubtreeVersion() {
+        return subtreeVersion;
+    }
+
+    @Override
+    public Optional<TreeNode> getChild(final PathArgument key) {
+        return Optional.fromNullable(children.get(key));
+    }
+
+    @Override
+    public MutableTreeNode mutable() {
+        return new Mutable(this);
+    }
+
+    private static final class Mutable implements MutableTreeNode {
+        private final Map<PathArgument, TreeNode> children;
+        private final Version version;
+        private NormalizedNode<?, ?> data;
+        private Version subtreeVersion;
+
+        private Mutable(final ContainerNode parent) {
+            this.data = parent.getData();
+            this.children = new HashMap<>(parent.children);
+            this.subtreeVersion = parent.getSubtreeVersion();
+            this.version = parent.getVersion();
+        }
+
+        @Override
+        public Optional<TreeNode> getChild(final PathArgument child) {
+            return Optional.fromNullable(children.get(child));
+        }
+
+        @Override
+        public void setSubtreeVersion(final Version subtreeVersion) {
+            this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+        }
+
+        @Override
+        public void addChild(final TreeNode child) {
+            children.put(child.getIdentifier(), child);
+        }
+
+        @Override
+        public void removeChild(final PathArgument id) {
+            children.remove(id);
+        }
+
+        @Override
+        public TreeNode seal() {
+            final Map<PathArgument, TreeNode> realChildren;
+
+            if (children.isEmpty()) {
+                realChildren = Collections.emptyMap();
+            } else {
+                realChildren = children;
+            }
+
+            return new ContainerNode(data, version, realChildren, subtreeVersion);
+        }
+
+        @Override
+        public void setData(final NormalizedNode<?, ?> data) {
+            this.data = Preconditions.checkNotNull(data);
+        }
+    }
+
+    private static ContainerNode create(final Version version, final NormalizedNode<?, ?> data,
+            final Iterable<NormalizedNode<?, ?>> children) {
+        final Map<PathArgument, TreeNode> map = new HashMap<>();
+
+        for (NormalizedNode<?, ?> child : children) {
+            map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version));
+        }
+
+        return new ContainerNode(data, version, map, version);
+    }
+
+    public static ContainerNode create(final Version version, final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
+        return create(version, container, container.getValue());
+    }
+
+    public static ContainerNode create(final Version version, final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
+        return create(version, container, container.getValue());
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java
new file mode 100644 (file)
index 0000000..dd3672c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface MutableTreeNode extends StoreTreeNode<TreeNode> {
+    void setData(NormalizedNode<?, ?> data);
+    void setSubtreeVersion(Version subtreeVersion);
+    void addChild(TreeNode child);
+    void removeChild(PathArgument id);
+    TreeNode seal();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java
new file mode 100644 (file)
index 0000000..b0beb81
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/*
+ * A very basic data tree node. It has a version (when it was last modified),
+ * a subtree version (when any of its children were modified) and some read-only
+ * data.
+ */
+public interface TreeNode extends Identifiable<PathArgument>, StoreTreeNode<TreeNode> {
+    /**
+     * Get the data node version.
+     *
+     * @return Current data node version.
+     */
+    Version getVersion();
+
+    /**
+     * Get the subtree version.
+     *
+     * @return Current subtree version.
+     */
+    Version getSubtreeVersion();
+
+    /**
+     * Get a read-only view of the underlying data.
+     *
+     * @return Unmodifiable view of the underlying data.
+     */
+    NormalizedNode<?, ?> getData();
+
+    /**
+     * Get a mutable, isolated copy of the node.
+     *
+     * @return Mutable copy
+     */
+    MutableTreeNode mutable();
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java
new file mode 100644 (file)
index 0000000..c5d174c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
+
+public final class TreeNodeFactory {
+    private TreeNodeFactory() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
+    /**
+     * Create a new AbstractTreeNode from a data node, descending recursively as needed.
+     * This method should only ever be used for new data.
+     *
+     * @param data data node
+     * @param version data node version
+     * @return new AbstractTreeNode instance, covering the data tree provided
+     */
+    public static final TreeNode createTreeNode(final NormalizedNode<?, ?> data, final Version version) {
+        if (data instanceof NormalizedNodeContainer<?, ?, ?>) {
+            @SuppressWarnings("unchecked")
+            NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
+            return ContainerNode.create(version, container);
+
+        }
+        if (data instanceof OrderedNodeContainer<?>) {
+            @SuppressWarnings("unchecked")
+            OrderedNodeContainer<NormalizedNode<?, ?>> container = (OrderedNodeContainer<NormalizedNode<?, ?>>) data;
+            return ContainerNode.create(version, container);
+        }
+
+        return new ValueNode(data, version);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java
new file mode 100644 (file)
index 0000000..7194faa
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+final class ValueNode extends AbstractTreeNode {
+    private static final Logger LOG = LoggerFactory.getLogger(ValueNode.class);
+
+    protected ValueNode(final NormalizedNode<?, ?> data, final Version version) {
+        super(data, version);
+    }
+
+    @Override
+    public Optional<TreeNode> getChild(final PathArgument childId) {
+        LOG.warn("Attempted to access child {} of value-node {}", childId, this);
+        return Optional.absent();
+    }
+
+    @Override
+    public Version getSubtreeVersion() {
+        return getVersion();
+    }
+
+    @Override
+    public MutableTreeNode mutable() {
+        /**
+         * Value nodes can only we read/written/delete, which does a straight
+         * replace. That means they don't haver need to be made mutable.
+         */
+        throw new UnsupportedOperationException(String.format("Attempted to mutate value-node %s", this));
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/Version.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/Version.java
new file mode 100644 (file)
index 0000000..09a35d3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi;
+
+/**
+ * The concept of a version, either node version, or a subtree version. The
+ * only interface contract this class has is that no two versions are the
+ * same.
+ */
+public final class Version {
+    private Version() {
+
+    }
+
+    /**
+     * Create a new version, distinct from any other version.
+     *
+     * @return a new version.
+     */
+    public Version next() {
+        return new Version();
+    }
+
+    /**
+     * Create an initial version.
+     *
+     * @return a new version.
+     */
+    public static final Version initial() {
+        return new Version();
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.java
new file mode 100644 (file)
index 0000000..7f83435
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * 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.dom.broker;
+
+import java.util.Hashtable;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+public class BrokerConfigActivator implements AutoCloseable {
+
+    private static InstanceIdentifier ROOT = InstanceIdentifier.builder()
+            .toInstance();
+
+    private DataProviderService dataService;
+
+    private ServiceRegistration<DataBrokerService> dataReg = null;
+    private ServiceRegistration<DataProviderService> dataProviderReg = null;
+    private ServiceRegistration<MountService> mountReg = null;
+    private ServiceRegistration<MountProvisionService> mountProviderReg = null;
+    private SchemaService schemaService = null;
+    private ServiceRegistration<RpcProvisionRegistry> rpcProvisionRegistryReg = null;
+    private MountPointManagerImpl mountService = null;
+
+    private SchemaAwareDataStoreAdapter wrappedStore = null;
+
+    public void start(final BrokerImpl broker, final DataStore store,
+            final DOMDataBroker asyncBroker, final BundleContext context) {
+
+        final Hashtable<String, String> emptyProperties = new Hashtable<String, String>();
+        broker.setBundleContext(context);
+
+        final ServiceReference<SchemaService> serviceRef = context
+                .getServiceReference(SchemaService.class);
+        schemaService = context.<SchemaService> getService(serviceRef);
+
+        broker.setRouter(new SchemaAwareRpcBroker("/", SchemaContextProviders
+                .fromSchemaService(schemaService)));
+
+        if (asyncBroker == null) {
+            dataService = new DataBrokerImpl();
+            dataProviderReg = context.registerService(
+                    DataProviderService.class, dataService, emptyProperties);
+
+            wrappedStore = new SchemaAwareDataStoreAdapter();
+            wrappedStore.changeDelegate(store);
+            wrappedStore.setValidationEnabled(false);
+            context.registerService(SchemaServiceListener.class, wrappedStore,
+                    emptyProperties);
+
+            dataService.registerConfigurationReader(ROOT, wrappedStore);
+            dataService.registerCommitHandler(ROOT, wrappedStore);
+            dataService.registerOperationalReader(ROOT, wrappedStore);
+        } else {
+            BackwardsCompatibleDataBroker compatibleDataBroker = new BackwardsCompatibleDataBroker(
+                    asyncBroker);
+            context.registerService(SchemaServiceListener.class,
+                    compatibleDataBroker, emptyProperties);
+            dataService = compatibleDataBroker;
+        }
+
+        mountService = new MountPointManagerImpl();
+        dataReg = context.registerService(DataBrokerService.class, dataService,
+                emptyProperties);
+        mountReg = context.registerService(MountService.class, mountService,
+                emptyProperties);
+        mountProviderReg = context.registerService(MountProvisionService.class,
+                mountService, emptyProperties);
+
+        rpcProvisionRegistryReg = context
+                .registerService(RpcProvisionRegistry.class,
+                        broker.getRouter(), emptyProperties);
+    }
+
+    @Override
+    public void close() {
+
+        if (dataReg != null) {
+            dataReg.unregister();
+            dataReg = null;
+        }
+        if (dataProviderReg != null) {
+            dataProviderReg.unregister();
+            dataProviderReg = null;
+        }
+        if (mountReg != null) {
+            mountReg.unregister();
+            mountReg = null;
+        }
+        if (mountProviderReg != null) {
+            mountProviderReg.unregister();
+            mountProviderReg = null;
+        }
+        if (rpcProvisionRegistryReg != null) {
+            rpcProvisionRegistryReg.unregister();
+            rpcProvisionRegistryReg = null;
+        }
+    }
+
+    /**
+     * @return the dataService
+     */
+    public DataProviderService getDataService() {
+        return dataService;
+    }
+
+    /**
+     * @param dataService
+     *            the dataService to set
+     */
+    public void setDataService(final DataProviderService dataService) {
+        this.dataService = dataService;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend
deleted file mode 100644 (file)
index 9cbf428..0000000
+++ /dev/null
@@ -1,99 +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.dom.broker
-
-import java.util.Hashtable
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.controller.sal.core.api.data.DataStore
-import org.opendaylight.controller.sal.core.api.model.SchemaService
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.controller.sal.core.api.mount.MountService
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.osgi.framework.BundleContext
-import org.osgi.framework.ServiceRegistration
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker
-import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl
-import com.google.common.util.concurrent.MoreExecutors
-import com.google.common.collect.ImmutableMap
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType
-import org.opendaylight.controller.sal.core.spi.data.DOMStore
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore
-import java.util.concurrent.Executors
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker
-
-class BrokerConfigActivator implements AutoCloseable {
-
-    private static val ROOT = InstanceIdentifier.builder().toInstance();
-
-    @Property
-    private var DataProviderService dataService;
-
-    private var ServiceRegistration<DataBrokerService> dataReg;
-    private var ServiceRegistration<DataProviderService> dataProviderReg;
-    private var ServiceRegistration<MountService> mountReg;
-    private var ServiceRegistration<MountProvisionService> mountProviderReg;
-    private var SchemaService schemaService;
-    private var ServiceRegistration<RpcProvisionRegistry> rpcProvisionRegistryReg;
-    private var MountPointManagerImpl mountService;
-
-    SchemaAwareDataStoreAdapter wrappedStore
-
-    public def void start(BrokerImpl broker, DataStore store, DOMDataBroker asyncBroker,BundleContext context) {
-        val emptyProperties = new Hashtable<String, String>();
-        broker.setBundleContext(context);
-
-        val serviceRef = context.getServiceReference(SchemaService);
-        schemaService = context.getService(serviceRef);
-
-        broker.setRouter(new SchemaAwareRpcBroker("/", SchemaContextProviders.fromSchemaService(schemaService)));
-        
-
-        if(asyncBroker == null) {
-            dataService = new DataBrokerImpl();
-            dataProviderReg = context.registerService(DataProviderService, dataService, emptyProperties);
-    
-            wrappedStore = new SchemaAwareDataStoreAdapter();
-            wrappedStore.changeDelegate(store);
-            wrappedStore.setValidationEnabled(false);
-            context.registerService(SchemaServiceListener, wrappedStore, emptyProperties)
-            
-            dataService.registerConfigurationReader(ROOT, wrappedStore);
-            dataService.registerCommitHandler(ROOT, wrappedStore);
-            dataService.registerOperationalReader(ROOT, wrappedStore);
-        } else {
-            val compatibleDataBroker = new BackwardsCompatibleDataBroker(asyncBroker);
-            context.registerService(SchemaServiceListener,compatibleDataBroker,emptyProperties);
-            dataService = compatibleDataBroker;
-        }
-        
-
-//        
-
-        mountService = new MountPointManagerImpl();
-        dataReg = context.registerService(DataBrokerService, dataService, emptyProperties);
-            mountReg = context.registerService(MountService, mountService, emptyProperties);
-        mountProviderReg = context.registerService(MountProvisionService, mountService, emptyProperties);
-
-        rpcProvisionRegistryReg = context.registerService(RpcProvisionRegistry, broker.getRouter(), emptyProperties);
-    }
-
-    override def close() {
-        dataReg?.unregister();
-        dataProviderReg?.unregister();
-        mountReg?.unregister();
-        mountProviderReg?.unregister();
-        rpcProvisionRegistryReg?.unregister();
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java
new file mode 100644 (file)
index 0000000..e4bd034
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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.dom.broker;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Consumer;
+import org.opendaylight.controller.sal.core.api.Provider;
+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.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
+
+public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
+    private final static Logger log = LoggerFactory.getLogger(BrokerImpl.class);
+
+    // Broker Generic Context
+    private final Set<ConsumerContextImpl> sessions = Collections
+            .synchronizedSet(new HashSet<ConsumerContextImpl>());
+    private final Set<ProviderContextImpl> providerSessions = Collections
+            .synchronizedSet(new HashSet<ProviderContextImpl>());
+
+    private BundleContext bundleContext = null;
+
+    private AutoCloseable deactivator = null;
+
+    private RpcRouter router = null;
+
+    @Override
+    public ConsumerSession registerConsumer(final Consumer consumer,
+            final BundleContext ctx) {
+        checkPredicates(consumer);
+        log.trace("Registering consumer {}", consumer);
+        final ConsumerContextImpl session = newSessionFor(consumer, ctx);
+        consumer.onSessionInitiated(session);
+        sessions.add(session);
+        return session;
+    }
+
+    @Override
+    public ProviderSession registerProvider(final Provider provider,
+            final BundleContext ctx) {
+        checkPredicates(provider);
+        final ProviderContextImpl session = newSessionFor(provider, ctx);
+        provider.onSessionInitiated(session);
+        providerSessions.add(session);
+        return session;
+    }
+
+    protected Future<RpcResult<CompositeNode>> invokeRpcAsync(final QName rpc,
+            final CompositeNode input) {
+        return router.invokeRpc(rpc, input);
+    }
+
+    // Validation
+    private void checkPredicates(final Provider prov) {
+        Preconditions.checkNotNull(prov, "Provider should not be null.");
+        for (ProviderContextImpl session : providerSessions) {
+            if (prov.equals(session.getProvider()))
+                throw new IllegalStateException("Provider already registered");
+        }
+
+    }
+
+    private void checkPredicates(final Consumer cons) {
+        Preconditions.checkNotNull(cons, "Consumer should not be null.");
+        for (ConsumerContextImpl session : sessions) {
+            if (cons.equals(session.getConsumer()))
+                throw new IllegalStateException("Consumer already registered");
+        }
+    }
+
+    // Private Factory methods
+    private ConsumerContextImpl newSessionFor(final Consumer provider,
+            final BundleContext ctx) {
+        ConsumerContextImpl ret = new ConsumerContextImpl(provider, ctx);
+        ret.setBroker(this);
+        return ret;
+    }
+
+    private ProviderContextImpl newSessionFor(final Provider provider,
+            final BundleContext ctx) {
+        ProviderContextImpl ret = new ProviderContextImpl(provider, ctx);
+        ret.setBroker(this);
+        return ret;
+    }
+
+    protected void consumerSessionClosed(
+            final ConsumerContextImpl consumerContextImpl) {
+        sessions.remove(consumerContextImpl);
+        providerSessions.remove(consumerContextImpl);
+    }
+
+    @Override
+    public void close() throws Exception {
+        if (deactivator != null) {
+            deactivator.close();
+            deactivator = null;
+        }
+    }
+
+    @Override
+    public RpcRegistration addRpcImplementation(final QName rpcType,
+            final RpcImplementation implementation)
+            throws IllegalArgumentException {
+        return router.addRpcImplementation(rpcType, implementation);
+    }
+
+    @Override
+    public RoutedRpcRegistration addRoutedRpcImplementation(
+            final QName rpcType, final RpcImplementation implementation) {
+        return router.addRoutedRpcImplementation(rpcType, implementation);
+    }
+
+    @Override
+    public void setRoutedRpcDefaultDelegate(
+            final RoutedRpcDefaultImplementation defaultImplementation) {
+        router.setRoutedRpcDefaultDelegate(defaultImplementation);
+    }
+
+    @Override
+    public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
+            final RpcRegistrationListener listener) {
+        return router.addRpcRegistrationListener(listener);
+    }
+
+    @Override
+    public <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
+            final L listener) {
+        return router.registerRouteChangeListener(listener);
+    }
+
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        return router.getSupportedRpcs();
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(
+            final QName rpc, final CompositeNode input) {
+        return router.invokeRpc(rpc, input);
+    }
+
+    /**
+     * @return the bundleContext
+     */
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    /**
+     * @param bundleContext
+     *            the bundleContext to set
+     */
+    public void setBundleContext(final BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    /**
+     * @return the deactivator
+     */
+    public AutoCloseable getDeactivator() {
+        return deactivator;
+    }
+
+    /**
+     * @param deactivator
+     *            the deactivator to set
+     */
+    public void setDeactivator(final AutoCloseable deactivator) {
+        this.deactivator = deactivator;
+    }
+
+    /**
+     * @return the router
+     */
+    public RpcRouter getRouter() {
+        return router;
+    }
+
+    /**
+     * @param router
+     *            the router to set
+     */
+    public void setRouter(final RpcRouter router) {
+        this.router = router;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
deleted file mode 100644 (file)
index 0ed14c1..0000000
+++ /dev/null
@@ -1,140 +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.dom.broker;
-
-import com.google.common.util.concurrent.ListenableFuture
-import java.util.Collections
-import java.util.HashSet
-import java.util.Set
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener
-import org.opendaylight.controller.sal.core.api.Broker
-import org.opendaylight.controller.sal.core.api.Consumer
-import org.opendaylight.controller.sal.core.api.Provider
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.osgi.framework.BundleContext
-import org.slf4j.LoggerFactory
-import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.sal.core.api.RpcImplementation
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation
-
-public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
-    private static val log = LoggerFactory.getLogger(BrokerImpl);
-
-    // Broker Generic Context
-    private val Set<ConsumerContextImpl> sessions = Collections.synchronizedSet(new HashSet<ConsumerContextImpl>());
-    private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
-        new HashSet<ProviderContextImpl>());
-
-    @Property
-    private var BundleContext bundleContext;
-
-    @Property
-    private var AutoCloseable deactivator;
-
-    @Property
-    private var RpcRouter router;
-
-    override registerConsumer(Consumer consumer, BundleContext ctx) {
-        checkPredicates(consumer);
-        log.trace("Registering consumer " + consumer);
-        val session = newSessionFor(consumer, ctx);
-        consumer.onSessionInitiated(session);
-        sessions.add(session);
-        return session;
-    }
-
-    override registerProvider(Provider provider, BundleContext ctx) {
-        checkPredicates(provider);
-
-        val session = newSessionFor(provider, ctx);
-        provider.onSessionInitiated(session);
-        providerSessions.add(session);
-        return session;
-    }
-
-    protected def ListenableFuture<RpcResult<CompositeNode>> invokeRpcAsync(QName rpc, CompositeNode input) {
-        return router.invokeRpc(rpc, input);
-    }
-
-    // Validation
-    private def void checkPredicates(Provider prov) {
-        if (prov == null)
-            throw new IllegalArgumentException("Provider should not be null.");
-        for (ProviderContextImpl session : providerSessions) {
-            if (prov.equals(session.getProvider()))
-                throw new IllegalStateException("Provider already registered");
-        }
-
-    }
-
-    private def void checkPredicates(Consumer cons) {
-        if (cons == null)
-            throw new IllegalArgumentException("Consumer should not be null.");
-        for (ConsumerContextImpl session : sessions) {
-            if (cons.equals(session.getConsumer()))
-                throw new IllegalStateException("Consumer already registered");
-        }
-    }
-
-    // Private Factory methods
-    private def ConsumerContextImpl newSessionFor(Consumer provider, BundleContext ctx) {
-        val ret = new ConsumerContextImpl(provider, ctx);
-        ret.broker = this;
-        return ret;
-    }
-
-    private def ProviderContextImpl newSessionFor(Provider provider, BundleContext ctx) {
-        val ret = new ProviderContextImpl(provider, ctx);
-        ret.broker = this;
-        return ret;
-    }
-
-    protected def void consumerSessionClosed(ConsumerContextImpl consumerContextImpl) {
-        sessions.remove(consumerContextImpl);
-        providerSessions.remove(consumerContextImpl);
-    }
-
-    override close() throws Exception {
-        deactivator?.close();
-    }
-
-    override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
-        router.addRpcImplementation(rpcType,implementation);
-    }
-
-    override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
-        router.addRoutedRpcImplementation(rpcType,implementation);
-    }
-
-    override setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultImplementation) {
-        router.setRoutedRpcDefaultDelegate(defaultImplementation);
-    }
-
-    override addRpcRegistrationListener(RpcRegistrationListener listener) {
-        return router.addRpcRegistrationListener(listener);
-    }
-
-    override <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> registerRouteChangeListener(L listener) {
-        return router.registerRouteChangeListener(listener);
-    }
-
-    override getSupportedRpcs() {
-        return router.getSupportedRpcs();
-    }
-
-    override invokeRpc(QName rpc, CompositeNode input) {
-        return router.invokeRpc(rpc,input)
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.java
new file mode 100644 (file)
index 0000000..fa81bc9
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.util.Collection;
+import java.util.concurrent.Future;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Consumer;
+import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy;
+import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.MutableClassToInstanceMap;
+
+class ConsumerContextImpl implements ConsumerSession {
+
+    private final ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap
+            .create();
+    private final BundleContext context;
+    private final Consumer consumer;
+
+    private BrokerImpl broker = null;
+    @GuardedBy("this")
+    private boolean closed = false;
+
+    public ConsumerContextImpl(final Consumer consumer, final BundleContext ctx) {
+        this.consumer = consumer;
+        this.context = ctx;
+    }
+
+    @Override
+    public Future<RpcResult<CompositeNode>> rpc(final QName rpc,
+            final CompositeNode input) {
+        return broker.invokeRpcAsync(rpc, input);
+    }
+
+    @Override
+    public <T extends BrokerService> T getService(final Class<T> service) {
+        final T localProxy = instantiatedServices.getInstance(service);
+        if (localProxy != null) {
+            return localProxy;
+        }
+        final ServiceReference<T> serviceRef = context
+                .getServiceReference(service);
+        if (serviceRef == null) {
+            return null;
+        }
+        final T serviceImpl = context.getService(serviceRef);
+        final T ret = ProxyFactory.createProxy(serviceRef, serviceImpl);
+        if (ret != null) {
+            instantiatedServices.putInstance(service, ret);
+        }
+        return ret;
+    }
+
+    @Override
+    public void close() {
+        synchronized (this) {
+            if (closed) {
+                return;
+            }
+            this.closed = true;
+        }
+
+        Collection<BrokerService> toStop = instantiatedServices.values();
+        for (BrokerService brokerService : toStop) {
+            if (brokerService instanceof AbstractBrokerServiceProxy<?>) {
+                ((AbstractBrokerServiceProxy<?>) brokerService).close();
+            }
+        }
+        broker.consumerSessionClosed(this);
+    }
+
+    @Override
+    public synchronized boolean isClosed() {
+        return closed;
+    }
+
+    /**
+     * @return the broker
+     */
+    public BrokerImpl getBroker() {
+        return broker;
+    }
+
+    /**
+     * @param broker
+     *            the broker to set
+     */
+    public void setBroker(final BrokerImpl broker) {
+        this.broker = broker;
+    }
+
+    /**
+     * @return the _consumer
+     */
+    public Consumer getConsumer() {
+        return consumer;
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend
deleted file mode 100644 (file)
index 813f52b..0000000
+++ /dev/null
@@ -1,76 +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.dom.broker
-
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import org.opendaylight.controller.sal.core.api.BrokerService
-import org.opendaylight.controller.sal.core.api.Consumer
-import org.osgi.framework.BundleContext
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy
-import com.google.common.collect.ClassToInstanceMap
-import com.google.common.collect.MutableClassToInstanceMap
-import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory
-
-class ConsumerContextImpl implements ConsumerSession {
-
-    @Property
-    private val Consumer consumer;
-
-    @Property
-    private var BrokerImpl broker;
-
-    private val ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap.create();
-    private boolean closed = false;
-
-    private BundleContext context;
-
-    public new(Consumer consumer, BundleContext ctx) {
-        this._consumer = consumer;
-        this.context = ctx;
-    }
-
-    override rpc(QName rpc, CompositeNode input) {
-        return broker.invokeRpcAsync(rpc, input);
-    }
-
-    override <T extends BrokerService> T getService(Class<T> service) {
-        val localProxy = instantiatedServices.getInstance(service);
-        if(localProxy != null) {
-            return localProxy;
-        }
-        val serviceRef = context.getServiceReference(service);
-        if(serviceRef == null) {
-            return null;
-        }
-        val serviceImpl = context.getService(serviceRef);
-        
-        
-        val ret = ProxyFactory.createProxy(serviceRef,serviceImpl);
-        if(ret != null) {
-            instantiatedServices.putInstance(service, ret);
-        }
-        return ret;
-    }
-
-    override close() {
-        val toStop = instantiatedServices.values();
-        this.closed = true;
-        for (BrokerService brokerService : toStop) {
-            if(brokerService instanceof AbstractBrokerServiceProxy<?>) {
-                (brokerService as AutoCloseable).close();
-            } 
-        }
-        broker.consumerSessionClosed(this);
-    }
-
-    override isClosed() {
-        return closed;
-    }
-}
index dab8fd5cd10bb71f1d9f9df480b3ec509276cd62..430963a884b4fbaa71a7c3c12d5df9356058be0c 100644 (file)
@@ -10,7 +10,10 @@ package org.opendaylight.controller.sal.dom.broker;
 import static com.google.common.base.Preconditions.checkState;
 
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
@@ -33,54 +36,34 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
 
-public class GlobalBundleScanningSchemaServiceImpl implements //
-        SchemaContextProvider, //
-        SchemaService, //
-        ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, //
-        AutoCloseable {
-    private static final Logger logger = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class);
-
-    private ListenerRegistry<SchemaServiceListener> listeners;
-
-    private BundleContext context;
-    private final BundleScanner scanner = new BundleScanner();
-
-    private BundleTracker<ImmutableSet<Registration<URL>>> bundleTracker;
+public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvider, SchemaService, ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class);
 
+    private final ListenerRegistry<SchemaServiceListener> listeners = new ListenerRegistry<>();
     private final URLSchemaContextResolver contextResolver = new URLSchemaContextResolver();
+    private final BundleScanner scanner = new BundleScanner();
+    private final BundleContext context;
 
     private ServiceTracker<SchemaServiceListener, SchemaServiceListener> listenerTracker;
-
+    private BundleTracker<Iterable<Registration<URL>>> bundleTracker;
     private boolean starting = true;
 
-    public ListenerRegistry<SchemaServiceListener> getListeners() {
-        return listeners;
-    }
-
-    public void setListeners(final ListenerRegistry<SchemaServiceListener> listeners) {
-        this.listeners = listeners;
+    public GlobalBundleScanningSchemaServiceImpl(final BundleContext context) {
+        this.context = Preconditions.checkNotNull(context);
     }
 
     public BundleContext getContext() {
         return context;
     }
 
-    public void setContext(final BundleContext context) {
-        this.context = context;
-    }
-
     public void start() {
         checkState(context != null);
-        if (listeners == null) {
-            listeners = new ListenerRegistry<>();
-        }
 
         listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, GlobalBundleScanningSchemaServiceImpl.this);
-        bundleTracker = new BundleTracker<ImmutableSet<Registration<URL>>>(context, BundleEvent.RESOLVED
-                        | BundleEvent.UNRESOLVED, scanner);
+        bundleTracker = new BundleTracker<>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
         bundleTracker.open();
         listenerTracker.open();
         starting = false;
@@ -139,7 +122,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements //
             try {
                 listener.getInstance().onGlobalContextUpdated(snapshot);
             } catch (Exception e) {
-                logger.error("Exception occured during invoking listener", e);
+                LOG.error("Exception occured during invoking listener", e);
             }
         }
         if (services != null) {
@@ -148,37 +131,47 @@ public class GlobalBundleScanningSchemaServiceImpl implements //
                 try {
                     listener.onGlobalContextUpdated(snapshot);
                 } catch (Exception e) {
-                    logger.error("Exception occured during invoking listener", e);
+                    LOG.error("Exception occured during invoking listener {}", listener, e);
                 }
             }
         }
     }
 
-    private class BundleScanner implements BundleTrackerCustomizer<ImmutableSet<Registration<URL>>> {
+    private class BundleScanner implements BundleTrackerCustomizer<Iterable<Registration<URL>>> {
         @Override
-        public ImmutableSet<Registration<URL>> addingBundle(final Bundle bundle, final BundleEvent event) {
+        public Iterable<Registration<URL>> addingBundle(final Bundle bundle, final BundleEvent event) {
 
             if (bundle.getBundleId() == 0) {
-                return ImmutableSet.of();
+                return Collections.emptyList();
             }
 
-            Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
-            Builder<Registration<URL>> builder = ImmutableSet.<Registration<URL>> builder();
-            while (enumeration != null && enumeration.hasMoreElements()) {
-                Registration<URL> reg = contextResolver.registerSource(enumeration.nextElement());
-                builder.add(reg);
+            final Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
+            if (enumeration == null) {
+                return Collections.emptyList();
             }
-            ImmutableSet<Registration<URL>> urls = builder.build();
-            if(urls.isEmpty()) {
-                return urls;
+
+            final List<Registration<URL>> urls = new ArrayList<>();
+            while (enumeration.hasMoreElements()) {
+                final URL u = enumeration.nextElement();
+                try {
+                    urls.add(contextResolver.registerSource(u));
+                    LOG.debug("Registered {}", u);
+                } catch (Exception e) {
+                    LOG.warn("Failed to register {}, ignoring it", e);
+                }
             }
-            tryToUpdateSchemaContext();
-            return urls;
+
+            if (!urls.isEmpty()) {
+                LOG.debug("Loaded {} new URLs, rebuilding schema context", urls.size());
+                tryToUpdateSchemaContext();
+            }
+
+            return ImmutableList.copyOf(urls);
         }
 
         @Override
-        public void modifiedBundle(final Bundle bundle, final BundleEvent event, final ImmutableSet<Registration<URL>> object) {
-            logger.debug("Modified bundle {} {} {}", bundle, event, object);
+        public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Iterable<Registration<URL>> object) {
+            LOG.debug("Modified bundle {} {} {}", bundle, event, object);
         }
 
         /**
@@ -188,12 +181,12 @@ public class GlobalBundleScanningSchemaServiceImpl implements //
          */
 
         @Override
-        public synchronized void removedBundle(final Bundle bundle, final BundleEvent event, final ImmutableSet<Registration<URL>> urls) {
+        public synchronized void removedBundle(final Bundle bundle, final BundleEvent event, final Iterable<Registration<URL>> urls) {
             for (Registration<URL> url : urls) {
                 try {
                     url.close();
                 } catch (Exception e) {
-                    e.printStackTrace();
+                    LOG.warn("Failed do unregister URL {}, proceeding", url, e);
                 }
             }
             tryToUpdateSchemaContext();
@@ -212,7 +205,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements //
     }
 
     public synchronized void tryToUpdateSchemaContext() {
-        if(starting ) {
+        if (starting) {
             return;
         }
         Optional<SchemaContext> schema = contextResolver.tryToUpdateSchemaContext();
index 263f0500fd1c280b470171352716c70b723c18c7..623bbdb19514ce15ffa0b9102959fbac77cb51d2 100644 (file)
@@ -135,7 +135,7 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
 
     @Override
     public ListenableFuture<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input) {
-        return null;
+        return rpcs.invokeRpc( type, input );
     }
 
     @Override
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.java
new file mode 100644 (file)
index 0000000..55a6ee7
--- /dev/null
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class MountPointManagerImpl implements MountProvisionService {
+
+    private final ListenerRegistry<MountProvisionListener> listeners =
+            ListenerRegistry.create();
+    private final ConcurrentMap<InstanceIdentifier, MountPointImpl> mounts =
+            new ConcurrentHashMap<>();
+    private DataProviderService dataBroker = null;
+
+    @Override
+    public MountProvisionInstance createMountPoint(final InstanceIdentifier path) {
+        checkState(!mounts.containsKey(path), "Mount already created");
+        final MountPointImpl mount = new MountPointImpl(path);
+        registerMountPoint(mount);
+        mounts.put(path, mount);
+        notifyMountCreated(path);
+        return mount;
+    }
+
+    public void notifyMountCreated(final InstanceIdentifier identifier) {
+        for (final ListenerRegistration<MountProvisionListener> listener : listeners
+                .getListeners()) {
+            listener.getInstance().onMountPointCreated(identifier);
+        }
+    }
+
+    public Object registerMountPoint(final MountPointImpl impl) {
+        // FIXME: Why is thie commented out? Either we need it or we don't
+        // dataBroker?.registerConfigurationReader(impl.mountPath,impl.readWrapper);
+        // dataBroker?.registerOperationalReader(impl.mountPath,impl.readWrapper);
+        return null;
+    }
+
+    @Override
+    public MountProvisionInstance createOrGetMountPoint(
+            final InstanceIdentifier path) {
+        final MountPointImpl mount = mounts.get(path);
+        if (mount == null) {
+            return createMountPoint(path);
+        }
+        return mount;
+    }
+
+    @Override
+    public MountProvisionInstance getMountPoint(final InstanceIdentifier path) {
+        return mounts.get(path);
+    }
+
+    /**
+     * @return the dataBroker
+     */
+    public DataProviderService getDataBroker() {
+        return dataBroker;
+    }
+
+    /**
+     * @param dataBroker
+     *            the dataBroker to set
+     */
+    public void setDataBroker(final DataProviderService dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    @Override
+    public ListenerRegistration<MountProvisionListener> registerProvisionListener(
+            final MountProvisionListener listener) {
+        return listeners.register(listener);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend
deleted file mode 100644 (file)
index 023f906..0000000
+++ /dev/null
@@ -1,66 +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.dom.broker
-
-
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import java.util.concurrent.ConcurrentMap
-import java.util.concurrent.ConcurrentHashMap
-import static com.google.common.base.Preconditions.*;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService.MountProvisionListener
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry
-
-class MountPointManagerImpl implements MountProvisionService {
-    
-    @Property
-    DataProviderService dataBroker;
-    
-    val ListenerRegistry<MountProvisionListener> listeners = ListenerRegistry.create()
-    
-    ConcurrentMap<InstanceIdentifier,MountPointImpl> mounts = new ConcurrentHashMap();
-    
-    override createMountPoint(InstanceIdentifier path) {
-        checkState(!mounts.containsKey(path),"Mount already created");
-        val mount = new MountPointImpl(path);
-        registerMountPoint(mount);
-        mounts.put(path,mount);
-        notifyMountCreated(path);
-        return mount;
-    }
-    
-    def notifyMountCreated(InstanceIdentifier identifier) {
-        for(listener : listeners) {
-            listener.instance.onMountPointCreated(identifier);
-        }
-    }
-    
-    def registerMountPoint(MountPointImpl impl) {
-        //dataBroker?.registerConfigurationReader(impl.mountPath,impl.readWrapper);
-        //dataBroker?.registerOperationalReader(impl.mountPath,impl.readWrapper);
-    }
-    
-    override registerProvisionListener(MountProvisionListener listener) {
-        listeners.register(listener)
-    }
-    
-    
-    override createOrGetMountPoint(InstanceIdentifier path) {
-        val mount = mounts.get(path);
-        if(mount === null) {
-            return createMountPoint(path)
-        }
-        return mount;
-    }
-    
-    
-    override getMountPoint(InstanceIdentifier path) {
-        mounts.get(path);
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.java
new file mode 100644 (file)
index 0000000..5e8c0e8
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.BundleContext;
+
+class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession {
+    private final Set<RpcRegistrationWrapper> registrations = new HashSet<>();
+    private final Provider provider;
+
+    public ProviderContextImpl(final Provider provider, final BundleContext ctx) {
+        super(null, ctx);
+        this.provider = provider;
+    }
+
+    @Override
+    public RpcRegistrationWrapper addRpcImplementation(final QName rpcType,
+            final RpcImplementation implementation) throws IllegalArgumentException {
+        final RpcRegistration origReg = getBroker().getRouter()
+                .addRpcImplementation(rpcType, implementation);
+        final RpcRegistrationWrapper newReg = new RpcRegistrationWrapper(
+                origReg);
+        registrations.add(newReg);
+        return newReg;
+    }
+
+    protected boolean removeRpcImplementation(final RpcRegistrationWrapper implToRemove) {
+        return registrations.remove(implToRemove);
+    }
+
+    @Override
+    public void close() {
+        for (final RpcRegistrationWrapper reg : registrations) {
+            reg.close();
+        }
+    }
+
+    @Override
+    public RoutedRpcRegistration addMountedRpcImplementation(
+            final QName rpcType, final RpcImplementation implementation) {
+        throw new UnsupportedOperationException(
+                "TODO: auto-generated method stub");
+    }
+
+    @Override
+    public RoutedRpcRegistration addRoutedRpcImplementation(
+            final QName rpcType, final RpcImplementation implementation) {
+        throw new UnsupportedOperationException(
+                "TODO: auto-generated method stub");
+    }
+
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        return getBroker().getRouter().getSupportedRpcs();
+    }
+
+    @Override
+    public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
+            final RpcRegistrationListener listener) {
+        return getBroker().getRouter().addRpcRegistrationListener(listener);
+    }
+
+    /**
+     * @return the provider
+     */
+    public Provider getProvider() {
+        return provider;
+    }
+
+    /**
+     * @param provider
+     *            the provider to set
+     */
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend
deleted file mode 100644 (file)
index e641ed1..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.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
-import org.opendaylight.controller.sal.core.api.Provider
-import org.opendaylight.controller.sal.core.api.RpcImplementation
-import org.opendaylight.yangtools.yang.common.QName
-import org.osgi.framework.BundleContext
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
-import org.opendaylight.yangtools.concepts.Registration
-
-import java.util.Set
-import java.util.HashSet
-
-class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession {
-
-    @Property
-    private val Provider provider;
-
-    private val Set<Registration<?>> registrations = new HashSet();
-
-    new(Provider provider, BundleContext ctx) {
-        super(null, ctx);
-        this._provider = provider;
-    }
-
-    override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
-        val origReg = broker.router.addRpcImplementation(rpcType, implementation);
-        val newReg = new RpcRegistrationWrapper(origReg);
-        registrations.add(newReg);
-        return newReg;
-    }
-
-    protected def removeRpcImplementation(RpcRegistrationWrapper implToRemove) throws IllegalArgumentException {
-        registrations.remove(implToRemove);
-    }
-    
-    override close() {
-        
-        for (reg : registrations) {
-            reg.close()
-        }
-        super.close
-    }
-
-    override addMountedRpcImplementation(QName rpcType, RpcImplementation implementation) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-
-    override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-
-    override getSupportedRpcs() {
-        broker.router.supportedRpcs;
-    }
-
-    override addRpcRegistrationListener(RpcRegistrationListener listener) {
-        broker.router.addRpcRegistrationListener(listener);
-    }
-}
-
-class RpcRegistrationWrapper implements RpcRegistration {
-
-
-    @Property
-    val RpcRegistration delegate
-
-    new(RpcRegistration delegate) {
-        _delegate = delegate
-    }
-
-    override getInstance() {
-        delegate.instance
-    }
-
-    override close() {
-        delegate.close
-    }
-
-    override getType() {
-        delegate.type
-    }
-}
-
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/RpcRegistrationWrapper.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/RpcRegistrationWrapper.java
new file mode 100644 (file)
index 0000000..db6c72e
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker;
+
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import com.google.common.base.Preconditions;
+
+public class RpcRegistrationWrapper implements RpcRegistration {
+
+    private final RpcRegistration delegate;
+
+    public RpcRegistrationWrapper(final RpcRegistration delegate) {
+        this.delegate = Preconditions.checkNotNull(delegate);
+    }
+
+    @Override
+    public RpcImplementation getInstance() {
+        return delegate.getInstance();
+    }
+
+    @Override
+    public void close() {
+        delegate.close();
+    }
+
+    @Override
+    public QName getType() {
+        return delegate.getType();
+    }
+
+    /**
+     * @return the delegate
+     */
+    public RpcRegistration getDelegate() {
+        return delegate;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.java
new file mode 100644 (file)
index 0000000..53423f6
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter;
+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.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Iterables;
+
+public class DataReaderRouter extends
+AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
+    private final static Logger LOG = LoggerFactory
+            .getLogger(DataReaderRouter.class);
+    private final static URI NETCONF_NAMESPACE = URI
+            .create("urn:ietf:params:xml:ns:netconf:base:1.0");
+    private final static QName NETCONF_DATA = new QName(NETCONF_NAMESPACE,
+            "data");
+
+    @Override
+    protected CompositeNodeTOImpl merge(final InstanceIdentifier path,
+            final Iterable<CompositeNode> data) {
+        PathArgument pathArgument = Iterables.getLast(path.getPath(), null);
+        boolean empty = true;
+        QName name = (pathArgument == null ? null : pathArgument.getNodeType());
+        final ArrayList<Node<?>> nodes = new ArrayList<Node<?>>();
+        final HashMap<QName, SimpleNode<?>> keyNodes = new HashMap<QName, SimpleNode<?>>();
+        for (final CompositeNode dataBit : data) {
+            try {
+                if (pathArgument != null && dataBit != null) {
+                    empty = false;
+                    final Map<QName, SimpleNode<?>> keyNodesLocal = getKeyNodes(
+                            pathArgument, dataBit);
+                    nodes.addAll(this.childrenWithout(dataBit,
+                            keyNodesLocal.entrySet()));
+                } else if (dataBit != null) {
+                    empty = false;
+                    nodes.addAll(dataBit.getValue());
+                }
+            } catch (IllegalStateException e) {
+                LOG.error("BUG: Readed data for path {} was invalid", path, e);
+            }
+        }
+        if (empty) {
+            return null;
+        }
+        /**
+         * Reading from Root
+         *
+         */
+        if (pathArgument == null) {
+            return new CompositeNodeTOImpl(NETCONF_DATA, null, nodes);
+        }
+        final ArrayList<Node<?>> finalNodes = new ArrayList<Node<?>>(
+                nodes.size() + keyNodes.size());
+        finalNodes.addAll(keyNodes.values());
+        finalNodes.addAll(nodes);
+        return new CompositeNodeTOImpl(name, null, finalNodes);
+    }
+
+    protected Map<QName, SimpleNode<?>> _getKeyNodes(
+            final PathArgument argument, final CompositeNode node) {
+        return Collections.emptyMap();
+    }
+
+    protected Map<QName, SimpleNode<?>> _getKeyNodes(
+            final NodeIdentifierWithPredicates argument,
+            final CompositeNode node) {
+        final HashMap<QName, SimpleNode<?>> ret = new HashMap<QName, SimpleNode<?>>();
+        for (final Entry<QName, Object> keyValue : argument.getKeyValues()
+                .entrySet()) {
+            final List<SimpleNode<?>> simpleNode = node
+                    .getSimpleNodesByName(keyValue.getKey());
+            if (simpleNode != null && !simpleNode.isEmpty()) {
+                checkState(
+                        simpleNode.size() <= 1,
+                        "Only one simple node for key $s is allowed in node $s",
+                        keyValue.getKey(), node);
+                checkState(
+                        simpleNode.get(0).getValue() == keyValue.getValue(),
+                        "Key node must equal to instance identifier value in node $s",
+                        node);
+                ret.put(keyValue.getKey(), simpleNode.get(0));
+            }
+            final List<CompositeNode> compositeNode = node
+                    .getCompositesByName(keyValue.getKey());
+            checkState(compositeNode == null || compositeNode.isEmpty(),
+                    "Key node must be Simple Node, not composite node.");
+        }
+        return ret;
+    }
+
+    public Map<QName, SimpleNode<?>> getKeyNodes(
+            final InstanceIdentifier.PathArgument argument,
+            final CompositeNode node) {
+        if (argument instanceof InstanceIdentifier.NodeIdentifierWithPredicates) {
+            return _getKeyNodes(
+                    (InstanceIdentifier.NodeIdentifierWithPredicates) argument,
+                    node);
+        } else if (argument != null) {
+            return _getKeyNodes(argument, node);
+        } else {
+            throw new IllegalArgumentException("Unhandled parameter types: "
+                    + Arrays.<Object> asList(argument, node).toString());
+        }
+    }
+
+    private Collection<? extends Node<?>> childrenWithout(
+            final CompositeNode node,
+            final Set<Entry<QName, SimpleNode<?>>> entries) {
+        if (entries.isEmpty()) {
+            return node.getValue();
+        }
+        final List<Node<?>> filteredNodes = new ArrayList<Node<?>>();
+        for (final Node<?> scannedNode : node.getValue()) {
+            if (!entries.contains(scannedNode.getNodeType())) {
+                filteredNodes.add(scannedNode);
+            }
+        }
+        return filteredNodes;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend
deleted file mode 100644 (file)
index 95d0018..0000000
+++ /dev/null
@@ -1,106 +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.dom.broker.impl
-
-import java.net.URI
-import java.util.ArrayList
-import java.util.Collection
-import java.util.Collections
-import java.util.HashMap
-import java.util.Map
-import java.util.Map.Entry
-import java.util.Set
-import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
-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.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.api.SimpleNode
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.slf4j.LoggerFactory
-
-import static com.google.common.base.Preconditions.*
-
-class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
-    private static val LOG = LoggerFactory.getLogger(DataReaderRouter);
-    private static val NETCONF_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
-    private static val NETCONF_DATA = new QName(NETCONF_NAMESPACE,"data");
-
-    override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
-        val pathArgument = path.path.last;
-        var empty = true;
-        var name = pathArgument?.nodeType;
-        val nodes = new ArrayList<Node<?>>();
-        val keyNodes = new HashMap<QName, SimpleNode<?>>();
-        for(dataBit : data) {
-            try {
-                if(pathArgument != null && dataBit != null) {
-                    empty = false;
-                    val keyNodesLocal = getKeyNodes(pathArgument,dataBit);
-                    nodes.addAll(dataBit.childrenWithout(keyNodesLocal.entrySet));
-                } else if (dataBit != null) {
-                    empty = false;
-                    nodes.addAll(dataBit.children)
-                }
-            }   catch (IllegalStateException e) {
-                LOG.error("BUG: Readed data for path {} was invalid",path,e);
-            }
-        }
-        if(empty) {
-            return null;
-        }
-        /**
-         * Reading from Root
-         * 
-         */
-        if(pathArgument == null) {
-            return new CompositeNodeTOImpl(NETCONF_DATA,null,nodes);
-        }
-        val finalNodes = new ArrayList<Node<?>>();
-        finalNodes.addAll(keyNodes.values);
-        finalNodes.addAll(nodes);
-        return new CompositeNodeTOImpl(name,null,finalNodes);
-    }
-    
-    
-    
-    dispatch def Map<QName, SimpleNode<?>> getKeyNodes(PathArgument argument, CompositeNode node) {
-        return Collections.emptyMap();
-    }
-    
-    dispatch def getKeyNodes(NodeIdentifierWithPredicates argument, CompositeNode node) {
-        val ret = new HashMap<QName, SimpleNode<?>>();
-        for (keyValue : argument.keyValues.entrySet) {
-            val simpleNode = node.getSimpleNodesByName(keyValue.key);
-            if(simpleNode !== null && !simpleNode.empty) {
-                checkState(simpleNode.size <= 1,"Only one simple node for key $s is allowed in node $s",keyValue.key,node);
-                checkState(simpleNode.get(0).value == keyValue.value,"Key node must equal to instance identifier value in node $s",node);
-                ret.put(keyValue.key,simpleNode.get(0));
-            }
-            val compositeNode = node.getCompositesByName(keyValue.key);
-            checkState(compositeNode === null || compositeNode.empty,"Key node must be Simple Node, not composite node.");
-        }
-        return ret;
-    }
-    
-    def Collection<? extends Node<?>> childrenWithout(CompositeNode node, Set<Entry<QName, SimpleNode<?>>> entries) {
-        if(entries.empty) {
-            return node.children;
-        }
-        val filteredNodes = new ArrayList<Node<?>>();
-        for(scannedNode : node.children) {
-            if(!entries.contains(scannedNode.nodeType)) {
-                filteredNodes.add(scannedNode);
-            }
-        }
-        return filteredNodes;
-    }
-    
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.java
new file mode 100644 (file)
index 0000000..50dfbe8
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class HashMapDataStore implements DataStore, AutoCloseable {
+    private static final Logger LOG = LoggerFactory
+            .getLogger(HashMapDataStore.class);
+
+    private final Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap<InstanceIdentifier, CompositeNode>();
+    private final Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap<InstanceIdentifier, CompositeNode>();
+
+    @Override
+    public boolean containsConfigurationPath(final InstanceIdentifier path) {
+        return configuration.containsKey(path);
+    }
+
+    @Override
+    public boolean containsOperationalPath(final InstanceIdentifier path) {
+        return operational.containsKey(path);
+    }
+
+    @Override
+    public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
+        return configuration.keySet();
+    }
+
+    @Override
+    public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
+        return operational.keySet();
+    }
+
+    @Override
+    public CompositeNode readConfigurationData(final InstanceIdentifier path) {
+        LOG.trace("Reading configuration path {}", path);
+        return configuration.get(path);
+    }
+
+    @Override
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        LOG.trace("Reading operational path {}", path);
+        return operational.get(path);
+    }
+
+    @Override
+    public DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
+            final DataModification<InstanceIdentifier, CompositeNode> modification) {
+        return new HashMapDataStoreTransaction(modification, this);
+    }
+
+    public RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
+        return Rpcs.<Void> getRpcResult(true, null,
+                Collections.<RpcError> emptySet());
+    }
+
+    public RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
+        final DataModification<InstanceIdentifier, CompositeNode> modification = transaction
+                .getModification();
+        for (final InstanceIdentifier removal : modification
+                .getRemovedConfigurationData()) {
+            LOG.trace("Removing configuration path {}", removal);
+            remove(configuration, removal);
+        }
+        for (final InstanceIdentifier removal : modification
+                .getRemovedOperationalData()) {
+            LOG.trace("Removing operational path {}", removal);
+            remove(operational, removal);
+        }
+        if (LOG.isTraceEnabled()) {
+            for (final InstanceIdentifier a : modification
+                    .getUpdatedConfigurationData().keySet()) {
+                LOG.trace("Adding configuration path {}", a);
+            }
+            for (final InstanceIdentifier a : modification
+                    .getUpdatedOperationalData().keySet()) {
+                LOG.trace("Adding operational path {}", a);
+            }
+        }
+        configuration.putAll(modification.getUpdatedConfigurationData());
+        operational.putAll(modification.getUpdatedOperationalData());
+
+        return Rpcs.<Void> getRpcResult(true, null,
+                Collections.<RpcError> emptySet());
+    }
+
+    public void remove(final Map<InstanceIdentifier, CompositeNode> map,
+            final InstanceIdentifier identifier) {
+        Set<InstanceIdentifier> affected = new HashSet<InstanceIdentifier>();
+        for (final InstanceIdentifier path : map.keySet()) {
+            if (identifier.contains(path)) {
+                affected.add(path);
+            }
+        }
+        for (final InstanceIdentifier pathToRemove : affected) {
+            LOG.trace("Removed path {}", pathToRemove);
+            map.remove(pathToRemove);
+        }
+    }
+
+    @Override
+    public void close() {
+        // NOOP
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend
deleted file mode 100644 (file)
index 12835cc..0000000
+++ /dev/null
@@ -1,141 +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.dom.broker.impl
-
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import org.opendaylight.yangtools.yang.common.RpcResult
-import java.util.Map
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.controller.sal.common.util.Rpcs
-import java.util.Collections
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.sal.core.api.data.DataStore
-import java.util.HashSet
-import org.slf4j.LoggerFactory
-import org.slf4j.Logger
-
-final class HashMapDataStore implements DataStore, AutoCloseable {
-    private val Logger LOG = LoggerFactory.getLogger(HashMapDataStore)
-
-    val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
-    val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
-    
-    
-    
-    override containsConfigurationPath(InstanceIdentifier path) {
-        return configuration.containsKey(path)
-    }
-    
-    override containsOperationalPath(InstanceIdentifier path) {
-        return operational.containsKey(path)
-    }
-    
-    override getStoredConfigurationPaths() {
-        configuration.keySet
-    }
-    
-    override getStoredOperationalPaths() {
-        operational.keySet
-    }
-
-    override readConfigurationData(InstanceIdentifier path) {
-        LOG.trace("Reading configuration path {}", path)
-        configuration.get(path);
-    }
-
-    override readOperationalData(InstanceIdentifier path) {
-        LOG.trace("Reading operational path {}", path)
-        operational.get(path);
-    }
-
-
-
-    override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
-        return new HashMapDataStoreTransaction(modification, this);
-    }
-
-    def RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
-        return Rpcs.getRpcResult(true, null, Collections.emptySet);
-    }
-
-    def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
-        val modification = transaction.modification;
-        for (removal : modification.removedConfigurationData) {
-            LOG.trace("Removing configuration path {}", removal)
-            remove(configuration,removal);
-        }
-        for (removal : modification.removedOperationalData) {
-            LOG.trace("Removing operational path {}", removal)
-            remove(operational,removal);
-        }
-        if (LOG.isTraceEnabled()) {
-            for (a : modification.updatedConfigurationData.keySet) {
-                LOG.trace("Adding configuration path {}", a)
-            }
-            for (a : modification.updatedOperationalData.keySet) {
-                LOG.trace("Adding operational path {}", a)
-            }
-        }
-        configuration.putAll(modification.updatedConfigurationData);
-        operational.putAll(modification.updatedOperationalData);
-
-        return Rpcs.getRpcResult(true, null, Collections.emptySet);
-    }
-    
-    def remove(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier identifier) {
-        val affected = new HashSet<InstanceIdentifier>();
-        for(path : map.keySet) {
-            if(identifier.contains(path)) {
-                affected.add(path);
-            }
-        }
-        for(pathToRemove : affected) {
-            LOG.trace("Removed path {}", pathToRemove)
-            map.remove(pathToRemove);
-        }
-        
-    }
-
-
-    override close()  {
-        // NOOP
-    }
-    
-}
-
-class HashMapDataStoreTransaction implements // 
-DataCommitTransaction<InstanceIdentifier, CompositeNode> {
-    @Property
-    val DataModification<InstanceIdentifier, CompositeNode> modification
-
-    @Property
-    val HashMapDataStore datastore;
-
-    new(
-        DataModification<InstanceIdentifier, CompositeNode> modify,
-        HashMapDataStore store
-    ) {
-        _modification = modify;
-        _datastore = store;
-    }
-
-    override finish() throws IllegalStateException {
-        datastore.finish(this);
-
-    }
-
-    override getModification() {
-        this._modification;
-    }
-
-    override rollback() throws IllegalStateException {
-        datastore.rollback(this);
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStoreTransaction.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStoreTransaction.java
new file mode 100644 (file)
index 0000000..bb66594
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class HashMapDataStoreTransaction implements
+        DataCommitTransaction<InstanceIdentifier, CompositeNode> {
+    private final DataModification<InstanceIdentifier, CompositeNode> modification;
+    private final HashMapDataStore datastore;
+
+    HashMapDataStoreTransaction(
+            final DataModification<InstanceIdentifier, CompositeNode> modify,
+            final HashMapDataStore store) {
+        modification = modify;
+        datastore = store;
+    }
+
+    @Override
+    public RpcResult<Void> finish() throws IllegalStateException {
+        return datastore.finish(this);
+    }
+
+    @Override
+    public DataModification<InstanceIdentifier, CompositeNode> getModification() {
+        return this.modification;
+    }
+
+    @Override
+    public RpcResult<Void> rollback() throws IllegalStateException {
+        return datastore.rollback(this);
+    }
+}
\ No newline at end of file
index d8315568bee86ea07ee00b86feddcb0801faaa8e..1a572d157dba9f8272140495b8eabf9669df11bc 100644 (file)
@@ -45,9 +45,9 @@ import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableSet;
 
 public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
-        DataStore, //
-        SchemaContextListener, //
-        AutoCloseable {
+DataStore, //
+SchemaContextListener, //
+AutoCloseable {
 
     private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class);
 
@@ -56,7 +56,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     private final DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
 
     @Override
-    public boolean containsConfigurationPath(InstanceIdentifier path) {
+    public boolean containsConfigurationPath(final InstanceIdentifier path) {
         try {
             getDelegateReadLock().lock();
             return getDelegate().containsConfigurationPath(path);
@@ -67,7 +67,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     }
 
     @Override
-    public boolean containsOperationalPath(InstanceIdentifier path) {
+    public boolean containsOperationalPath(final InstanceIdentifier path) {
         try {
             getDelegateReadLock().lock();
             return getDelegate().containsOperationalPath(path);
@@ -100,18 +100,18 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     }
 
     @Override
-    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+    public CompositeNode readConfigurationData(final InstanceIdentifier path) {
         return reader.readConfigurationData(path);
     }
 
     @Override
-    public CompositeNode readOperationalData(InstanceIdentifier path) {
+    public CompositeNode readOperationalData(final InstanceIdentifier path) {
         return reader.readOperationalData(path);
     }
 
     @Override
     public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
-            DataModification<InstanceIdentifier, CompositeNode> modification) {
+            final DataModification<InstanceIdentifier, CompositeNode> modification) {
         validateAgainstSchema(modification);
         NormalizedDataModification cleanedUp = prepareMergedTransaction(modification);
         cleanedUp.status = TransactionStatus.SUBMITED;
@@ -122,11 +122,11 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         return validationEnabled;
     }
 
-    public void setValidationEnabled(boolean validationEnabled) {
+    public void setValidationEnabled(final boolean validationEnabled) {
         this.validationEnabled = validationEnabled;
     }
 
-    private void validateAgainstSchema(DataModification<InstanceIdentifier, CompositeNode> modification) {
+    private void validateAgainstSchema(final DataModification<InstanceIdentifier, CompositeNode> modification) {
         if (!validationEnabled) {
             return;
         }
@@ -138,12 +138,12 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
     }
 
     @Override
-    protected void onDelegateChanged(DataStore oldDelegate, DataStore newDelegate) {
+    protected void onDelegateChanged(final DataStore oldDelegate, final DataStore newDelegate) {
         // NOOP
     }
 
     @Override
-    public void onGlobalContextUpdated(SchemaContext context) {
+    public void onGlobalContextUpdated(final SchemaContext context) {
         this.schema = context;
     }
 
@@ -152,8 +152,8 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         this.schema = null;
     }
 
-    protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified,
-            boolean config) {
+    protected CompositeNode mergeData(final InstanceIdentifier path, final CompositeNode stored, final CompositeNode modified,
+            final boolean config) {
         // long startTime = System.nanoTime();
         try {
             DataSchemaNode node = schemaNodeFor(path);
@@ -164,13 +164,13 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         }
     }
 
-    private DataSchemaNode schemaNodeFor(InstanceIdentifier path) {
+    private DataSchemaNode schemaNodeFor(final InstanceIdentifier path) {
         checkState(schema != null, "YANG Schema is not available");
         return YangSchemaUtils.getSchemaNode(schema, path);
     }
 
     private NormalizedDataModification prepareMergedTransaction(
-            DataModification<InstanceIdentifier, CompositeNode> original) {
+            final DataModification<InstanceIdentifier, CompositeNode> original) {
         NormalizedDataModification normalized = new NormalizedDataModification(original);
         LOG.trace("Transaction: {} Removed Configuration {}, Removed Operational {}", original.getIdentifier(),
                 original.getRemovedConfigurationData(), original.getRemovedConfigurationData());
@@ -194,7 +194,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         return normalized;
     }
 
-    private Iterable<InstanceIdentifier> getConfigurationSubpaths(InstanceIdentifier entry) {
+    private Iterable<InstanceIdentifier> getConfigurationSubpaths(final InstanceIdentifier entry) {
         // FIXME: This should be replaced by index
         Iterable<InstanceIdentifier> paths = getStoredConfigurationPaths();
 
@@ -202,15 +202,15 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     }
 
-    public Iterable<InstanceIdentifier> getOperationalSubpaths(InstanceIdentifier entry) {
+    public Iterable<InstanceIdentifier> getOperationalSubpaths(final InstanceIdentifier entry) {
         // FIXME: This should be indexed
         Iterable<InstanceIdentifier> paths = getStoredOperationalPaths();
 
         return getChildrenPaths(entry, paths);
     }
 
-    private static final Iterable<InstanceIdentifier> getChildrenPaths(InstanceIdentifier entry,
-            Iterable<InstanceIdentifier> paths) {
+    private static final Iterable<InstanceIdentifier> getChildrenPaths(final InstanceIdentifier entry,
+            final Iterable<InstanceIdentifier> paths) {
         ImmutableSet.Builder<InstanceIdentifier> children = ImmutableSet.builder();
         for (InstanceIdentifier potential : paths) {
             if (entry.contains(potential)) {
@@ -222,7 +222,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
         @Override
-        public int compare(Entry<InstanceIdentifier, CompositeNode> o1, Entry<InstanceIdentifier, CompositeNode> o2) {
+        public int compare(final Entry<InstanceIdentifier, CompositeNode> o1, final Entry<InstanceIdentifier, CompositeNode> o2) {
             InstanceIdentifier o1Key = o1.getKey();
             InstanceIdentifier o2Key = o2.getKey();
             return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size());
@@ -242,7 +242,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 CompositeNode original = getDelegate().readConfigurationData(path);
                 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
                 if (original != null) {
-                    childNodes.addAll(original.getChildren());
+                    childNodes.addAll(original.getValue());
                     qname = original.getNodeType();
                 } else {
                     qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
@@ -251,7 +251,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
                         .filter(new Predicate<InstanceIdentifier>() {
                             @Override
-                            public boolean apply(InstanceIdentifier input) {
+                            public boolean apply(final InstanceIdentifier input) {
                                 if (path.contains(input)) {
                                     int nesting = input.getPath().size() - path.getPath().size();
                                     if (nesting == 1) {
@@ -285,7 +285,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 CompositeNode original = getDelegate().readOperationalData(path);
                 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
                 if (original != null) {
-                    childNodes.addAll(original.getChildren());
+                    childNodes.addAll(original.getValue());
                     qname = original.getNodeType();
                 } else {
                     qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
@@ -294,7 +294,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
                 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
                         .filter(new Predicate<InstanceIdentifier>() {
                             @Override
-                            public boolean apply(InstanceIdentifier input) {
+                            public boolean apply(final InstanceIdentifier input) {
                                 if (path.contains(input)) {
                                     int nesting = input.getPath().size() - path.getPath().size();
                                     if (nesting == 1) {
@@ -326,7 +326,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         private final Object identifier;
         private TransactionStatus status;
 
-        public NormalizedDataModification(DataModification<InstanceIdentifier, CompositeNode> original) {
+        public NormalizedDataModification(final DataModification<InstanceIdentifier, CompositeNode> original) {
             super(getDelegate());
             identifier = original;
             status = TransactionStatus.NEW;
@@ -339,7 +339,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
          *
          * @param entry
          */
-        public void deepRemoveOperationalData(InstanceIdentifier entry) {
+        public void deepRemoveOperationalData(final InstanceIdentifier entry) {
             Iterable<InstanceIdentifier> paths = getOperationalSubpaths(entry);
             removeOperationalData(entry);
             for (InstanceIdentifier potential : paths) {
@@ -347,7 +347,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
 
-        public void deepRemoveConfigurationData(InstanceIdentifier entry) {
+        public void deepRemoveConfigurationData(final InstanceIdentifier entry) {
             Iterable<InstanceIdentifier> paths = getConfigurationSubpaths(entry);
             removeConfigurationData(entry);
             for (InstanceIdentifier potential : paths) {
@@ -355,11 +355,11 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
 
-        public void putDeepConfigurationData(InstanceIdentifier entryKey, CompositeNode entryData) {
+        public void putDeepConfigurationData(final InstanceIdentifier entryKey, final CompositeNode entryData) {
             this.putCompositeNodeData(entryKey, entryData, CONFIGURATIONAL_DATA_STORE_MARKER);
         }
 
-        public void putDeepOperationalData(InstanceIdentifier entryKey, CompositeNode entryData) {
+        public void putDeepOperationalData(final InstanceIdentifier entryKey, final CompositeNode entryData) {
             this.putCompositeNodeData(entryKey, entryData, OPERATIONAL_DATA_STORE_MARKER);
         }
 
@@ -379,26 +379,26 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         }
 
         @Override
-        protected CompositeNode mergeConfigurationData(InstanceIdentifier path, CompositeNode stored,
-                CompositeNode modified) {
+        protected CompositeNode mergeConfigurationData(final InstanceIdentifier path, final CompositeNode stored,
+                final CompositeNode modified) {
             return mergeData(path, stored, modified, true);
         }
 
         @Override
-        protected CompositeNode mergeOperationalData(InstanceIdentifier path, CompositeNode stored,
-                CompositeNode modified) {
+        protected CompositeNode mergeOperationalData(final InstanceIdentifier path, final CompositeNode stored,
+                final CompositeNode modified) {
             return mergeData(path, stored, modified, false);
         }
 
-        private void putData(InstanceIdentifier entryKey, CompositeNode entryData, String dataStoreIdentifier) {
+        private void putData(final InstanceIdentifier entryKey, final CompositeNode entryData, final String dataStoreIdentifier) {
             if (dataStoreIdentifier != null && entryKey != null && entryData != null) {
                 switch (dataStoreIdentifier) {
                 case (CONFIGURATIONAL_DATA_STORE_MARKER):
                     this.putConfigurationData(entryKey, entryData);
-                    break;
+                break;
                 case (OPERATIONAL_DATA_STORE_MARKER):
                     this.putOperationalData(entryKey, entryData);
-                    break;
+                break;
 
                 default:
                     LOG.error(dataStoreIdentifier + " is NOT valid DataStore switch marker");
@@ -407,11 +407,11 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
 
-        private void putCompositeNodeData(InstanceIdentifier entryKey, CompositeNode entryData,
-                String dataStoreIdentifier) {
+        private void putCompositeNodeData(final InstanceIdentifier entryKey, final CompositeNode entryData,
+                final String dataStoreIdentifier) {
             this.putData(entryKey, entryData, dataStoreIdentifier);
 
-            for (Node<?> child : entryData.getChildren()) {
+            for (Node<?> child : entryData.getValue()) {
                 InstanceIdentifier subEntryId = InstanceIdentifier.builder(entryKey).node(child.getNodeType())
                         .toInstance();
                 if (child instanceof CompositeNode) {
@@ -438,7 +438,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
 
-        private Map<QName, Object> getValuesFromListSchema(ListSchemaNode listSchema, CompositeNode entryData) {
+        private Map<QName, Object> getValuesFromListSchema(final ListSchemaNode listSchema, final CompositeNode entryData) {
             List<QName> keyDef = listSchema.getKeyDefinition();
             if (keyDef != null && !keyDef.isEmpty()) {
                 Map<QName, Object> map = new HashMap<QName, Object>();
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.java
new file mode 100644 (file)
index 0000000..c2d6add
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import java.util.Arrays;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.osgi.framework.ServiceReference;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+@SuppressWarnings("unchecked")
+public class ProxyFactory {
+
+    public static <T extends BrokerService> T createProxy(
+            final ServiceReference<T> serviceRef, final T service) {
+
+        Object _createProxyImpl = ProxyFactory.createProxyImpl(serviceRef,
+                service);
+        return ((T) _createProxyImpl);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> ref,
+            final DataBrokerService service) {
+
+        return new DataBrokerServiceProxy(
+                ((ServiceReference<DataBrokerService>) ref), service);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> ref,
+            final DataProviderService service) {
+
+        return new DataProviderServiceProxy(
+                ((ServiceReference<DataProviderService>) ref), service);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> ref,
+            final NotificationPublishService service) {
+
+        return new NotificationPublishServiceProxy(
+                ((ServiceReference<NotificationPublishService>) ref), service);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> ref,
+            final NotificationService service) {
+
+        return new NotificationServiceProxy(
+                ((ServiceReference<NotificationService>) ref), service);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> ref,
+            final MountProvisionService service) {
+
+        return new MountProviderServiceProxy(
+                ((ServiceReference<MountProvisionService>) ref), service);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> ref,
+            final SchemaService service) {
+
+        return new SchemaServiceProxy(((ServiceReference<SchemaService>) ref),
+                service);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> ref,
+            final RpcProvisionRegistry service) {
+
+        return new RpcProvisionRegistryProxy(
+                ((ServiceReference<RpcProvisionRegistry>) ref), service);
+    }
+
+    private static DOMDataBrokerProxy _createProxyImpl(
+            final ServiceReference<?> ref, final DOMDataBroker service) {
+
+        return new DOMDataBrokerProxy(((ServiceReference<DOMDataBroker>) ref),
+                service);
+    }
+
+    private static Object _createProxyImpl(final ServiceReference<?> reference,
+            final BrokerService service) {
+
+        throw new IllegalArgumentException("Not supported class: "
+                + service.getClass().getName());
+    }
+
+    private static Object createProxyImpl(final ServiceReference<?> ref,
+            final BrokerService service) {
+
+        if (service instanceof DOMDataBroker) {
+            return _createProxyImpl(ref, (DOMDataBroker) service);
+        } else if (service instanceof RpcProvisionRegistry) {
+            return _createProxyImpl(ref, (RpcProvisionRegistry) service);
+        } else if (service instanceof DataProviderService) {
+            return _createProxyImpl(ref, (DataProviderService) service);
+        } else if (service instanceof MountProvisionService) {
+            return _createProxyImpl(ref, (MountProvisionService) service);
+        } else if (service instanceof NotificationPublishService) {
+            return _createProxyImpl(ref, (NotificationPublishService) service);
+        } else if (service instanceof DataBrokerService) {
+            return _createProxyImpl(ref, (DataBrokerService) service);
+        } else if (service instanceof SchemaService) {
+            return _createProxyImpl(ref, (SchemaService) service);
+        } else if (service instanceof NotificationService) {
+            return _createProxyImpl(ref, (NotificationService) service);
+        } else if (service != null) {
+            return _createProxyImpl(ref, service);
+        } else {
+            throw new IllegalArgumentException("Unhandled parameter types: "
+                    + Arrays.<Object> asList(ref, service).toString());
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend
deleted file mode 100644 (file)
index d0afc3f..0000000
+++ /dev/null
@@ -1,66 +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.dom.broker.osgi
-
-import org.opendaylight.controller.sal.core.api.BrokerService
-import org.osgi.framework.ServiceReference
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService
-import org.opendaylight.controller.sal.core.api.notify.NotificationService
-import org.opendaylight.controller.sal.core.api.model.SchemaService
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker
-
-class ProxyFactory {
-
-    static def <T extends BrokerService> T createProxy(ServiceReference<T> serviceRef, T service) {
-        return createProxyImpl(serviceRef, service) as T;
-    }
-
-
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataBrokerService service) {
-        new DataBrokerServiceProxy(ref as ServiceReference<DataBrokerService>, service);
-    }
-
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataProviderService service) {
-        new DataProviderServiceProxy(ref as ServiceReference<DataProviderService>, service);
-    }
-    
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationPublishService service) {
-        new NotificationPublishServiceProxy(ref as ServiceReference<NotificationPublishService>, service);
-    }
-    
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationService service) {
-        new NotificationServiceProxy(ref as ServiceReference<NotificationService>, service);
-    }
-
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, MountProvisionService service) {
-        new MountProviderServiceProxy(ref as ServiceReference<MountProvisionService>, service);
-    }
-
-
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, SchemaService service) {
-        new SchemaServiceProxy(ref as ServiceReference<SchemaService>, service);
-    }
-
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, RpcProvisionRegistry service) {
-        new RpcProvisionRegistryProxy(ref as ServiceReference<RpcProvisionRegistry>, service);
-    }
-    
-    private static def dispatch createProxyImpl(ServiceReference<?> ref, DOMDataBroker service) {
-        new DOMDataBrokerProxy(ref as ServiceReference<DOMDataBroker>, service)
-    }
-    
-
-    private static def dispatch createProxyImpl(ServiceReference<?> reference, BrokerService service) {
-        throw new IllegalArgumentException("Not supported class");
-    }
-
-}
index 344b3f32763c2fcb9c45047ae7c4e34f0b6e087d..f893f96d18c59e94df9fe7961b8856b214a6f196 100644 (file)
@@ -17,20 +17,19 @@ import org.osgi.framework.ServiceRegistration;
 
 public class SchemaServiceActivator implements BundleActivator {
 
-    
+
     private ServiceRegistration<SchemaService> schemaServiceReg;
     private GlobalBundleScanningSchemaServiceImpl schemaService;
 
     @Override
-    public void start(BundleContext context) throws Exception {
-        schemaService = new GlobalBundleScanningSchemaServiceImpl();
-        schemaService.setContext(context);
+    public void start(final BundleContext context) {
+        schemaService = new GlobalBundleScanningSchemaServiceImpl(context);
         schemaService.start();
         schemaServiceReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String,String>());
     }
-    
+
     @Override
-    public void stop(BundleContext context) throws Exception {
+    public void stop(final BundleContext context) throws Exception {
         schemaServiceReg.unregister();
         schemaService.close();
     }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.java
new file mode 100644 (file)
index 0000000..0f8ce1d
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+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 com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+public class YangDataOperations {
+
+    public static CompositeNode merge(final DataSchemaNode schema,
+            final CompositeNode stored, final CompositeNode modified,
+            final boolean config) {
+        if (stored == null) {
+            return modified;
+        }
+
+        Preconditions.checkArgument(schema instanceof ListSchemaNode
+                || schema instanceof ContainerSchemaNode,
+                "Supplied node is not data node container.");
+
+        return YangDataOperations.mergeContainer((DataNodeContainer) schema,
+                stored, modified, config);
+    }
+
+    private static Iterable<? extends Node<?>> _mergeMultiple(
+            final LeafSchemaNode node, final List<Node<?>> original,
+            final List<Node<?>> modified, final boolean configurational) {
+        checkArgument(original.size() == 1);
+        checkArgument(modified.size() == 1);
+
+        return modified;
+    }
+
+    private static Iterable<? extends Node<?>> _mergeMultiple(
+            final LeafListSchemaNode node, final List<Node<?>> original,
+            final List<Node<?>> modified, final boolean configurational) {
+        return modified;
+    }
+
+    private static Iterable<? extends Node<?>> _mergeMultiple(
+            final ContainerSchemaNode node, final List<Node<?>> original,
+            final List<Node<?>> modified, final boolean configurational) {
+        checkArgument(original.size() == 1);
+        checkArgument(modified.size() == 1);
+        return Collections.singletonList(merge(node,
+                (CompositeNode) original.get(0),
+                (CompositeNode) modified.get(0), configurational));
+    }
+
+    private static Iterable<? extends Node<?>> _mergeMultiple(
+            final ListSchemaNode node, final List<Node<?>> original,
+            final List<Node<?>> modified, final boolean configurational) {
+
+        if (node.getKeyDefinition() == null
+                || node.getKeyDefinition().isEmpty()) {
+            return modified;
+        }
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final Map<Map<QName, Object>, CompositeNode> originalMap = YangDataUtils
+                .toIndexMap((List) original, node.getKeyDefinition());
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final Map<Map<QName, Object>, CompositeNode> modifiedMap = YangDataUtils
+                .toIndexMap((List) modified, node.getKeyDefinition());
+
+        final List<Node<?>> mergedNodes = new ArrayList<Node<?>>(
+                original.size() + modified.size());
+        for (final Map.Entry<Map<QName, Object>, CompositeNode> entry : modifiedMap
+                .entrySet()) {
+            final CompositeNode originalEntry = originalMap.get(entry.getKey());
+            if (originalEntry != null) {
+                originalMap.remove(entry.getKey());
+                mergedNodes.add(merge(node, originalEntry, entry.getValue(),
+                        configurational));
+            } else {
+                mergedNodes.add(entry.getValue());
+            }
+        }
+        mergedNodes.addAll(originalMap.values());
+        return mergedNodes;
+    }
+
+    private static Iterable<? extends Node<?>> mergeMultiple(
+            final DataSchemaNode node, final List<Node<?>> original,
+            final List<Node<?>> modified, final boolean configurational) {
+        if (node instanceof ContainerSchemaNode) {
+            return _mergeMultiple((ContainerSchemaNode) node, original,
+                    modified, configurational);
+        } else if (node instanceof LeafListSchemaNode) {
+            return _mergeMultiple((LeafListSchemaNode) node, original,
+                    modified, configurational);
+        } else if (node instanceof LeafSchemaNode) {
+            return _mergeMultiple((LeafSchemaNode) node, original, modified,
+                    configurational);
+        } else if (node instanceof ListSchemaNode) {
+            return _mergeMultiple((ListSchemaNode) node, original, modified,
+                    configurational);
+        } else {
+            throw new IllegalArgumentException("Unhandled parameter types: "
+                    + Arrays.<Object> asList(node, original, modified,
+                            configurational).toString());
+        }
+    }
+
+    private static CompositeNode mergeContainer(final DataNodeContainer schema,
+            final CompositeNode stored, final CompositeNode modified,
+            final boolean config) {
+        if (stored == null) {
+            return modified;
+        }
+        Preconditions.checkNotNull(stored);
+        Preconditions.checkNotNull(modified);
+        Preconditions.checkArgument(Objects.equals(stored.getNodeType(),
+                modified.getNodeType()));
+
+        final List<Node<?>> mergedChildNodes = new ArrayList<Node<?>>(stored
+                .getChildren().size() + modified.getChildren().size());
+        final Set<QName> toProcess = new HashSet<QName>(stored.keySet());
+        toProcess.addAll(modified.keySet());
+
+        for (QName qname : toProcess) {
+            final DataSchemaNode schemaChild = schema.getDataChildByName(qname);
+            final List<Node<?>> storedChildren = stored.get(qname);
+            final List<Node<?>> modifiedChildren = modified.get(qname);
+
+            if (modifiedChildren != null && !modifiedChildren.isEmpty()) {
+                if (storedChildren == null || storedChildren.isEmpty()
+                        || schemaChild == null) {
+                    mergedChildNodes.addAll(modifiedChildren);
+                } else {
+                    final Iterable<? extends Node<?>> _mergeMultiple = mergeMultiple(
+                            schemaChild, storedChildren, modifiedChildren,
+                            config);
+                    Iterables.addAll(mergedChildNodes, _mergeMultiple);
+                }
+            } else if (storedChildren != null && !storedChildren.isEmpty()) {
+                mergedChildNodes.addAll(storedChildren);
+            }
+        }
+        return new CompositeNodeTOImpl(stored.getNodeType(), null,
+                mergedChildNodes);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.xtend
deleted file mode 100644 (file)
index d80e405..0000000
+++ /dev/null
@@ -1,117 +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.dom.broker.util
-
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import static com.google.common.base.Preconditions.*;
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import java.util.ArrayList
-
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import java.util.List
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import java.util.Collections
-import java.util.HashSet
-import org.opendaylight.yangtools.yang.common.QName
-import static extension org.opendaylight.controller.sal.dom.broker.util.YangDataUtils.*;
-
-class YangDataOperations {
-
-    static def CompositeNode merge(DataSchemaNode schema, CompositeNode stored, CompositeNode modified, boolean config) {
-        if (stored === null) {
-            return modified;
-        }
-
-        if (schema instanceof ListSchemaNode || schema instanceof ContainerSchemaNode) {
-            return mergeContainer(schema as DataNodeContainer, stored, modified, config);
-        }
-        throw new IllegalArgumentException("Supplied node is not data node container.");
-    }
-
-    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
-        List<Node<?>> modified, boolean configurational) {
-        checkArgument(original.size === 1);
-        checkArgument(modified.size === 1);
-        
-        return modified;
-    }
-
-    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafListSchemaNode node,
-        List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
-        return modified;
-    }
-
-    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ContainerSchemaNode node,
-        List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
-        checkArgument(original.size === 1);
-        checkArgument(modified.size === 1);
-        return Collections.singletonList(
-            merge(node, original.get(0) as CompositeNode, modified.get(0) as CompositeNode, configurational));
-    }
-
-    private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ListSchemaNode node, List<Node<?>> original,
-        List<Node<?>> modified, boolean configurational) {
-        
-        if(node.keyDefinition === null || node.keyDefinition.empty) {
-            return modified;
-        }
-        val originalMap = (original as List).toIndexMap(node.keyDefinition);
-        val modifiedMap = (modified as List).toIndexMap(node.keyDefinition);
-        
-        val List<Node<?>> mergedNodes = new ArrayList(original.size + modified.size);
-        for(entry : modifiedMap.entrySet) {
-            val originalEntry = originalMap.get(entry.key);
-            if(originalEntry != null) {
-                originalMap.remove(entry.key);
-                mergedNodes.add(merge(node,originalEntry,entry.value,configurational));
-            } else {
-                mergedNodes.add(entry.value);
-            }
-        }
-        mergedNodes.addAll(originalMap.values);
-        return mergedNodes;
-    }
-
-    static private def CompositeNode mergeContainer(DataNodeContainer schema, CompositeNode stored,
-        CompositeNode modified, boolean config) {
-        if (stored == null) {
-            return modified;
-        }
-        checkNotNull(stored)
-        checkNotNull(modified)
-        checkArgument(stored.nodeType == modified.nodeType);
-
-        val mergedChildNodes = new ArrayList<Node<?>>(stored.children.size + modified.children.size);
-        
-        val toProcess = new HashSet<QName>(stored.keySet);
-        toProcess.addAll(modified.keySet);
-        
-        for (qname : toProcess) {
-            val schemaChild = schema.getDataChildByName(qname);
-            val storedChildren = stored.get(qname);
-            val modifiedChildren = modified.get(qname);
-
-            if (modifiedChildren !== null && !modifiedChildren.empty) {
-                if (storedChildren === null || storedChildren.empty || schemaChild === null) {
-                    mergedChildNodes.addAll(modifiedChildren);
-                } else {
-                    mergedChildNodes.addAll(mergeMultiple(schemaChild, storedChildren, modifiedChildren, config));
-                }
-            } else if (storedChildren !== null && !storedChildren.empty) {
-                mergedChildNodes.addAll(storedChildren);
-            }
-        }
-        return new CompositeNodeTOImpl(stored.nodeType, null, mergedChildNodes);
-    }
-
-}
@@ -1,4 +1,11 @@
-package org.opendaylight.controller.md.sal.dom.store.impl;
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -19,7 +26,11 @@ import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.ma
 
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -31,7 +42,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableCo
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 import com.google.common.base.Optional;
-import com.google.common.primitives.UnsignedLong;
 
 /**
  *
@@ -89,14 +99,16 @@ public class ModificationMetadataTreeTest {
                     .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_ONE_NAME)) //
                     .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME)) //
                     .build()) //
-            .build();
+                    .build();
 
     private SchemaContext schemaContext;
+    private ModificationApplyOperation applyOper;
 
     @Before
     public void prepare() {
         schemaContext = TestModel.createTestContext();
         assertNotNull("Schema context must not be null.", schemaContext);
+        applyOper = SchemaAwareApplyOperation.from(schemaContext);
     }
 
     /**
@@ -131,18 +143,16 @@ public class ModificationMetadataTreeTest {
                 .withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
                 .withChild(
                         mapNodeBuilder(OUTER_LIST_QNAME)
-                                .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
-                                .withChild(BAR_NODE).build()).build();
+                        .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
+                        .withChild(BAR_NODE).build()).build();
     }
 
     @Test
     public void basicReadWrites() {
-        MutableDataTree modificationTree = MutableDataTree.from(
-                DataAndMetadataSnapshot.builder() //
-                        .setMetadataTree(StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))) //
-                        .setSchemaContext(schemaContext) //
-                        .build(), new SchemaAwareApplyOperationRoot(schemaContext));
-        Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.read(OUTER_LIST_2_PATH);
+        DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
+                TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), applyOper),
+                new SchemaAwareApplyOperationRoot(schemaContext));
+        Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
         assertTrue(originalBarNode.isPresent());
         assertSame(BAR_NODE, originalBarNode.get());
 
@@ -151,22 +161,23 @@ public class ModificationMetadataTreeTest {
 
         // reads node to /outer-list/1/inner_list/two/value
         // and checks if node is already present
-        Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.read(TWO_TWO_VALUE_PATH);
+        Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.readNode(TWO_TWO_VALUE_PATH);
         assertTrue(barTwoCModified.isPresent());
         assertEquals(ImmutableNodes.leafNode(VALUE_QNAME, "test"), barTwoCModified.get());
 
         // delete node to /outer-list/1/inner_list/two/value
         modificationTree.delete(TWO_TWO_VALUE_PATH);
-        Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.read(TWO_TWO_VALUE_PATH);
+        Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.readNode(TWO_TWO_VALUE_PATH);
         assertFalse(barTwoCAfterDelete.isPresent());
     }
 
 
-    public MutableDataTree createEmptyModificationTree() {
+    public DataTreeModification createEmptyModificationTree() {
         /**
          * Creates empty Snapshot with associated schema context.
          */
-        DataAndMetadataSnapshot emptySnapshot = DataAndMetadataSnapshot.createEmpty(schemaContext);
+        DataTree t = InMemoryDataTreeFactory.getInstance().create();
+        t.setSchemaContext(schemaContext);
 
         /**
          *
@@ -174,15 +185,13 @@ public class ModificationMetadataTreeTest {
          * context.
          *
          */
-        MutableDataTree modificationTree = MutableDataTree.from(emptySnapshot, new SchemaAwareApplyOperationRoot(
-                schemaContext));
-        return modificationTree;
+        return t.takeSnapshot().newModification();
     }
 
     @Test
     public void createFromEmptyState() {
 
-        MutableDataTree modificationTree = createEmptyModificationTree();
+        DataTreeModification modificationTree = createEmptyModificationTree();
         /**
          * Writes empty container node to /test
          *
@@ -197,14 +206,14 @@ public class ModificationMetadataTreeTest {
         /**
          * Reads list node from /test/outer-list
          */
-        Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.read(OUTER_LIST_PATH);
+        Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.readNode(OUTER_LIST_PATH);
         assertTrue(potentialOuterList.isPresent());
 
         /**
          * Reads container node from /test and verifies that it contains test
          * node
          */
-        Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.read(TEST_PATH);
+        Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.readNode(TEST_PATH);
         ContainerNode containerTest = assertPresentAndType(potentialTest, ContainerNode.class);
 
         /**
@@ -219,23 +228,23 @@ public class ModificationMetadataTreeTest {
 
     @Test
     public void writeSubtreeReadChildren() {
-        MutableDataTree modificationTree = createEmptyModificationTree();
+        DataTreeModification modificationTree = createEmptyModificationTree();
         modificationTree.write(TEST_PATH, createTestContainer());
-        Optional<NormalizedNode<?, ?>> potential = modificationTree.read(TWO_TWO_PATH);
-        MapEntryNode node = assertPresentAndType(potential, MapEntryNode.class);
+        Optional<NormalizedNode<?, ?>> potential = modificationTree.readNode(TWO_TWO_PATH);
+        assertPresentAndType(potential, MapEntryNode.class);
     }
 
     @Test
     public void writeSubtreeDeleteChildren() {
-        MutableDataTree modificationTree = createEmptyModificationTree();
+        DataTreeModification modificationTree = createEmptyModificationTree();
         modificationTree.write(TEST_PATH, createTestContainer());
 
         // We verify data are present
-        Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.read(TWO_TWO_PATH);
-        MapEntryNode node = assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
+        Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.readNode(TWO_TWO_PATH);
+        assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
 
         modificationTree.delete(TWO_TWO_PATH);
-        Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.read(TWO_TWO_PATH);
+        Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.readNode(TWO_TWO_PATH);
         assertFalse(potentialAfterDelete.isPresent());
 
     }
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.md.sal.dom.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
 
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -14,7 +14,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableCo
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.DataNodeContainerModificationStrategy<ContainerSchemaNode> {
+public class SchemaAwareApplyOperationRoot extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
     private final SchemaContext context;
 
     public SchemaAwareApplyOperationRoot(final SchemaContext context) {
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 de3c18db699e3edb42ed1fd1b49e6b54a44db91a..1839de15975f381ebc8d32980050cfb16ace72ad 100644 (file)
@@ -17,18 +17,22 @@ import java.io.File;
 import java.io.InputStream;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.URI;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
 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.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
 import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
@@ -36,6 +40,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider;
 import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider;
 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
index 8a74b17ac46449c806f745c48e0892a59ec9374b..34cd9aa47b7f82702a797ddc4bea96ed34f28b7d 100644 (file)
@@ -35,7 +35,6 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifie
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,9 +51,9 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<In
     private final boolean candidateSupported;
     private final boolean rollbackSupported;
 
-    public NetconfDeviceTwoPhaseCommitTransaction(NetconfDevice device,
-            DataModification<InstanceIdentifier, CompositeNode> modification,
-            boolean candidateSupported, boolean rollbackOnErrorSupported) {
+    public NetconfDeviceTwoPhaseCommitTransaction(final NetconfDevice device,
+            final DataModification<InstanceIdentifier, CompositeNode> modification,
+            final boolean candidateSupported, final boolean rollbackOnErrorSupported) {
         this.device = Preconditions.checkNotNull(device);
         this.modification = Preconditions.checkNotNull(modification);
         this.candidateSupported = candidateSupported;
@@ -70,15 +69,15 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<In
         }
     }
 
-    private void sendMerge(InstanceIdentifier key, CompositeNode value) throws InterruptedException, ExecutionException {
+    private void sendMerge(final InstanceIdentifier key, final CompositeNode value) throws InterruptedException, ExecutionException {
         sendEditRpc(createEditStructure(key, Optional.<String>absent(), Optional.of(value)));
     }
 
-    private void sendDelete(InstanceIdentifier toDelete) throws InterruptedException, ExecutionException {
+    private void sendDelete(final InstanceIdentifier toDelete) throws InterruptedException, ExecutionException {
         sendEditRpc(createEditStructure(toDelete, Optional.of("delete"), Optional.<CompositeNode> absent()));
     }
 
-    private void sendEditRpc(CompositeNode editStructure) throws InterruptedException, ExecutionException {
+    private void sendEditRpc(final CompositeNode editStructure) throws InterruptedException, ExecutionException {
         CompositeNodeBuilder<ImmutableCompositeNode> builder = configurationRpcBuilder();
         builder.setQName(NETCONF_EDIT_CONFIG_QNAME);
         builder.add(editStructure);
@@ -108,8 +107,8 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<In
         return ret;
     }
 
-    private CompositeNode createEditStructure(InstanceIdentifier dataPath, Optional<String> operation,
-            Optional<CompositeNode> lastChildOverride) {
+    private CompositeNode createEditStructure(final InstanceIdentifier dataPath, final Optional<String> operation,
+            final Optional<CompositeNode> lastChildOverride) {
         List<PathArgument> path = dataPath.getPath();
         List<PathArgument> reversed = Lists.reverse(path);
         CompositeNode previous = null;
@@ -130,7 +129,7 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<In
                     builder.setAttribute(NETCONF_OPERATION_QNAME, operation.get());
                 }
                 if (lastChildOverride.isPresent()) {
-                    List<Node<?>> children = lastChildOverride.get().getChildren();
+                    List<Node<?>> children = lastChildOverride.get().getValue();
                     for(Node<?> child : children) {
                         if(!predicates.containsKey(child.getKey())) {
                             builder.add(child);
index f76ec28624e158a3cfa5ad8050c13647b82e2163..2b3a992fc1c3eebaa45a33220731b4c80d2a0181 100644 (file)
@@ -7,12 +7,6 @@
  */
 package org.opendaylight.controller.sal.connect.netconf;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -20,8 +14,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
+
 import javax.activation.UnsupportedDataTypeException;
 import javax.annotation.Nullable;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
@@ -41,11 +37,16 @@ import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
 public class NetconfMapping {
 
     public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
@@ -91,7 +92,7 @@ public class NetconfMapping {
 
     static AtomicInteger messageId = new AtomicInteger(0);
 
-    static Node<?> toFilterStructure(InstanceIdentifier identifier) {
+    static Node<?> toFilterStructure(final InstanceIdentifier identifier) {
         Node<?> previous = null;
         if (identifier.getPath().isEmpty()) {
             return null;
@@ -108,7 +109,7 @@ public class NetconfMapping {
         return filter("subtree", previous);
     }
 
-    static Node<?> toNode(NodeIdentifierWithPredicates argument, Node<?> node) {
+    static Node<?> toNode(final NodeIdentifierWithPredicates argument, final Node<?> node) {
         List<Node<?>> list = new ArrayList<>();
         for (Map.Entry<QName, Object> arg : argument.getKeyValues().entrySet()) {
             list.add(new SimpleNodeTOImpl(arg.getKey(), null, arg.getValue()));
@@ -119,7 +120,7 @@ public class NetconfMapping {
         return new CompositeNodeTOImpl(argument.getNodeType(), null, list);
     }
 
-    static Node<?> toNode(PathArgument argument, Node<?> node) {
+    static Node<?> toNode(final PathArgument argument, final Node<?> node) {
         if (node != null) {
             return new CompositeNodeTOImpl(argument.getNodeType(), null, Collections.<Node<?>> singletonList(node));
         } else {
@@ -127,14 +128,14 @@ public class NetconfMapping {
         }
     }
 
-    static CompositeNode toCompositeNode(NetconfMessage message, Optional<SchemaContext> ctx) {
+    static CompositeNode toCompositeNode(final NetconfMessage message, final Optional<SchemaContext> ctx) {
         // TODO: implement general normalization to normalize incoming Netconf
         // Message
         // for Schema Context counterpart
         return null;
     }
 
-    static CompositeNode toNotificationNode(NetconfMessage message, Optional<SchemaContext> ctx) {
+    static CompositeNode toNotificationNode(final NetconfMessage message, final Optional<SchemaContext> ctx) {
         if (ctx.isPresent()) {
             SchemaContext schemaContext = ctx.get();
             Set<NotificationDefinition> notifications = schemaContext.getNotifications();
@@ -144,7 +145,7 @@ public class NetconfMapping {
         return null;
     }
 
-    static NetconfMessage toRpcMessage(QName rpc, CompositeNode node, Optional<SchemaContext> ctx) {
+    static NetconfMessage toRpcMessage(final QName rpc, final CompositeNode node, final Optional<SchemaContext> ctx) {
         CompositeNodeTOImpl rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node));
         Document w3cPayload = null;
         try {
@@ -164,8 +165,8 @@ public class NetconfMapping {
         if (input instanceof CompositeNode) {
 
             List<Node<?>> nodes = ImmutableList.<Node<?>> builder() //
-                    .addAll(input.getChildren()) //
-                    .addAll(Collections2.filter(node.getChildren(), new Predicate<Node<?>>() {
+                    .addAll(input.getValue()) //
+                    .addAll(Collections2.filter(node.getValue(), new Predicate<Node<?>>() {
                         @Override
                         public boolean apply(@Nullable final Node<?> input) {
                             return input.getNodeType() != inputQName;
@@ -179,7 +180,7 @@ public class NetconfMapping {
         return input;
     }
 
-    static RpcResult<CompositeNode> toRpcResult(NetconfMessage message, final QName rpc, Optional<SchemaContext> context) {
+    static RpcResult<CompositeNode> toRpcResult(final NetconfMessage message, final QName rpc, final Optional<SchemaContext> context) {
         CompositeNode rawRpc;
         if (context.isPresent())
             if (isDataRetrieQNameReply(rpc)) {
@@ -196,7 +197,7 @@ public class NetconfMapping {
                 rawRpc = it.toInstance();
                 // sys(xmlData)
             } else {
-                rawRpc = (CompositeNode) toCompositeNode(message, context);
+                rawRpc = toCompositeNode(message, context);
             }
         else {
             rawRpc = (CompositeNode) toCompositeNode(message.getDocument());
@@ -205,17 +206,17 @@ public class NetconfMapping {
         return Rpcs.getRpcResult(true, rawRpc, Collections.<RpcError> emptySet());
     }
 
-    static Element getDataSubtree(Document doc) {
+    static Element getDataSubtree(final Document doc) {
         return (Element) doc.getElementsByTagNameNS(NETCONF_URI.toString(), "data").item(0);
     }
 
-    static boolean isDataRetrieQNameReply(QName it) {
+    static boolean isDataRetrieQNameReply(final QName it) {
         return NETCONF_URI == it.getNamespace()
                 && (it.getLocalName() == NETCONF_GET_CONFIG_QNAME.getLocalName() || it.getLocalName() == NETCONF_GET_QNAME
-                        .getLocalName());
+                .getLocalName());
     }
 
-    static CompositeNodeTOImpl wrap(QName name, Node<?> node) {
+    static CompositeNodeTOImpl wrap(final QName name, final Node<?> node) {
         if (node != null) {
             return new CompositeNodeTOImpl(name, null, Collections.<Node<?>> singletonList(node));
         } else {
@@ -223,7 +224,7 @@ public class NetconfMapping {
         }
     }
 
-    static CompositeNodeTOImpl wrap(QName name, Node<?> additional, Node<?> node) {
+    static CompositeNodeTOImpl wrap(final QName name, final Node<?> additional, final Node<?> node) {
         if (node != null) {
             return new CompositeNodeTOImpl(name, null, ImmutableList.of(additional, node));
         } else {
@@ -231,7 +232,7 @@ public class NetconfMapping {
         }
     }
 
-    static ImmutableCompositeNode filter(String type, Node<?> node) {
+    static ImmutableCompositeNode filter(final String type, final Node<?> node) {
         CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder(); //
         it.setQName(NETCONF_FILTER_QNAME);
         it.setAttribute(NETCONF_TYPE_QNAME, type);
@@ -242,11 +243,11 @@ public class NetconfMapping {
         }
     }
 
-    public static Node<?> toCompositeNode(Document document) {
+    public static Node<?> toCompositeNode(final Document document) {
         return XmlDocumentUtils.toDomNode(document);
     }
 
-    public static void checkValidReply(NetconfMessage input, NetconfMessage output) {
+    public static void checkValidReply(final NetconfMessage input, final NetconfMessage output) {
         String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id");
         String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id");
 
@@ -257,7 +258,7 @@ public class NetconfMapping {
         }
     }
 
-    public static void checkSuccessReply(NetconfMessage output) throws NetconfDocumentedException {
+    public static void checkSuccessReply(final NetconfMessage output) throws NetconfDocumentedException {
         if(NetconfMessageUtil.isErrorMessage(output)) {
             throw new IllegalStateException(String.format("Response contains error: %s", XmlUtil.toString(output.getDocument())));
         }
index 8f95e73b15cdcd8307612bb155a0c3c406647a57..e721084763732900a1820e83e4b7d7d92f051d0e 100644 (file)
@@ -180,10 +180,10 @@ public class ClientImpl implements RemoteRpcClient {
    * @param  routeId route identifier
    * @return         remote network address
    */
-  private String lookupRemoteAddressForGlobalRpc(RpcRouter.RouteIdentifier routeId){
+  private String lookupRemoteAddressForGlobalRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
     checkNotNull(routeId, "route must not be null");
 
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable = routingTableProvider.getRoutingTable();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
     checkNotNull(routingTable.isPresent(), "Routing table is null");
 
     String address = null;
@@ -202,10 +202,10 @@ public class ClientImpl implements RemoteRpcClient {
    * @param  routeId route identifier
    * @return         remote network address
    */
-  private String lookupRemoteAddressForRpc(RpcRouter.RouteIdentifier routeId){
+  private String lookupRemoteAddressForRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
     checkNotNull(routeId, "route must not be null");
 
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable = routingTableProvider.getRoutingTable();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
     checkNotNull(routingTable.isPresent(), "Routing table is null");
 
     String address = routingTable.get().getLastAddedRoute(routeId);
@@ -230,7 +230,7 @@ public class ClientImpl implements RemoteRpcClient {
    */
   private void closeZmqContext() {
     ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask zmqTermination = new FutureTask(new Runnable() {
+    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
 
       @Override
       public void run() {
index 9e66c20613e89db5cc5825e376b339ef52f9bba7..37bff7b7bba8ce091be33dc11a0ffff14979993f 100644 (file)
@@ -7,19 +7,19 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import org.zeromq.ZMQ;
-
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.Enumeration;
 
+import org.zeromq.ZMQ;
+
 /**
  * Provides a ZeroMQ Context object
  */
 public class Context {
-  private ZMQ.Context zmqContext = ZMQ.context(1);
+  private final ZMQ.Context zmqContext = ZMQ.context(1);
   private String uri;
   private final String DEFAULT_RPC_PORT = "5554";
 
@@ -69,7 +69,7 @@ public class Context {
    */
   private String findIpAddress() {
     String hostAddress = null;
-    Enumeration e = null;
+    Enumeration<?> e = null;
     try {
       e = NetworkInterface.getNetworkInterfaces();
     } catch (SocketException e1) {
@@ -79,7 +79,7 @@ public class Context {
 
       NetworkInterface n = (NetworkInterface) e.nextElement();
 
-      Enumeration ee = n.getInetAddresses();
+      Enumeration<?> ee = n.getInetAddresses();
       while (ee.hasMoreElements()) {
         InetAddress i = (InetAddress) ee.nextElement();
         if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
index a564a0ad045a533818135b2921c173e684a603b1..94e3232f17b1505f51ff51371c9e7dd1d767a93f 100644 (file)
@@ -8,14 +8,11 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-
 public interface RemoteRpcClient extends AutoCloseable{
 
     void setRoutingTableProvider(RoutingTableProvider provider);
-    
+
     void stop();
-    
+
     void start();
 }
index 53fbb929bb3a5c5942851a224f71c263f6ec2305..76df25682e1b79df3f7762ac1fb8094dac5eda18 100644 (file)
@@ -58,7 +58,7 @@ public class RemoteRpcProvider implements
   private ProviderSession brokerSession;
   private RpcProvisionRegistry rpcProvisionRegistry;
   private BundleContext context;
-  private ServiceTracker clusterTracker;
+  private ServiceTracker<?, ?> clusterTracker;
 
   public RemoteRpcProvider(ServerImpl server, ClientImpl client) {
     this.server = server;
@@ -170,8 +170,8 @@ public class RemoteRpcProvider implements
 
   }
 
-  private RoutingTable<RpcRouter.RouteIdentifier, String> getRoutingTable(){
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable =
+  private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> getRoutingTable(){
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable =
         routingTableProvider.getRoutingTable();
 
     checkState(routingTable.isPresent(), "Routing table is null");
@@ -191,7 +191,7 @@ public class RemoteRpcProvider implements
       RouteIdentifierImpl routeId = new RouteIdentifierImpl();
       routeId.setType(rpc);
 
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
 
       try {
         routingTable.addGlobalRoute(routeId, server.getServerAddress());
@@ -212,7 +212,7 @@ public class RemoteRpcProvider implements
       RouteIdentifierImpl routeId = new RouteIdentifierImpl();
       routeId.setType(rpc);
 
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
 
       try {
         routingTable.removeGlobalRoute(routeId);
@@ -245,9 +245,9 @@ public class RemoteRpcProvider implements
      *
      * @param announcements
      */
-    private void announce(Set<RpcRouter.RouteIdentifier> announcements) {
+    private void announce(Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements) {
       _logger.debug("Announcing [{}]", announcements);
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
       try {
         routingTable.addRoutes(announcements, server.getServerAddress());
       } catch (RoutingTableException | SystemException e) {
@@ -259,9 +259,9 @@ public class RemoteRpcProvider implements
      *
      * @param removals
      */
-    private void remove(Set<RpcRouter.RouteIdentifier> removals){
+    private void remove(Set<RpcRouter.RouteIdentifier<?, ?, ?>> removals){
       _logger.debug("Removing [{}]", removals);
-      RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
       try {
         routingTable.removeRoutes(removals, server.getServerAddress());
       } catch (RoutingTableException | SystemException e) {
@@ -274,9 +274,9 @@ public class RemoteRpcProvider implements
      * @param changes
      * @return
      */
-    private Set<RpcRouter.RouteIdentifier> getRouteIdentifiers(Map<RpcRoutingContext, Set<InstanceIdentifier>> changes) {
+    private Set<RpcRouter.RouteIdentifier<?, ?, ?>> getRouteIdentifiers(Map<RpcRoutingContext, Set<InstanceIdentifier>> changes) {
       RouteIdentifierImpl routeId = null;
-      Set<RpcRouter.RouteIdentifier> routeIdSet = new HashSet<RpcRouter.RouteIdentifier>();
+      Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdSet = new HashSet<>();
 
       for (RpcRoutingContext context : changes.keySet()){
         routeId = new RouteIdentifierImpl();
index 71bab288e6ce3c38c555a036cf3a6b05c35af4de..d960303fcf4b45c5ec5ac7d35ccff04f2fee4a3b 100644 (file)
@@ -8,25 +8,24 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import com.google.common.base.Optional;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
 import org.opendaylight.controller.sal.connector.remoterpc.impl.RoutingTableImpl;
 import org.osgi.framework.BundleContext;
 import org.osgi.util.tracker.ServiceTracker;
 
+import com.google.common.base.Optional;
+
 public class RoutingTableProvider implements AutoCloseable {
 
     @SuppressWarnings("rawtypes")
     final ServiceTracker<RoutingTable,RoutingTable> tracker;
 
-    private RoutingTableImpl routingTableImpl = null;
+    private RoutingTableImpl<?, ?> routingTableImpl = null;
 
     //final private RouteChangeListener routeChangeListener;
-    
-    
+
+
     public RoutingTableProvider(BundleContext ctx){//,RouteChangeListener rcl) {
         @SuppressWarnings("rawtypes")
         ServiceTracker<RoutingTable, RoutingTable> rawTracker = new ServiceTracker<>(ctx, RoutingTable.class, null);
@@ -35,14 +34,14 @@ public class RoutingTableProvider implements AutoCloseable {
 
         //routeChangeListener = rcl;
     }
-    
-    public Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> getRoutingTable() {
+
+    public Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> getRoutingTable() {
         @SuppressWarnings("unchecked")
-        RoutingTable<RpcRouter.RouteIdentifier,String> tracked = tracker.getService();
+        RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> tracked = tracker.getService();
 
         if(tracked instanceof RoutingTableImpl){
             if(routingTableImpl != tracked){
-             routingTableImpl= (RoutingTableImpl)tracked;
+             routingTableImpl= (RoutingTableImpl<?, ?>)tracked;
              //routingTableImpl.setRouteChangeListener(routeChangeListener);
             }
         }
index d256b998d4f8abd254fffea087778600a1b70051..3acea356ceb4747feb48a3ae6126e0435708f74f 100644 (file)
@@ -7,48 +7,33 @@
  */
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Sets;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
-import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.Enumeration;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 /**
  * ZeroMq based implementation of RpcRouter.
  */
 public class ServerImpl implements RemoteRpcServer {
 
-  private Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
+  private final Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
 
   private ExecutorService serverPool;
   protected ServerRequestHandler handler;
@@ -63,7 +48,7 @@ public class ServerImpl implements RemoteRpcServer {
   private volatile State status = State.STOPPED;
 
   private String serverAddress;
-  private int port;
+  private final int port;
 
   public static enum State {
     STARTING, STARTED, STOPPED;
@@ -167,7 +152,7 @@ public class ServerImpl implements RemoteRpcServer {
    */
   private void closeZmqContext() {
     ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask zmqTermination = new FutureTask(new Runnable() {
+    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
 
       @Override
       public void run() {
@@ -249,7 +234,7 @@ public class ServerImpl implements RemoteRpcServer {
    * @return
    */
   private String findIpAddress() {
-    Enumeration e = null;
+    Enumeration<?> e = null;
     try {
       e = NetworkInterface.getNetworkInterfaces();
     } catch (SocketException e1) {
@@ -260,7 +245,7 @@ public class ServerImpl implements RemoteRpcServer {
 
       NetworkInterface n = (NetworkInterface) e.nextElement();
 
-      Enumeration ee = n.getInetAddresses();
+      Enumeration<?> ee = n.getInetAddresses();
       while (ee.hasMoreElements()) {
         InetAddress i = (InetAddress) ee.nextElement();
         _logger.debug("Trying address {}", i);
index 2041f03afba07c58146c1c2d449d3e1f5d2ccc3d..a25387d297935351bbec8d3f6b0af13638f43286 100644 (file)
@@ -8,38 +8,39 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
 import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.zeromq.ZMQ;
 
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Collection;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
 /**
  *
  */
 public class ServerRequestHandler implements AutoCloseable{
 
-  private Logger _logger = LoggerFactory.getLogger(ServerRequestHandler.class);
+  private final Logger _logger = LoggerFactory.getLogger(ServerRequestHandler.class);
   private final String DEFAULT_NAME = "remote-rpc-worker";
-  private String dealerAddress;
-  private String serverAddress;
-  private int workerCount;
-  private ZMQ.Context context;
-  private Broker.ProviderSession broker;
+  private final String dealerAddress;
+  private final String serverAddress;
+  private final int workerCount;
+  private final ZMQ.Context context;
+  private final Broker.ProviderSession broker;
 
   private RequestHandlerThreadPool workerPool;
   private final AtomicInteger threadId = new AtomicInteger();
@@ -87,7 +88,7 @@ public class ServerRequestHandler implements AutoCloseable{
    * Worker to handles RPC request
    */
   private class Worker implements Runnable {
-    private String name;
+    private final String name;
 
     public Worker(int id){
       this.name = DEFAULT_NAME + "-" + id;
@@ -187,7 +188,7 @@ public class ServerRequestHandler implements AutoCloseable{
   }
 
   class MessageHandler{
-    private ZMQ.Socket socket;
+    private final ZMQ.Socket socket;
     private Message message;          //parsed message received on zmq server port
     private boolean messageForBroker = false; //if the message is valid and not a "ping" message
 
@@ -236,7 +237,7 @@ public class ServerRequestHandler implements AutoCloseable{
       CompositeNode payload = (result != null) ? result.getResult() : null;
 
       String recipient = null;
-      RpcRouter.RouteIdentifier routeId = null;
+      RpcRouter.RouteIdentifier<?, ?, ?> routeId = null;
 
       if (message != null) {
         recipient = message.getSender();
index 21d02be7d7295b5514b4819310f74a744fcb0ae0..cbcfe3e2a9e4833a2c88ffc08fd2bb05b0ed3d79 100644 (file)
@@ -41,7 +41,7 @@ public class Message implements Serializable {
   private MessageType type;
   private String sender;
   private String recipient;
-  private RpcRouter.RouteIdentifier route;
+  private RpcRouter.RouteIdentifier<?, ?, ?> route;
   private Object payload;
 
   public MessageType getType() {
@@ -60,11 +60,11 @@ public class Message implements Serializable {
     this.sender = sender;
   }
 
-  public RpcRouter.RouteIdentifier getRoute() {
+  public RpcRouter.RouteIdentifier<?, ?, ?> getRoute() {
     return route;
   }
 
-  public void setRoute(RpcRouter.RouteIdentifier route) {
+  public void setRoute(RpcRouter.RouteIdentifier<?, ?, ?> route) {
     this.route = route;
   }
 
@@ -123,7 +123,7 @@ public class Message implements Serializable {
     return o.readObject();
   }
 
-  public static class Response extends Message implements RpcRouter.RpcReply {
+  public static class Response extends Message implements RpcRouter.RpcReply<Object> {
     private static final long serialVersionUID = 1L;
     private ResponseCode code; // response code
 
@@ -173,7 +173,7 @@ public class Message implements Serializable {
       return this;
     }
 
-    public MessageBuilder route(RpcRouter.RouteIdentifier route){
+    public MessageBuilder route(RpcRouter.RouteIdentifier<?, ?, ?> route){
       message.setRoute(route);
       return this;
     }
index 0fa12e351c19d075ce934f4ca2ccccafa6918514..f8d14ce62e190a19faf1496b73923cb1a4d25ad0 100644 (file)
@@ -40,8 +40,8 @@ public class ClientImplTest {
 
     //mock routing table
     routingTableProvider = mock(RoutingTableProvider.class);
-    RoutingTable<RpcRouter.RouteIdentifier, String> mockRoutingTable = new MockRoutingTable<String, String>();
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
+    RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> mockRoutingTable = new MockRoutingTable<String, String>();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
     when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
 
     //mock ClientRequestHandler
index 1edd004d3725a5fcbe55a8e7057087cdd83a5b53..09188683cd5ef8e6cc79f6fa3e57825f709279a5 100644 (file)
@@ -99,7 +99,7 @@ public class ClientRequestHandlerTest {
   private Message handleMessageWithTimeout(final Message request) {
     Message response = null;
 
-    FutureTask task = new FutureTask(new Callable<Message>() {
+    FutureTask<?> task = new FutureTask<Message>(new Callable<Message>() {
 
       @Override
       public Message call() {
index 0fe0155bb6a90e48a24e3ce7d3ecaaee37f956f8..179051e4d48ecb2e2f7f7d81b3cabaedb267c5f0 100644 (file)
@@ -7,16 +7,13 @@
  */
 package org.opendaylight.controller.sal.connector.remoterpc;
 
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
 import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
 /**
  * Mock implementation of routing table
  */
@@ -59,7 +56,7 @@ public class MockRoutingTable<K, V> implements RoutingTable {
   }
 
   @Override
-  public Set getRoutes(Object o) {
+  public Set<String> getRoutes(Object o) {
     Set<String> routes = new HashSet<String>();
     routes.add("localhost:5554");
     return routes;
index 886ff426c7948d4a95d778d0f5717da1f0aa582e..7ffdf17ce761a2adb0ae763d2bcf15444e958c6f 100644 (file)
@@ -8,28 +8,34 @@
 package org.opendaylight.controller.sal.connector.remoterpc;
 
 
-import com.google.common.base.Optional;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+
 import junit.framework.Assert;
-import org.junit.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
 import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.zeromq.ZMQ;
+
 import zmq.Ctx;
 import zmq.SocketBase;
 
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ThreadPoolExecutor;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import com.google.common.base.Optional;
 
 public class ServerImplTest {
 
@@ -68,12 +74,12 @@ public class ServerImplTest {
     server = new ServerImpl(port);
     server.setBrokerSession(brokerSession);
 
-    RoutingTable<RpcRouter.RouteIdentifier, String> mockRoutingTable = new MockRoutingTable<String, String>();
-    Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
+    RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> mockRoutingTable = new MockRoutingTable<String, String>();
+    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
     when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
 
     when(brokerSession.addRpcRegistrationListener(listener)).thenReturn(null);
-    when(brokerSession.getSupportedRpcs()).thenReturn(Collections.EMPTY_SET);
+    when(brokerSession.getSupportedRpcs()).thenReturn(Collections.<QName>emptySet());
     when(brokerSession.rpc(null, mock(CompositeNode.class))).thenReturn(null);
     server.start();
     Thread.sleep(5000);//wait for server to start
@@ -178,7 +184,7 @@ public class ServerImplTest {
     Thread[] threads = new Thread[Thread.activeCount()];
     Thread.enumerate(threads);
 
-    List<Thread> foundThreads = new ArrayList();
+    List<Thread> foundThreads = new ArrayList<Thread>();
     for (Thread t : threads) {
       if (t.getName().startsWith(name))
         foundThreads.add(t);
index 6e39867e5368cbb30d1db4b174890d79bb30b983..e5fbc761b4a9b02664f9729572de253d46e5c041 100644 (file)
@@ -7,7 +7,15 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc;
 
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 import junit.framework.Assert;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -15,22 +23,15 @@ import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.zeromq.ZMQ;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import static org.mockito.Mockito.mock;
-
 public class ServerRequestHandlerTest {
 
   ServerRequestHandler handler;
   ZMQ.Context context;
   ExecutorService executorService = Executors.newCachedThreadPool();
-  private int workerCount = 2;
-  private String mockDealerAddress = "inproc://rpc-request-handler";
-  private String mockServerIp = "localhost";
-  private int mockServerPort = 5554;
+  private final int workerCount = 2;
+  private final String mockDealerAddress = "inproc://rpc-request-handler";
+  private final String mockServerIp = "localhost";
+  private final int mockServerPort = 5554;
 
   @Before
   public void setUp() throws Exception {
@@ -98,7 +99,7 @@ public class ServerRequestHandlerTest {
     Thread[] threads = new Thread[Thread.activeCount()];
     Thread.enumerate(threads);
 
-    List<Thread> foundThreads = new ArrayList();
+    List<Thread> foundThreads = new ArrayList<Thread>();
     for (Thread t : threads) {
       if (t.getName().startsWith(name))
         foundThreads.add(t);
index a68ee574f339526fa2c7a3f5b06e23a78ea13700..883aa52f3f278d5bd725d9c99c1406f795caf04f 100644 (file)
@@ -7,12 +7,6 @@
 
 package org.opendaylight.controller.sal.connector.remoterpc.utils;
 
-import junit.framework.Assert;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -21,6 +15,13 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
 
+import junit.framework.Assert;
+
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
 public class MessagingUtil {
 
   private static final Logger _logger = LoggerFactory.getLogger(MessagingUtil.class);
@@ -160,7 +161,7 @@ public class MessagingUtil {
     if (context == null) return;
 
     ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask zmqTermination = new FutureTask(new Runnable() {
+    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
 
       @Override
       public void run() {
index a71ab865aa717b84edcc615a6f01d750ac417132..7a4f4a5974606c945a3538fcebe8623f226ddc03 100644 (file)
@@ -1,14 +1,14 @@
 package org.opendaylight.controller.sal.connector.remoterpc.utils;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
 import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.zeromq.ZMQ;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
 public class RemoteServerTestClient {
 
 
@@ -39,7 +39,7 @@ public class RemoteServerTestClient {
   }
   public Message createAddFlowMessage(String serverAddress ){
 
-    RpcRouter.RouteIdentifier routeIdentifier = getAddFlowRpcIdentifier();
+    RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier = getAddFlowRpcIdentifier();
 
     Message addFlow = new Message.MessageBuilder()
         .type(Message.MessageType.REQUEST)
@@ -52,7 +52,7 @@ public class RemoteServerTestClient {
     return addFlow;
   }
 
-  private RpcRouter.RouteIdentifier getAddFlowRpcIdentifier(){
+  private RpcRouter.RouteIdentifier<?, ?, ?> getAddFlowRpcIdentifier(){
     throw new UnsupportedOperationException();
   }
 
index fe00ab1836dbf7326d2a3352b86c018b4cce139d..c2d245badbca059dfbff3d7bdbf2b50ba30efa1d 100644 (file)
       <groupId>io.netty</groupId>
       <artifactId>netty-codec-http</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-remote</artifactId>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-parser-impl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-restconf</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-util</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
           <instructions>
             <Bundle-Name>MD SAL Restconf Connector</Bundle-Name>
             <Private-Package>org.opendaylight.controller.sal.rest.*,
+              org.opendaylight.controller.sal.restconf.rpc.*,
               org.opendaylight.controller.sal.restconf.impl,</Private-Package>
             <Import-Package>*,
             com.sun.jersey.spi.container.servlet</Import-Package>
index d0eaa36dde23bd118a47a38b519139ccaed31a7a..af763cce0d20e0b03a76a1321580dcd71571446c 100644 (file)
@@ -7,18 +7,67 @@
  */
 package org.opendaylight.controller.sal.rest.api;
 
+import org.opendaylight.yangtools.yang.common.QName;
+
 public class Draft02 {
-    public static class MediaTypes {
-        public static final String API = "application/yang.api";
-        public static final String DATASTORE = "application/yang.datastore";
-        public static final String DATA = "application/yang.data";
-        public static final String OPERATION = "application/yang.operation";
-        public static final String PATCH = "application/yang.patch";
-        public static final String PATCH_STATUS = "application/yang.patch-status";
-        public static final String STREAM = "application/yang.stream";
+    public static interface MediaTypes {
+        String API = "application/yang.api";
+        String DATASTORE = "application/yang.datastore";
+        String DATA = "application/yang.data";
+        String OPERATION = "application/yang.operation";
+        String PATCH = "application/yang.patch";
+        String PATCH_STATUS = "application/yang.patch-status";
+        String STREAM = "application/yang.stream";
+    }
+
+    public static interface RestConfModule {
+        String REVISION = "2013-10-19";
+
+        String NAME = "ietf-restconf";
+
+        String NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf";
+
+        String RESTCONF_GROUPING_SCHEMA_NODE = "restconf";
+
+        String RESTCONF_CONTAINER_SCHEMA_NODE = "restconf";
+
+        String MODULES_CONTAINER_SCHEMA_NODE = "modules";
+
+        String MODULE_LIST_SCHEMA_NODE = "module";
+
+        String STREAMS_CONTAINER_SCHEMA_NODE = "streams";
+
+        String STREAM_LIST_SCHEMA_NODE = "stream";
+
+        String OPERATIONS_CONTAINER_SCHEMA_NODE = "operations";
+
+        String ERRORS_GROUPING_SCHEMA_NODE = "errors";
+
+        String ERRORS_CONTAINER_SCHEMA_NODE = "errors";
+
+        String ERROR_LIST_SCHEMA_NODE = "error";
+
+        QName IETF_RESTCONF_QNAME = QName.create( Draft02.RestConfModule.NAMESPACE,
+                                                  Draft02.RestConfModule.REVISION,
+                                                  Draft02.RestConfModule.NAME );
+
+        QName ERRORS_CONTAINER_QNAME = QName.create( IETF_RESTCONF_QNAME, ERRORS_CONTAINER_SCHEMA_NODE );
+
+        QName ERROR_LIST_QNAME = QName.create( IETF_RESTCONF_QNAME, ERROR_LIST_SCHEMA_NODE );
+
+        QName ERROR_TYPE_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-type" );
+
+        QName ERROR_TAG_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-tag" );
+
+        QName ERROR_APP_TAG_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-app-tag" );
+
+        QName ERROR_MESSAGE_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-message" );
+
+        QName ERROR_INFO_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-info" );
     }
-    
-    public static class Paths {
-        
+
+
+    public static interface Paths {
+
     }
 }
index d1441d7b9d904a202ad90bfcc53d36c794ae993e..1e5bfbd6b93e7fe540931a0f6f828625a4a963c1 100644 (file)
@@ -11,6 +11,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.IOException;
 import java.net.URI;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -57,7 +58,7 @@ class JsonMapper {
     private MountInstance mountPoint;
     private final Logger logger = LoggerFactory.getLogger(JsonMapper.class);
 
-    public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema, MountInstance mountPoint)
+    public void write(final JsonWriter writer, final CompositeNode data, final DataNodeContainer schema, final MountInstance mountPoint)
             throws IOException {
         Preconditions.checkNotNull(writer);
         Preconditions.checkNotNull(data);
@@ -81,20 +82,25 @@ class JsonMapper {
         foundLists.clear();
     }
 
-    private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema)
+    private void writeChildrenOfParent(final JsonWriter writer, final CompositeNode parent, final DataNodeContainer parentSchema)
             throws IOException {
         checkNotNull(parent);
-        checkNotNull(parentSchema);
 
-        for (Node<?> child : parent.getChildren()) {
-            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
+        Set<DataSchemaNode> parentSchemaChildNodes = parentSchema == null ?
+                                   Collections.<DataSchemaNode>emptySet() : parentSchema.getChildNodes();
+
+
+        for (Node<?> child : parent.getValue()) {
+            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
 
             if (childSchema == null) {
-                throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
-                        + "\" is not conform to schema");
-            }
+                // Node may not conform to schema or allows "anyxml" - we'll process it.
 
-            if (childSchema instanceof ContainerSchemaNode) {
+                logger.debug( "No schema found for data node \"" + child.getNodeType() );
+
+                handleNoSchemaFound( writer, child, parent );
+            }
+            else if (childSchema instanceof ContainerSchemaNode) {
                 Preconditions.checkState(child instanceof CompositeNode,
                         "Data representation of Container should be CompositeNode - " + child.getNodeType());
                 writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
@@ -122,17 +128,33 @@ class JsonMapper {
             }
         }
 
-        for (Node<?> child : parent.getChildren()) {
-            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
+        for (Node<?> child : parent.getValue()) {
+            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
             if (childSchema instanceof LeafListSchemaNode) {
-                foundLeafLists.remove((LeafListSchemaNode) childSchema);
+                foundLeafLists.remove(childSchema);
             } else if (childSchema instanceof ListSchemaNode) {
-                foundLists.remove((ListSchemaNode) childSchema);
+                foundLists.remove(childSchema);
             }
         }
     }
 
-    private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
+    private void handleNoSchemaFound( final JsonWriter writer, final Node<?> node,
+                                      final CompositeNode parent ) throws IOException {
+        if( node instanceof SimpleNode<?> ) {
+            writeName( node, null, writer );
+            Object value = node.getValue();
+            if( value != null ) {
+                writer.value( String.valueOf( value ) );
+            }
+        } else { // CompositeNode
+            Preconditions.checkState( node instanceof CompositeNode,
+                    "Data representation of Container should be CompositeNode - " + node.getNodeType() );
+
+            writeContainer( writer, (CompositeNode) node, null );
+        }
+    }
+
+    private DataSchemaNode findFirstSchemaForNode(final Node<?> node, final Set<DataSchemaNode> dataSchemaNode) {
         for (DataSchemaNode dsn : dataSchemaNode) {
             if (node.getNodeType().equals(dsn.getQName())) {
                 return dsn;
@@ -148,14 +170,14 @@ class JsonMapper {
         return null;
     }
 
-    private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
+    private void writeContainer(final JsonWriter writer, final CompositeNode node, final ContainerSchemaNode schema) throws IOException {
         writeName(node, schema, writer);
         writer.beginObject();
         writeChildrenOfParent(writer, node, schema);
         writer.endObject();
     }
 
-    private void writeList(JsonWriter writer, CompositeNode nodeParent, CompositeNode node, ListSchemaNode schema)
+    private void writeList(final JsonWriter writer, final CompositeNode nodeParent, final CompositeNode node, final ListSchemaNode schema)
             throws IOException {
         writeName(node, schema, writer);
         writer.beginArray();
@@ -176,8 +198,8 @@ class JsonMapper {
         writer.endArray();
     }
 
-    private void writeLeafList(JsonWriter writer, CompositeNode nodeParent, SimpleNode<?> node,
-            LeafListSchemaNode schema) throws IOException {
+    private void writeLeafList(final JsonWriter writer, final CompositeNode nodeParent, final SimpleNode<?> node,
+            final LeafListSchemaNode schema) throws IOException {
         writeName(node, schema, writer);
         writer.beginArray();
 
@@ -188,13 +210,13 @@ class JsonMapper {
         writer.endArray();
     }
 
-    private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
+    private void writeLeaf(final JsonWriter writer, final SimpleNode<?> node, final LeafSchemaNode schema) throws IOException {
         writeName(node, schema, writer);
         writeValueOfNodeByType(writer, node, schema.getType(), schema);
     }
 
-    private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type,
-            DataSchemaNode schema) throws IOException {
+    private void writeValueOfNodeByType(final JsonWriter writer, final SimpleNode<?> node, final TypeDefinition<?> type,
+            final DataSchemaNode schema) throws IOException {
 
         TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
 
@@ -245,7 +267,7 @@ class JsonMapper {
         }
     }
 
-    private void writeIdentityValuesDTOToJson(JsonWriter writer, IdentityValuesDTO valueDTO) throws IOException {
+    private void writeIdentityValuesDTOToJson(final JsonWriter writer, final IdentityValuesDTO valueDTO) throws IOException {
         StringBuilder result = new StringBuilder();
         for (IdentityValue identityValue : valueDTO.getValuesWithNamespaces()) {
             result.append("/");
@@ -271,7 +293,7 @@ class JsonMapper {
         writer.value(result.toString());
     }
 
-    private void writeModuleNameAndIdentifier(StringBuilder result, IdentityValue identityValue) {
+    private void writeModuleNameAndIdentifier(final StringBuilder result, final IdentityValue identityValue) {
         String moduleName = ControllerContext.getInstance().findModuleNameByNamespace(
                 URI.create(identityValue.getNamespace()));
         if (moduleName != null && !moduleName.isEmpty()) {
@@ -281,8 +303,8 @@ class JsonMapper {
         result.append(identityValue.getValue());
     }
 
-    private void writeStringRepresentation(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> baseType,
-            Class<?> requiredType) throws IOException {
+    private void writeStringRepresentation(final JsonWriter writer, final SimpleNode<?> node, final TypeDefinition<?> baseType,
+            final Class<?> requiredType) throws IOException {
         Object value = node.getValue();
         logger.debug("Value of " + baseType.getQName().getNamespace() + ":" + baseType.getQName().getLocalName()
                 + " is not instance of " + requiredType.getClass() + " but is " + node.getValue().getClass());
@@ -293,15 +315,15 @@ class JsonMapper {
         }
     }
 
-    private void writeEmptyDataTypeToJson(JsonWriter writer) throws IOException {
+    private void writeEmptyDataTypeToJson(final JsonWriter writer) throws IOException {
         writer.beginArray();
         writer.nullValue();
         writer.endArray();
     }
 
-    private void writeName(Node<?> node, DataSchemaNode schema, JsonWriter writer) throws IOException {
+    private void writeName(final Node<?> node, final DataSchemaNode schema, final JsonWriter writer) throws IOException {
         String nameForOutput = node.getNodeType().getLocalName();
-        if (schema.isAugmenting()) {
+        if ( schema != null && schema.isAugmenting()) {
             ControllerContext contContext = ControllerContext.getInstance();
             CharSequence moduleName = null;
             if (mountPoint == null) {
@@ -323,7 +345,7 @@ class JsonMapper {
         private static final long serialVersionUID = -3147729419814417666L;
         private final String value;
 
-        public NumberForJsonWriter(String value) {
+        public NumberForJsonWriter(final String value) {
             this.value = value;
         }
 
index 0d73485c80b3fcbceaddf7235d93737cad9fa40c..856e09fabd21a1083cbe716890ba22ae3b2d5bc6 100644 (file)
@@ -16,13 +16,17 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.Provider;
 
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Provider
 @Consumes({ Draft02.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.OPERATION + RestconfService.JSON,
@@ -30,6 +34,8 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
     INSTANCE;
 
+    private final static Logger LOG = LoggerFactory.getLogger( JsonToCompositeNodeProvider.class );
+
     @Override
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return true;
@@ -42,9 +48,11 @@ public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNo
         JsonReader jsonReader = new JsonReader();
         try {
             return jsonReader.read(entityStream);
-        } catch (UnsupportedFormatException e) {
-            throw new WebApplicationException(e, Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())
-                    .build());
+        } catch (Exception e) {
+            LOG.debug( "Error parsing json input", e );
+            throw new RestconfDocumentedException(
+                            "Error parsing input: " + e.getMessage(),
+                            ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE );
         }
     }
 
index 6166a084c19c1e9e80480c2d3745e04bc9b28eca..a5fd7bdaab2646f35e7463f9698f15ca217de11f 100644 (file)
@@ -16,8 +16,15 @@ import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 
+import com.google.common.collect.ImmutableSet;
+
 public class RestconfApplication extends Application {
 
+    @Override
+    public Set<Class<?>> getClasses() {
+        return ImmutableSet.<Class<?>>of( RestconfDocumentedExceptionMapper.class );
+    }
+
     @Override
     public Set<Object> getSingletons() {
         Set<Object> singletons = new HashSet<>();
@@ -36,4 +43,5 @@ public class RestconfApplication extends Application {
         return singletons;
     }
 
+
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfDocumentedExceptionMapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfDocumentedExceptionMapper.java
new file mode 100644 (file)
index 0000000..456354b
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.rest.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map.Entry;
+
+import javax.activation.UnsupportedDataTypeException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import static org.opendaylight.controller.sal.rest.api.Draft02.RestConfModule.*;
+
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * This class defines an ExceptionMapper that handles RestconfDocumentedExceptions thrown by
+ * resource implementations and translates appropriately to restconf error response as defined in
+ * the RESTCONF RFC draft.
+ *
+ * @author Thomas Pantelis
+ */
+@Provider
+public class RestconfDocumentedExceptionMapper implements ExceptionMapper<RestconfDocumentedException> {
+
+    private final static Logger LOG = LoggerFactory.getLogger( RestconfDocumentedExceptionMapper.class );
+
+    @Context
+    private HttpHeaders headers;
+
+    @Override
+    public Response toResponse( RestconfDocumentedException exception ) {
+
+        LOG.debug( "In toResponse: {}", exception.getMessage() );
+
+        // Default to the content type if there's no Accept header
+
+        MediaType mediaType = headers.getMediaType();
+
+        List<MediaType> accepts = headers.getAcceptableMediaTypes();
+
+        LOG.debug( "Accept headers: {}", accepts );
+
+        if( accepts != null && accepts.size() > 0 ) {
+            mediaType = accepts.get( 0 ); // just pick the first one
+        }
+
+        LOG.debug( "Using MediaType: {}",  mediaType );
+
+        List<RestconfError> errors = exception.getErrors();
+        if( errors.isEmpty() ) {
+            // We don't actually want to send any content but, if we don't set any content here,
+            // the tomcat front-end will send back an html error report. To prevent that, set a
+            // single space char in the entity.
+
+            return Response.status( exception.getStatus() )
+                                    .type( MediaType.TEXT_PLAIN_TYPE )
+                                    .entity( " " ).build();
+        }
+
+        Status status = errors.iterator().next().getErrorTag().getStatusCode();
+
+        ControllerContext context = ControllerContext.getInstance();
+        DataNodeContainer errorsSchemaNode = (DataNodeContainer)context.getRestconfModuleErrorsSchemaNode();
+
+        if( errorsSchemaNode == null ) {
+            return Response.status( status )
+                           .type( MediaType.TEXT_PLAIN_TYPE )
+                           .entity( exception.getMessage() ).build();
+        }
+
+        ImmutableList.Builder<Node<?>> errorNodes = ImmutableList.<Node<?>> builder();
+        for( RestconfError error: errors ) {
+            errorNodes.add( toDomNode( error ) );
+        }
+
+        ImmutableCompositeNode errorsNode =
+                         ImmutableCompositeNode.create( ERRORS_CONTAINER_QNAME, errorNodes.build() );
+
+        Object responseBody;
+        if( mediaType.getSubtype().endsWith( "json" ) ) {
+            responseBody = toJsonResponseBody( errorsNode, errorsSchemaNode );
+        }
+        else {
+            responseBody = toXMLResponseBody( errorsNode, errorsSchemaNode );
+        }
+
+        return Response.status( status ).type( mediaType ).entity( responseBody ).build();
+    }
+
+    private Object toJsonResponseBody( ImmutableCompositeNode errorsNode,
+                                       DataNodeContainer errorsSchemaNode ) {
+
+        JsonMapper jsonMapper = new JsonMapper();
+
+        Object responseBody = null;
+        try {
+            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+            JsonWriter writer = new JsonWriter( new OutputStreamWriter( outStream, "UTF-8" ) );
+            writer.setIndent( "    " );
+
+            jsonMapper.write( writer, errorsNode, errorsSchemaNode, null );
+            writer.flush();
+
+            responseBody = outStream.toString( "UTF-8" );
+        }
+        catch( IOException e ) {
+            LOG.error( "Error writing error response body", e );
+        }
+
+        return responseBody;
+    }
+
+    private Object toXMLResponseBody( ImmutableCompositeNode errorsNode,
+                                      DataNodeContainer errorsSchemaNode ) {
+
+        XmlMapper xmlMapper = new XmlMapper();
+
+        Object responseBody = null;
+        try {
+            Document xmlDoc = xmlMapper.write( errorsNode, errorsSchemaNode );
+
+            responseBody = documentToString( xmlDoc );
+        }
+        catch( TransformerException | UnsupportedDataTypeException | UnsupportedEncodingException e ) {
+            LOG.error( "Error writing error response body", e );
+        }
+
+        return responseBody;
+    }
+
+    private String documentToString( Document doc ) throws TransformerException, UnsupportedEncodingException {
+        Transformer transformer = createTransformer();
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+
+        transformer.transform( new DOMSource( doc ), new StreamResult( outStream ) );
+
+        return outStream.toString( "UTF-8" );
+    }
+
+    private Transformer createTransformer() throws TransformerFactoryConfigurationError,
+        TransformerConfigurationException {
+        TransformerFactory tf = TransformerFactory.newInstance();
+        Transformer transformer = tf.newTransformer();
+        transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
+        transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
+        transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
+        transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
+        transformer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "4" );
+        return transformer;
+    }
+
+    private Node<?> toDomNode( RestconfError error ) {
+
+        CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
+        builder.setQName( ERROR_LIST_QNAME );
+
+        addLeaf( builder, ERROR_TYPE_QNAME, error.getErrorType().getErrorTypeTag() );
+        addLeaf( builder, ERROR_TAG_QNAME, error.getErrorTag().getTagValue() );
+        addLeaf( builder, ERROR_MESSAGE_QNAME, error.getErrorMessage() );
+        addLeaf( builder, ERROR_APP_TAG_QNAME, error.getErrorAppTag() );
+
+        Node<?> errorInfoNode = parseErrorInfo( error.getErrorInfo() );
+        if( errorInfoNode != null ) {
+            builder.add( errorInfoNode );
+        }
+
+        return builder.toInstance();
+    }
+
+    private Node<?> parseErrorInfo( String errorInfo ) {
+        if( Strings.isNullOrEmpty( errorInfo ) ) {
+            return null;
+        }
+
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware( true );
+        factory.setCoalescing( true );
+        factory.setIgnoringElementContentWhitespace( true );
+        factory.setIgnoringComments( true );
+
+        // Wrap the error info content in a root <error-info> element so it can be parsed
+        // as XML. The error info content may or may not be XML. If not then it will be
+        // parsed as text content of the <error-info> element.
+
+        String errorInfoWithRoot =
+                new StringBuilder( "<error-info xmlns=\"" ).append( NAMESPACE ).append( "\">" )
+                        .append( errorInfo ).append( "</error-info>" ).toString();
+
+        Document doc = null;
+        try {
+            doc = factory.newDocumentBuilder().parse(
+                                 new InputSource( new StringReader( errorInfoWithRoot ) ) );
+        }
+        catch( Exception e ) {
+            // TODO: what if the content is text that happens to contain invalid markup? Could
+            // wrap in CDATA and try again.
+
+            LOG.warn( "Error parsing restconf error-info, \"" + errorInfo + "\", as XML: " +
+                      e.toString() );
+            return null;
+        }
+
+        Node<?> errorInfoNode = XmlDocumentUtils.toDomNode( doc );
+
+        if( errorInfoNode instanceof CompositeNode ) {
+            CompositeNode compositeNode = (CompositeNode)XmlDocumentUtils.toDomNode( doc );
+
+            // At this point the QName for the "error-info" CompositeNode doesn't contain the revision
+            // as it isn't present in the XML. So we'll copy all the child nodes and create a new
+            // CompositeNode with the full QName. This is done so the XML/JSON mapping code can
+            // locate the schema.
+
+            ImmutableList.Builder<Node<?>> childNodes = ImmutableList.builder();
+            for( Entry<QName, List<Node<?>>> entry: compositeNode.entrySet() ) {
+                childNodes.addAll( entry.getValue() );
+            }
+
+            errorInfoNode = ImmutableCompositeNode.create( ERROR_INFO_QNAME, childNodes.build() );
+        }
+
+        return errorInfoNode;
+    }
+
+    private void addLeaf( CompositeNodeBuilder<ImmutableCompositeNode> builder, QName qname,
+                          String value ) {
+        if( !Strings.isNullOrEmpty( value ) ) {
+            builder.addLeaf( qname, value );
+        }
+    }
+}
index 1870bdf0bf37daf6e5e0acaee273b90ce3c749a5..2abd4b6a3ab5b9a08c56e782257a262db80fbfe2 100644 (file)
@@ -34,7 +34,6 @@ public class RestconfProvider implements BundleActivator, Provider, ServiceTrack
     private ListenerRegistration<SchemaServiceListener> listenerRegistration;
     private ServiceTracker<Broker, Broker> brokerServiceTrancker;
     private BundleContext bundleContext;
-    private ProviderSession session;
     private Thread webSocketServerThread;
 
     @Override
@@ -70,7 +69,6 @@ public class RestconfProvider implements BundleActivator, Provider, ServiceTrack
             }
         }
         webSocketServerThread.interrupt();
-        session.close();
         brokerServiceTrancker.close();
     }
 
index 5dba7474caa22affe5d73594ff918de54f1d4c5f..422cf04cca82f7d0bf5d2f535df40a6f7688215e 100644 (file)
@@ -23,7 +23,7 @@ import javax.ws.rs.ext.Provider;
 
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -38,7 +38,7 @@ public enum StructuredDataToJsonProvider implements MessageBodyWriter<Structured
 
     @Override
     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
-        return true;
+        return type.equals( StructuredData.class );
     }
 
     @Override
@@ -52,7 +52,7 @@ public enum StructuredDataToJsonProvider implements MessageBodyWriter<Structured
             throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
         if (data == null) {
-            throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
+            throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
         }
 
         JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
index 7d6b329cfa2ac57a731f94934fa99f3acf04ca9f..bcb3c422ff8dc0c33c8a44d27d20b63ec1e3852d 100644 (file)
@@ -28,7 +28,9 @@ import javax.xml.transform.stream.StreamResult;
 
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -46,7 +48,7 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
 
     @Override
     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
-        return true;
+        return type.equals( StructuredData.class );
     }
 
     @Override
@@ -60,9 +62,9 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
             throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
         if (data == null) {
-            throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
+            throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
         }
-        
+
         XmlMapper xmlMapper = new XmlMapper();
         Document domTree = xmlMapper.write(data, (DataNodeContainer) t.getSchema());
         try {
@@ -76,7 +78,8 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
             transformer.transform(new DOMSource(domTree), new StreamResult(entityStream));
         } catch (TransformerException e) {
             logger.error("Error during translation of Document to OutputStream", e);
-            throw new ResponseException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
+            throw new RestconfDocumentedException( e.getMessage(), ErrorType.TRANSPORT,
+                                                   ErrorTag.OPERATION_FAILED );
         }
     }
 
index 13d617031ad5717367ee50778c692ccfbda3fb16..bc7473864cbb3ffa553c78fbf8a96fb64a7dad6d 100644 (file)
@@ -16,15 +16,18 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.Provider;
 import javax.xml.stream.XMLStreamException;
 
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Provider
 @Consumes({ Draft02.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.OPERATION + RestconfService.XML,
@@ -32,6 +35,8 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
     INSTANCE;
 
+    private final static Logger LOG = LoggerFactory.getLogger( XmlToCompositeNodeProvider.class );
+
     @Override
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return true;
@@ -45,7 +50,10 @@ public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNod
         try {
             return xmlReader.read(entityStream);
         } catch (XMLStreamException | UnsupportedFormatException e) {
-            throw new ResponseException(Response.Status.BAD_REQUEST, e.getMessage());
+            LOG.debug( "Error parsing json input", e );
+            throw new RestconfDocumentedException(
+                            "Error parsing input: " + e.getMessage(),
+                            ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE );
         }
     }
 
index 1cc1f783d676ed69f68c959d1024a58349dc51d9..062d03a49f56e12ca6bb178fa39303b78fc059da 100644 (file)
@@ -18,7 +18,8 @@ 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.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -53,9 +54,7 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
 
     private void checkPreconditions() {
         if( context == null || dataService == null ) {
-            ResponseException _responseException = new ResponseException( Status.SERVICE_UNAVAILABLE,
-                    RestconfProvider.NOT_INITALIZED_MSG );
-            throw _responseException;
+            throw new RestconfDocumentedException( Status.SERVICE_UNAVAILABLE );
         }
     }
 
@@ -95,17 +94,10 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
         return mountPoint.readOperationalData( path );
     }
 
-    public RpcResult<CompositeNode> invokeRpc( final QName type, final CompositeNode payload ) {
+    public Future<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 );
-        }
+        return context.rpc( type, payload );
     }
 
     public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut( final InstanceIdentifier path,
@@ -138,9 +130,9 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
         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);
+
+            throw new RestconfDocumentedException(
+                    "Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS );
         }
         BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
         transaction.putConfigurationData( path, payload );
@@ -157,9 +149,9 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
         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);
+
+            throw new RestconfDocumentedException(
+                    "Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS );
         }
         BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
         transaction.putConfigurationData( path, payload );
index e0ae78870394223ca2a662e0d8cbfe3c64193e6f..96ad528a0dd3f9e0591b78b2be702e9b1d004c4c 100644 (file)
@@ -34,21 +34,21 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
     private QName name;
     private List<NodeWrapper<?>> values = new ArrayList<>();
 
-    public CompositeNodeWrapper(String localName) {
+    public CompositeNodeWrapper(final String localName) {
         this.localName = Preconditions.checkNotNull(localName);
     }
 
-    public CompositeNodeWrapper(URI namespace, String localName) {
+    public CompositeNodeWrapper(final URI namespace, final String localName) {
         this(localName);
         this.namespace = namespace;
     }
-    
+
     @Override
-    public void setQname(QName name) {
+    public void setQname(final QName name) {
         Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
         this.name = name;
     }
-    
+
     @Override
     public QName getQname() {
         return name;
@@ -71,26 +71,26 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
     }
 
     @Override
-    public void setNamespace(URI namespace) {
+    public void setNamespace(final URI namespace) {
         Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
         this.namespace = namespace;
     }
 
-    public void addValue(NodeWrapper<?> value) {
+    public void addValue(final NodeWrapper<?> value) {
         Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
         values.add(value);
     }
 
-    public void removeValue(NodeWrapper<CompositeNode> value) {
+    public void removeValue(final NodeWrapper<CompositeNode> value) {
         Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
         values.remove(value);
     }
-    
+
     public List<NodeWrapper<?>> getValues() {
         Preconditions.checkState(compositeNode == null, "Data can be inconsistent.");
         return Collections.unmodifiableList(values);
     }
-    
+
     @Override
     public boolean isChangeAllowed() {
         return compositeNode == null ? true : false;
@@ -103,13 +103,13 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
                 Preconditions.checkNotNull(namespace);
                 name = new QName(namespace, localName);
             }
-            
+
             List<Node<?>> nodeValues = new ArrayList<>();
             for (NodeWrapper<?> nodeWrapper : values) {
                 nodeValues.add(nodeWrapper.unwrap());
             }
             compositeNode = NodeFactory.createMutableCompositeNode(name, null, nodeValues, null, null);
-            
+
             values = null;
             namespace = null;
             localName = null;
@@ -123,6 +123,7 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
         return unwrap().getNodeType();
     }
 
+    @Deprecated
     @Override
     public CompositeNode getParent() {
         return unwrap().getParent();
@@ -138,38 +139,42 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
         return unwrap().getModificationAction();
     }
 
+    /**
+     * @deprecated Use {@link #getValue()} instead.
+     */
+    @Deprecated
     @Override
     public List<Node<?>> getChildren() {
-        return unwrap().getChildren();
+        return unwrap().getValue();
     }
 
     @Override
-    public List<CompositeNode> getCompositesByName(QName children) {
+    public List<CompositeNode> getCompositesByName(final QName children) {
         return unwrap().getCompositesByName(children);
     }
 
     @Override
-    public List<CompositeNode> getCompositesByName(String children) {
+    public List<CompositeNode> getCompositesByName(final String children) {
         return unwrap().getCompositesByName(children);
     }
 
     @Override
-    public List<SimpleNode<?>> getSimpleNodesByName(QName children) {
+    public List<SimpleNode<?>> getSimpleNodesByName(final QName children) {
         return unwrap().getSimpleNodesByName(children);
     }
 
     @Override
-    public List<SimpleNode<?>> getSimpleNodesByName(String children) {
+    public List<SimpleNode<?>> getSimpleNodesByName(final String children) {
         return unwrap().getSimpleNodesByName(children);
     }
 
     @Override
-    public CompositeNode getFirstCompositeByName(QName container) {
+    public CompositeNode getFirstCompositeByName(final QName container) {
         return unwrap().getFirstCompositeByName(container);
     }
 
     @Override
-    public SimpleNode<?> getFirstSimpleByName(QName leaf) {
+    public SimpleNode<?> getFirstSimpleByName(final QName leaf) {
         return unwrap().getFirstSimpleByName(leaf);
     }
 
@@ -184,7 +189,7 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
     }
 
     @Override
-    public List<Node<?>> setValue(List<Node<?>> value) {
+    public List<Node<?>> setValue(final List<Node<?>> value) {
         return unwrap().setValue(value);
     }
 
@@ -199,32 +204,32 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
     }
 
     @Override
-    public boolean containsKey(Object key) {
+    public boolean containsKey(final Object key) {
         return unwrap().containsKey(key);
     }
 
     @Override
-    public boolean containsValue(Object value) {
+    public boolean containsValue(final Object value) {
         return unwrap().containsValue(value);
     }
 
     @Override
-    public List<Node<?>> get(Object key) {
+    public List<Node<?>> get(final Object key) {
         return unwrap().get(key);
     }
 
     @Override
-    public List<Node<?>> put(QName key, List<Node<?>> value) {
+    public List<Node<?>> put(final QName key, final List<Node<?>> value) {
         return unwrap().put(key, value);
     }
 
     @Override
-    public List<Node<?>> remove(Object key) {
+    public List<Node<?>> remove(final Object key) {
         return unwrap().remove(key);
     }
 
     @Override
-    public void putAll(Map<? extends QName, ? extends List<Node<?>>> m) {
+    public void putAll(final Map<? extends QName, ? extends List<Node<?>>> m) {
         unwrap().putAll(m);
     }
 
index 1c076d1e2e76291f999384ccc2704a910400812e..86ed13a2802bc98b4ddd9a259aa5ac1c329118e2 100644 (file)
@@ -38,11 +38,12 @@ 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.api.Draft02;
 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.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -55,6 +56,7 @@ 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.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;
@@ -108,7 +110,7 @@ public class ControllerContext implements SchemaContextListener {
 
     private void checkPreconditions() {
         if( globalSchema == null ) {
-            throw new ResponseException( Status.SERVICE_UNAVAILABLE, RestconfProvider.NOT_INITALIZED_MSG );
+            throw new RestconfDocumentedException( Status.SERVICE_UNAVAILABLE );
         }
     }
 
@@ -139,8 +141,9 @@ public class ControllerContext implements SchemaContextListener {
         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\"" );
+            throw new RestconfDocumentedException(
+                    "First node in URI has to be in format \"moduleName:nodeName\"",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         InstanceIdentifierBuilder builder = InstanceIdentifier.builder();
@@ -149,7 +152,8 @@ public class ControllerContext implements SchemaContextListener {
                                                            latestModule, null, toMountPointIdentifier );
 
         if( iiWithSchemaNode == null ) {
-            throw new ResponseException( Status.BAD_REQUEST, "URI has bad format" );
+            throw new RestconfDocumentedException(
+                    "URI has bad format", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         return iiWithSchemaNode;
@@ -386,6 +390,112 @@ public class ControllerContext implements SchemaContextListener {
         return builder.toString();
     }
 
+    public Module getRestconfModule() {
+        return findModuleByNameAndRevision( Draft02.RestConfModule.IETF_RESTCONF_QNAME );
+    }
+
+    public DataSchemaNode getRestconfModuleErrorsSchemaNode() {
+        Module restconfModule = getRestconfModule();
+        if( restconfModule == null ) {
+            return null;
+        }
+
+        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(),
+                                     Draft02.RestConfModule.ERRORS_GROUPING_SCHEMA_NODE);
+            }
+        };
+
+        Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
+
+        final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
+
+        List<DataSchemaNode> instanceDataChildrenByName =
+                this.findInstanceDataChildrenByName(restconfGrouping,
+                                                    Draft02.RestConfModule.ERRORS_CONTAINER_SCHEMA_NODE);
+        return Iterables.getFirst(instanceDataChildrenByName, null);
+    }
+
+    public DataSchemaNode getRestconfModuleRestConfSchemaNode( Module inRestconfModule,
+                                                               String schemaNodeName ) {
+        Module restconfModule = inRestconfModule;
+        if( restconfModule == null ) {
+            restconfModule = getRestconfModule();
+        }
+
+        if( restconfModule == null ) {
+            return null;
+        }
+
+        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(),
+                                     Draft02.RestConfModule.RESTCONF_GROUPING_SCHEMA_NODE);
+            }
+        };
+
+        Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
+
+        final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
+
+        List<DataSchemaNode> instanceDataChildrenByName =
+                this.findInstanceDataChildrenByName(restconfGrouping,
+                                                            Draft02.RestConfModule.RESTCONF_CONTAINER_SCHEMA_NODE);
+        final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
+
+        if (Objects.equal(schemaNodeName, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                    Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                   Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                   Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
+            final DataSchemaNode modules = Iterables.getFirst(instances, null);
+            instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+                                                               Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                         Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                         Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
+            final DataSchemaNode modules = Iterables.getFirst(instances, null);
+            instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+                                                                 Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+        else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
+            List<DataSchemaNode> instances =
+                    this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+                                                   Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
+            return Iterables.getFirst(instances, null);
+        }
+
+        return null;
+    }
+
     private static DataSchemaNode childByQName( final ChoiceNode container, final QName name ) {
         for( final ChoiceCaseNode caze : container.getCases() ) {
             final DataSchemaNode ret = ControllerContext.childByQName( caze, name );
@@ -461,27 +571,30 @@ public class ControllerContext implements SchemaContextListener {
             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." );
+                    throw new RestconfDocumentedException(
+                            "Restconf supports just one mount point in URI.",
+                            ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED );
                 }
 
                 if( mountService == null ) {
-                    throw new ResponseException( Status.SERVICE_UNAVAILABLE,
-                                "MountService was not found. Finding behind mount points does not work." );
+                    throw new RestconfDocumentedException(
+                            "MountService was not found. Finding behind mount points does not work.",
+                            ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED );
                 }
 
                 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." );
+                    throw new RestconfDocumentedException(
+                         "Mount point does not exist.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
                 }
 
                 final SchemaContext mountPointSchema = mount.getSchemaContext();
                 if( mountPointSchema == null ) {
-                    throw new ResponseException( Status.BAD_REQUEST,
-                                       "Mount point does not contain any schema with modules." );
+                    throw new RestconfDocumentedException(
+                            "Mount point does not contain any schema with modules.",
+                            ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT );
                 }
 
                 if( returnJustMountPoint ) {
@@ -496,16 +609,17 @@ public class ControllerContext implements SchemaContextListener {
 
                 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\"" );
+                    throw new RestconfDocumentedException(
+                        "First node after mount point in URI has to be in format \"moduleName:nodeName\"",
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
                 }
 
                 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." );
+                    throw new RestconfDocumentedException(
+                            "\"" +moduleName + "\" module does not exist in mount point.",
+                            ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
                 }
 
                 List<String> subList = strings.subList( 1, strings.size() );
@@ -517,8 +631,9 @@ public class ControllerContext implements SchemaContextListener {
             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." );
+                    throw new RestconfDocumentedException(
+                            "\"" + moduleName + "\" module does not exist.",
+                            ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
                 }
             }
             else {
@@ -526,20 +641,20 @@ public class ControllerContext implements SchemaContextListener {
                 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." );
+                    throw new RestconfDocumentedException(
+                            "\"" + moduleName + "\" module does not exist in mount point.",
+                            ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
                 }
             }
 
             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 + "\"." );
+                throw new RestconfDocumentedException(
+                        "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 + "\".", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
         } else {
             final List<DataSchemaNode> potentialSchemaNodes =
@@ -552,26 +667,27 @@ public class ControllerContext implements SchemaContextListener {
                               .append( "\n" );
                 }
 
-                throw new ResponseException( Status.BAD_REQUEST,
+                throw new RestconfDocumentedException(
                         "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() );
+                        strBuilder.toString(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
 
             if( potentialSchemaNodes.isEmpty() ) {
-                throw new ResponseException( Status.BAD_REQUEST, "URI has bad format. \"" + nodeName +
-                                             "\" was not found in parent data node.\n" );
+                throw new RestconfDocumentedException(
+                        "\"" + nodeName + "\" in URI was not found in parent data node",
+                        ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
             }
 
             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." );
+            throw new RestconfDocumentedException(
+                    "URI has bad format. Node \"" + head + "\" must be Container or List yang type.",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         int consumed = 1;
@@ -579,8 +695,9 @@ public class ControllerContext implements SchemaContextListener {
             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() + "\"." );
+                throw new RestconfDocumentedException(
+                        "Missing key for list \"" + listNode.getQName().getLocalName() + "\".",
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
 
             final List<String> uriKeyValues = strings.subList( consumed, consumed + keysSize );
@@ -590,9 +707,10 @@ public class ControllerContext implements SchemaContextListener {
                 {
                     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." );
+                        throw new RestconfDocumentedException(
+                                "URI has bad format. List \"" + listNode.getQName().getLocalName() +
+                                "\" cannot contain \"null\" value as a key.",
+                                ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
                     }
 
                     this.addKeyValue( keyValues, listNode.getDataChildByName( key ),
@@ -711,8 +829,9 @@ public class ControllerContext implements SchemaContextListener {
         }
 
         if( decoded == null ) {
-            throw new ResponseException( Status.BAD_REQUEST, uriValue + " from URI can\'t be resolved. " +
-                                         additionalInfo );
+            throw new RestconfDocumentedException(
+                            uriValue + " from URI can't be resolved. " + additionalInfo,
+                            ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         map.put( node.getQName(), decoded );
@@ -807,8 +926,9 @@ public class ControllerContext implements SchemaContextListener {
             return decodedPathArgs;
         }
         catch( UnsupportedEncodingException e ) {
-            throw new ResponseException( Status.BAD_REQUEST,
-                    "Invalid URL path '" + strings + "': " + e.getMessage() );
+            throw new RestconfDocumentedException(
+                    "Invalid URL path '" + strings + "': " + e.getMessage(),
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
     }
 
@@ -818,8 +938,9 @@ public class ControllerContext implements SchemaContextListener {
                 return URLDecoder.decode( pathArg, URI_ENCODING_CHAR_SET );
             }
             catch( UnsupportedEncodingException e ) {
-                throw new ResponseException( Status.BAD_REQUEST,
-                        "Invalid URL path arg '" + pathArg + "': " + e.getMessage() );
+                throw new RestconfDocumentedException(
+                        "Invalid URL path arg '" + pathArg + "': " + e.getMessage(),
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
         }
 
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ResponseException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ResponseException.java
deleted file mode 100644 (file)
index 007fb8e..0000000
+++ /dev/null
@@ -1,27 +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.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-public class ResponseException extends WebApplicationException {
-
-    private static final long serialVersionUID = -5320114450593021655L;
-
-    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/RestconfDocumentedException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfDocumentedException.java
new file mode 100644 (file)
index 0000000..0548e95
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.util.List;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Unchecked exception to communicate error information, as defined in the ietf restcong draft,
+ * to be sent to the client.
+ *
+ * @author Devin Avery
+ * @author Thomas Pantelis
+ * @see {@link https://tools.ietf.org/html/draft-bierman-netconf-restconf-02}
+ */
+public class RestconfDocumentedException extends WebApplicationException {
+
+    private static final long serialVersionUID = 1L;
+
+    private final List<RestconfError> errors;
+    private final Status status;
+
+    /**
+     * Constructs an instance with an error message. The error type defaults to APPLICATION and
+     * the error tag defaults to OPERATION_FAILED.
+     *
+     * @param message A string which provides a plain text string describing the error.
+     */
+    public RestconfDocumentedException( String message ) {
+        this( message, RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED );
+    }
+
+    /**
+     * Constructs an instance with an error message, error type, and error tag.
+     *
+     * @param message A string which provides a plain text string describing the error.
+     * @param errorType The enumerated type indicating the layer where the error occurred.
+     * @param errorTag The enumerated tag representing a more specific error cause.
+     */
+    public RestconfDocumentedException( String message, ErrorType errorType, ErrorTag errorTag ) {
+        this( null, new RestconfError( errorType, errorTag, message ) );
+    }
+
+    /**
+     * Constructs an instance with an error message and exception cause. The stack trace of the
+     * exception is included in the error info.
+     *
+     * @param message A string which provides a plain text string describing the error.
+     * @param cause The underlying exception cause.
+     */
+    public RestconfDocumentedException( String message, Throwable cause ) {
+        this( cause, new RestconfError( RestconfError.ErrorType.APPLICATION,
+                                        RestconfError.ErrorTag.OPERATION_FAILED, message,
+                                        null, RestconfError.toErrorInfo( cause ) ) );
+    }
+
+    /**
+     * Constructs an instance with the given error.
+     */
+    public RestconfDocumentedException( RestconfError error ) {
+        this( null, error );
+    }
+
+    /**
+     * Constructs an instance with the given errors.
+     */
+    public RestconfDocumentedException( List<RestconfError> errors ) {
+        this.errors = ImmutableList.copyOf( errors );
+        Preconditions.checkArgument( !this.errors.isEmpty(), "RestconfError list can't be empty" );
+        status = null;
+    }
+
+    /**
+     * Constructs an instance with an HTTP status and no error information.
+     *
+     * @param status the HTTP status.
+     */
+    public RestconfDocumentedException( Status status ) {
+        Preconditions.checkNotNull( status, "Status can't be null" );
+        errors = ImmutableList.of();
+        this.status = status;
+    }
+
+    private RestconfDocumentedException( Throwable cause, RestconfError error ) {
+        super( cause );
+        Preconditions.checkNotNull( error, "RestconfError can't be null" );
+        errors = ImmutableList.of( error );
+        status = null;
+    }
+
+    public List<RestconfError> getErrors() {
+        return errors;
+    }
+
+    public Status getStatus() {
+        return status;
+    }
+
+
+    @Override
+    public String getMessage() {
+        return "errors: " + errors + (status != null ? ", status: " + status : "");
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfError.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfError.java
new file mode 100644 (file)
index 0000000..9220f8b
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Encapsulates a restconf error as defined in the ietf restconf draft.
+ *
+ * <br><br><b>Note:</b> Enumerations defined within are provided by the ietf restconf draft.
+ *
+ * @author Devin Avery
+ * @see {@link https://tools.ietf.org/html/draft-bierman-netconf-restconf-02}
+ */
+public class RestconfError {
+
+    public static enum ErrorType {
+        /** Errors relating to the transport layer */
+        TRANSPORT,
+        /** Errors relating to the RPC or notification layer */
+        RPC,
+        /** Errors relating to the protocol operation layer. */
+        PROTOCOL,
+        /** Errors relating to the server application layer. */
+        APPLICATION;
+
+        public String getErrorTypeTag() {
+            return name().toLowerCase();
+        }
+
+        public static ErrorType valueOfCaseInsensitive( String value )
+        {
+            try {
+                return ErrorType.valueOf( ErrorType.class, value.toUpperCase() );
+            }
+            catch( IllegalArgumentException e ) {
+                return APPLICATION;
+            }
+        }
+    }
+
+    public static enum ErrorTag {
+        IN_USE( "in-use", Status.fromStatusCode(409)),
+        INVALID_VALUE( "invalid-value", Status.fromStatusCode(400)),
+        TOO_BIG( "too-big", Status.fromStatusCode(413)),
+        MISSING_ATTRIBUTE( "missing-attribute", Status.fromStatusCode(400)),
+        BAD_ATTRIBUTE( "bad-attribute", Status.fromStatusCode(400)),
+        UNKNOWN_ATTRIBUTE( "unknown-attribute", Status.fromStatusCode(400)),
+        BAD_ELEMENT( "bad-element", Status.fromStatusCode(400)),
+        UNKNOWN_ELEMENT( "unknown-element", Status.fromStatusCode(400)),
+        UNKNOWN_NAMESPACE( "unknown-namespace", Status.fromStatusCode(400)),
+        ACCESS_DENIED( "access-denied", Status.fromStatusCode(403)),
+        LOCK_DENIED( "lock-denied", Status.fromStatusCode(409)),
+        RESOURCE_DENIED( "resource-denied", Status.fromStatusCode(409)),
+        ROLLBACK_FAILED( "rollback-failed", Status.fromStatusCode(500)),
+        DATA_EXISTS( "data-exists", Status.fromStatusCode(409)),
+        DATA_MISSING( "data-missing", Status.fromStatusCode(409)),
+        OPERATION_NOT_SUPPORTED( "operation-not-supported", Status.fromStatusCode(501)),
+        OPERATION_FAILED( "operation-failed", Status.fromStatusCode(500)),
+        PARTIAL_OPERATION( "partial-operation", Status.fromStatusCode(500)),
+        MALFORMED_MESSAGE( "malformed-message", Status.fromStatusCode(400));
+
+        private final String tagValue;
+        private final Status statusCode;
+
+        ErrorTag(final String tagValue, final Status statusCode) {
+            this.tagValue = tagValue;
+            this.statusCode = statusCode;
+        }
+
+        public String getTagValue() {
+            return this.tagValue.toLowerCase();
+        }
+
+        public static ErrorTag valueOfCaseInsensitive( String value )
+        {
+            try {
+                return ErrorTag.valueOf( ErrorTag.class, value.toUpperCase().replaceAll( "-","_" ) );
+            }
+            catch( IllegalArgumentException e ) {
+                return OPERATION_FAILED;
+            }
+        }
+
+        public Status getStatusCode() {
+            return statusCode;
+        }
+    }
+
+    private final ErrorType errorType;
+    private final ErrorTag errorTag;
+    private final String errorInfo;
+    private final String errorAppTag;
+    private final String errorMessage;
+    //TODO: Add in the error-path concept as defined in the ietf draft.
+
+    static String toErrorInfo( Throwable cause ) {
+        StringWriter writer = new StringWriter();
+        cause.printStackTrace( new PrintWriter( writer ) );
+        return writer.toString();
+    }
+
+    /**
+     * Constructs a RestConfError
+     *
+     * @param errorType The enumerated type indicating the layer where the error occurred.
+     * @param errorTag The enumerated tag representing a more specific error cause.
+     * @param errorMessage A string which provides a plain text string describing the error.
+     */
+    public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage) {
+        this( errorType, errorTag, errorMessage, null );
+    }
+
+    /**
+     * Constructs a RestConfError object.
+     *
+     * @param errorType The enumerated type indicating the layer where the error occurred.
+     * @param errorTag The enumerated tag representing a more specific error cause.
+     * @param errorMessage A string which provides a plain text string describing the error.
+     * @param errorAppTag A string which represents an application-specific error tag that further
+     *                    specifies the error cause.
+     */
+    public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage,
+                         String errorAppTag) {
+        this( errorType, errorTag, errorMessage, errorAppTag, null );
+    }
+
+    /**
+     * Constructs a RestConfError object.
+     *
+     * @param errorType The enumerated type indicating the layer where the error occurred.
+     * @param errorTag The enumerated tag representing a more specific error cause.
+     * @param errorMessage A string which provides a plain text string describing the error.
+     * @param errorAppTag A string which represents an application-specific error tag that further
+     *                    specifies the error cause.
+     * @param errorInfo A string, <b>formatted as XML</b>, which contains additional error information.
+     */
+    public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage,
+                         String errorAppTag, String errorInfo) {
+        Preconditions.checkNotNull( errorType, "Error type is required for RestConfError" );
+        Preconditions.checkNotNull( errorTag, "Error tag is required for RestConfError");
+        this.errorType = errorType;
+        this.errorTag = errorTag;
+        this.errorMessage = errorMessage;
+        this.errorAppTag = errorAppTag;
+        this.errorInfo = errorInfo;
+    }
+
+    /**
+     * Constructs a RestConfError object from an RpcError.
+     */
+    public RestconfError( RpcError rpcError ) {
+
+        this.errorType = rpcError.getErrorType() == null ? ErrorType.APPLICATION :
+                               ErrorType.valueOfCaseInsensitive( rpcError.getErrorType().name() );
+
+        this.errorTag = rpcError.getTag() == null ? ErrorTag.OPERATION_FAILED :
+                                    ErrorTag.valueOfCaseInsensitive( rpcError.getTag().toString() );
+
+        this.errorMessage = rpcError.getMessage();
+        this.errorAppTag = rpcError.getApplicationTag();
+
+        String errorInfo = null;
+        if( rpcError.getInfo() == null ) {
+            if( rpcError.getCause() != null ) {
+                errorInfo = toErrorInfo( rpcError.getCause() );
+            }
+            else if( rpcError.getSeverity() != null ) {
+                errorInfo = "<severity>" + rpcError.getSeverity().toString().toLowerCase() +
+                            "</severity>";
+            }
+        }
+        else {
+            errorInfo = rpcError.getInfo();
+        }
+
+        this.errorInfo = errorInfo;
+    }
+
+    public ErrorType getErrorType() {
+        return errorType;
+    }
+
+    public ErrorTag getErrorTag() {
+        return errorTag;
+    }
+
+    public String getErrorInfo() {
+        return errorInfo;
+    }
+
+    public String getErrorAppTag() {
+        return errorAppTag;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    @Override
+    public String toString() {
+        return "error-type: " + errorType.getErrorTypeTag()
+                + ", error-tag: " + errorTag.getTagValue() + ", "
+                + (errorAppTag != null ? "error-app-tag: " + errorAppTag + ", " : "")
+                + (errorMessage != null ? "error-message: " + errorMessage : "")
+                + (errorInfo != null ? "error-info: " + errorInfo + ", " : "") + "]";
+    }
+
+}
\ No newline at end of file
index 0b7b693b0c485b5686492ead95a3f3aa75201732..ad682bc8291d50e52d674607e30142009bac459e 100644 (file)
@@ -1,5 +1,6 @@
 /**
  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014 Brocade Communication Systems, Inc.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -7,11 +8,20 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+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.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -23,14 +33,32 @@ import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.commons.lang3.StringUtils;
 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.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.rpc.impl.BrokerRpcExecutor;
+import org.opendaylight.controller.sal.restconf.rpc.impl.MountPointRpcExecutor;
+import org.opendaylight.controller.sal.restconf.rpc.impl.RpcExecutor;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.RestCodec;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 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.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -43,7 +71,6 @@ 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;
@@ -57,42 +84,15 @@ 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 static final int CHAR_NOT_FOUND = -1;
+
     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";
@@ -121,8 +121,8 @@ public class RestconfImpl implements RestconfService {
         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);
+        final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                                        restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
 
         Set<Module> allModules = this.controllerContext.getAllModules();
         for (final Module module : allModules) {
@@ -130,8 +130,8 @@ public class RestconfImpl implements RestconfService {
             modulesAsData.add(moduleCompositeNode);
         }
 
-        final DataSchemaNode modulesSchemaNode =
-                this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+        final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                                   restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
         QName qName = modulesSchemaNode.getQName();
         final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
         return new StructuredData(modulesNode, modulesSchemaNode, null);
@@ -143,14 +143,14 @@ public class RestconfImpl implements RestconfService {
 
         final List<Node<?>> streamsAsData = new ArrayList<Node<?>>();
         Module restconfModule = this.getRestconfModule();
-        final DataSchemaNode streamSchemaNode =
-            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
+        final DataSchemaNode streamSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                                             restconfModule, Draft02.RestConfModule.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);
+        final DataSchemaNode streamsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                                     restconfModule, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
         QName qName = streamsSchemaNode.getQName();
         final CompositeNode streamsNode = NodeFactory.createImmutableCompositeNode(qName, null, streamsAsData);
         return new StructuredData(streamsNode, streamsSchemaNode, null);
@@ -167,22 +167,22 @@ public class RestconfImpl implements RestconfService {
             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);
+            throw new RestconfDocumentedException(
+                    "URI has bad format. If modules behind mount point should be showed, URI has to end with " +
+                    ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
         Module restconfModule = this.getRestconfModule();
-        final DataSchemaNode moduleSchemaNode =
-            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+        final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                                         restconfModule, Draft02.RestConfModule.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);
+        final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                                  restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
         QName qName = modulesSchemaNode.getQName();
         final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
         return new StructuredData(modulesNode, modulesSchemaNode, mountPoint);
@@ -204,14 +204,15 @@ public class RestconfImpl implements RestconfService {
         }
 
         if (module == null) {
-            throw new ResponseException(Status.BAD_REQUEST,
+            throw new RestconfDocumentedException(
                     "Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '" +
-                    moduleNameAndRevision.getRevision() + "' was not found.");
+                    moduleNameAndRevision.getRevision() + "' was not found.",
+                    ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
         }
 
         Module restconfModule = this.getRestconfModule();
-        final DataSchemaNode moduleSchemaNode =
-            this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+        final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                                          restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
         final CompositeNode moduleNode = this.toModuleCompositeNode(module, moduleSchemaNode);
         return new StructuredData(moduleNode, moduleSchemaNode, mountPoint);
     }
@@ -233,9 +234,9 @@ public class RestconfImpl implements RestconfService {
             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);
+            throw new RestconfDocumentedException(
+                    "URI has bad format. If operations behind mount point should be showed, URI has to end with " +
+                    ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         return this.operationsFromModulesToStructuredData(modules, mountPoint);
@@ -245,12 +246,12 @@ public class RestconfImpl implements RestconfService {
                                                                  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);
+        final DataSchemaNode operationsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+                              restconfModule, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
         QName qName = operationsSchemaNode.getQName();
         SchemaPath path = operationsSchemaNode.getPath();
         ContainerSchemaNodeBuilder containerSchemaNodeBuilder =
-                             new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, qName, path);
+                             new ContainerSchemaNodeBuilder(Draft02.RestConfModule.NAME, 0, qName, path);
         final ContainerSchemaNodeBuilder fakeOperationsSchemaNode = containerSchemaNodeBuilder;
         for (final Module module : modules) {
             Set<RpcDefinition> rpcs = module.getRpcs();
@@ -278,11 +279,11 @@ public class RestconfImpl implements RestconfService {
     }
 
     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);
+        Module restconfModule = controllerContext.getRestconfModule();
         if (restconfModule == null) {
-            throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Restconf module was not found.");
+            throw new RestconfDocumentedException(
+                    "ietf-restconf module was not found.", ErrorType.APPLICATION,
+                    ErrorTag.OPERATION_NOT_SUPPORTED );
         }
 
         return restconfModule;
@@ -302,8 +303,9 @@ public class RestconfImpl implements RestconfService {
         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\'");
+            throw new RestconfDocumentedException(
+                    "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         try {
@@ -313,7 +315,9 @@ public class RestconfImpl implements RestconfService {
             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\'");
+            throw new RestconfDocumentedException(
+                    "URI has bad format. It should be \'moduleName/yyyy-MM-dd\'",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
     }
 
@@ -385,66 +389,6 @@ public class RestconfImpl implements RestconfService {
         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;
@@ -452,109 +396,161 @@ public class RestconfImpl implements RestconfService {
 
     @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 RpcExecutor rpc = this.resolveIdentifierInInvokeRpc(identifier);
+        QName rpcName = rpc.getRpcDefinition().getQName();
+        URI rpcNamespace = rpcName.getNamespace();
+        if (Objects.equal(rpcNamespace.toString(), SAL_REMOTE_NAMESPACE) &&
+            Objects.equal(rpcName.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();
+            return invokeSalRemoteRpcSubscribeRPC(payload, rpc.getRpcDefinition());
+        }
 
-            if (!(pathValue instanceof InstanceIdentifier)) {
-                throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
-                                             "Instance identifier was not normalized correctly.");
-            }
+        return callRpc(rpc, payload);
+    }
 
-            final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
-            String streamName = null;
-            if (!Iterables.isEmpty(pathIdentifier.getPath())) {
-                String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
-                streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
-            }
+    private StructuredData invokeSalRemoteRpcSubscribeRPC(final CompositeNode payload,
+                                                          final RpcDefinition rpc) {
+        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 (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.");
-            }
+        if (!(pathValue instanceof InstanceIdentifier)) {
+            throw new RestconfDocumentedException(
+                    "Instance identifier was not normalized correctly.",
+                    ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED );
+        }
+
+        final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
+        String streamName = null;
+        if (!Iterables.isEmpty(pathIdentifier.getPath())) {
+            String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
+            streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
+        }
 
-            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);
+        if (Strings.isNullOrEmpty(streamName)) {
+            throw new RestconfDocumentedException(
+                    "Path is empty or contains data node which is not Container or List build-in type.",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+        }
 
-            final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
-                                                  rpc.getOutput().getQName(), null, output, null, null);
+        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);
 
-            if (!Notificator.existListenerFor(pathIdentifier)) {
-                Notificator.createListener(pathIdentifier, streamName);
-            }
+        final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
+                                              rpc.getOutput().getQName(), null, output, null, null);
 
-            return new StructuredData(responseData, rpc.getOutput(), null);
+        if (!Notificator.existListenerFor(pathIdentifier)) {
+            Notificator.createListener(pathIdentifier, streamName);
         }
 
-        RpcDefinition rpcDefinition = this.controllerContext.getRpcDefinition(identifier);
-        return this.callRpc(rpcDefinition, payload);
+        return new StructuredData(responseData, rpc.getOutput(), null);
     }
 
     @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.");
+        if (StringUtils.isNotBlank(noPayload)) {
+            throw new RestconfDocumentedException(
+                    "Content must be empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
-
-        final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
-        return this.callRpc(rpc, null);
+        final RpcExecutor rpc = resolveIdentifierInInvokeRpc(identifier);
+        return 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;
-            }
+    private RpcExecutor resolveIdentifierInInvokeRpc(final String identifier) {
+        String identifierEncoded = null;
+        MountInstance mountPoint = null;
+        if (identifier.contains(ControllerContext.MOUNT)) {
+            // mounted RPC call - look up mount instance.
+            InstanceIdWithSchemaNode mountPointId = controllerContext
+                    .toMountPointIdentifier(identifier);
+            mountPoint = mountPointId.getMountPoint();
+
+            int startOfRemoteRpcName = identifier.lastIndexOf(ControllerContext.MOUNT)
+                    + ControllerContext.MOUNT.length() + 1;
+            String remoteRpcName = identifier.substring(startOfRemoteRpcName);
+            identifierEncoded = remoteRpcName;
+
+        } else if (identifier.indexOf("/") != CHAR_NOT_FOUND) {
+            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 RestconfDocumentedException(
+                    slashErrorMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+        } else {
+            identifierEncoded = identifier;
+        }
+
+        final String identifierDecoded = controllerContext.urlPathArgDecode(identifierEncoded);
+        RpcDefinition rpc = controllerContext.getRpcDefinition(identifierDecoded);
 
-            throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
+        if (rpc == null) {
+            throw new RestconfDocumentedException(
+                    "RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT );
         }
 
-        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);
+        if (mountPoint == null) {
+            return new BrokerRpcExecutor(rpc, broker);
+        } else {
+            return new MountPointRpcExecutor(rpc, mountPoint);
+        }
 
-        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.");
+    private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload) {
+        if (rpcExecutor == null) {
+            throw new RestconfDocumentedException(
+                    "RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT );
         }
 
         CompositeNode rpcRequest = null;
+        RpcDefinition rpc = rpcExecutor.getRpcDefinition();
+        QName rpcName = rpc.getQName();
+
         if (payload == null) {
-            rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, null, null, null);
-        }
-        else {
+            rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, 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);
+            List<Node<?>> input = Collections.<Node<?>> singletonList(value);
+            rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, null, input, null, null);
         }
 
-        final RpcResult<CompositeNode> rpcResult = broker.invokeRpc(rpc.getQName(), rpcRequest);
+        RpcResult<CompositeNode> rpcResult = rpcExecutor.invokeRpc(rpcRequest);
 
-        if (!rpcResult.isSuccessful()) {
-            throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Operation failed");
-        }
+        checkRpcSuccessAndThrowException(rpcResult);
 
-        CompositeNode result = rpcResult.getResult();
-        if (result == null) {
+        if (rpcResult.getResult() == null) {
             return null;
         }
 
-        return new StructuredData(result, rpc.getOutput(), null);
+        if( rpc.getOutput() == null )
+        {
+            return null; //no output, nothing to send back.
+        }
+
+        return new StructuredData(rpcResult.getResult(), rpc.getOutput(), null);
+    }
+
+    private void checkRpcSuccessAndThrowException(RpcResult<CompositeNode> rpcResult) {
+        if (rpcResult.isSuccessful() == false) {
+
+            Collection<RpcError> rpcErrors = rpcResult.getErrors();
+            if( rpcErrors == null || rpcErrors.isEmpty() ) {
+                throw new RestconfDocumentedException(
+                    "The operation was not successful and there were no RPC errors returned",
+                    ErrorType.RPC, ErrorTag.OPERATION_FAILED );
+            }
+
+            List<RestconfError> errorList = Lists.newArrayList();
+            for( RpcError rpcError: rpcErrors ) {
+                errorList.add( new RestconfError( rpcError ) );
+            }
+
+            throw new RestconfDocumentedException( errorList );
+        }
     }
 
     @Override
@@ -603,7 +599,7 @@ public class RestconfImpl implements RestconfService {
             }
         }
         catch( Exception e ) {
-            throw new ResponseException( e, "Error updating data" );
+            throw new RestconfDocumentedException( "Error updating data", e );
         }
 
         if( status.getResult() == TransactionStatus.COMMITED )
@@ -616,8 +612,9 @@ public class RestconfImpl implements RestconfService {
     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)");
+            throw new RestconfDocumentedException(
+                 "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)",
+                 ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE );
         }
 
         InstanceIdWithSchemaNode iiWithData = null;
@@ -626,9 +623,10 @@ public class RestconfImpl implements RestconfService {
              // 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.");
+                throw new RestconfDocumentedException(
+                        "URI has bad format. URI should be without \"" + ControllerContext.MOUNT +
+                        "\" for POST operation.",
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
 
             final String completeIdentifier = this.addMountPointIdentifier(identifier);
@@ -643,8 +641,9 @@ public class RestconfImpl implements RestconfService {
             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 + "\"");
+                throw new RestconfDocumentedException(
+                        "Module was not found for \"" + payloadNS + "\"",
+                        ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
             }
 
             String payloadName = this.getName(payload);
@@ -670,9 +669,8 @@ public class RestconfImpl implements RestconfService {
                 status = future == null ? null : future.get();
             }
         }
-        catch( ResponseException e) { throw e; }
         catch( Exception e ) {
-            throw new ResponseException( e, "Error creating data" );
+            throw new RestconfDocumentedException( "Error creating data", e );
         }
 
         if (status == null) {
@@ -689,14 +687,16 @@ public class RestconfImpl implements RestconfService {
     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)");
+            throw new RestconfDocumentedException(
+                "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)",
+                ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE );
         }
 
         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)");
+            throw new RestconfDocumentedException(
+                    "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)",
+                    ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE );
         }
 
         String payloadName = this.getName(payload);
@@ -720,9 +720,8 @@ public class RestconfImpl implements RestconfService {
                 status = future == null ? null : future.get();
             }
         }
-        catch( ResponseException e) { throw e; }
         catch( Exception e ) {
-            throw new ResponseException( e, "Error creating data" );
+            throw new RestconfDocumentedException( "Error creating data", e );
         }
 
         if (status == null) {
@@ -751,7 +750,7 @@ public class RestconfImpl implements RestconfService {
             }
         }
         catch( Exception e ) {
-            throw new ResponseException( e, "Error creating data" );
+            throw new RestconfDocumentedException( "Error creating data", e );
         }
 
         if( status.getResult() == TransactionStatus.COMMITED )
@@ -764,12 +763,14 @@ public class RestconfImpl implements RestconfService {
     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.");
+            throw new RestconfDocumentedException(
+                    "Stream name is empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         final ListenerAdapter listener = Notificator.getListenerFor(streamName);
         if (listener == null) {
-            throw new ResponseException(Status.BAD_REQUEST, "Stream was not found.");
+            throw new RestconfDocumentedException(
+                    "Stream was not found.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
         }
 
         broker.registerToListenDataChanges(listener);
@@ -873,9 +874,10 @@ public class RestconfImpl implements RestconfService {
             }
 
             if (dataNodeKeyValueObject == null) {
-                throw new ResponseException(Status.BAD_REQUEST,
-                            "Data contains list \"" + dataNode.getNodeType().getLocalName() +
-                            "\" which does not contain key: \"" + key.getLocalName() + "\"");
+                throw new RestconfDocumentedException(
+                        "Data contains list \"" + dataNode.getNodeType().getLocalName() +
+                        "\" which does not contain key: \"" + key.getLocalName() + "\"",
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
 
             keyValues.put(key, dataNodeKeyValueObject);
@@ -910,14 +912,16 @@ public class RestconfImpl implements RestconfService {
         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 );
+
+            throw new RestconfDocumentedException(
+                    "Data schema node was not found for " + localName,
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         if (!(schema instanceof DataNodeContainer)) {
-            throw new ResponseException(Status.BAD_REQUEST,
-                                        "Root element has to be container or list yang datatype.");
+            throw new RestconfDocumentedException(
+                    "Root element has to be container or list yang datatype.",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         if ((node instanceof CompositeNodeWrapper)) {
@@ -926,8 +930,9 @@ public class RestconfImpl implements RestconfService {
                 try {
                     this.normalizeNode(((CompositeNodeWrapper) node), schema, null, mountPoint);
                 }
-                catch (NumberFormatException e) {
-                    throw new ResponseException(Status.BAD_REQUEST, e.getMessage());
+                catch (IllegalArgumentException e) {
+                    throw new RestconfDocumentedException(
+                                    e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
                 }
             }
 
@@ -941,9 +946,10 @@ public class RestconfImpl implements RestconfService {
                                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.");
+            throw new RestconfDocumentedException(
+                    "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
+                    "\" does not exist in yang schema.",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         QName currentAugment = null;
@@ -953,13 +959,14 @@ public class RestconfImpl implements RestconfService {
         else {
             currentAugment = this.normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint);
             if (nodeBuilder.getQname() == null) {
-                throw new ResponseException(Status.BAD_REQUEST,
+                throw new RestconfDocumentedException(
                         "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() + "\".");
+                        schema.getQName().getNamespace() + "\".",
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
         }
 
@@ -977,11 +984,12 @@ public class RestconfImpl implements RestconfService {
                                .append("\n");
                     }
 
-                    throw new ResponseException(Status.BAD_REQUEST,
+                    throw new RestconfDocumentedException(
                                  "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);
+                                 "\nThe node is added as augment from modules with namespaces:\n" + builder,
+                                 ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
                 }
 
                 boolean rightNodeSchemaFound = false;
@@ -997,8 +1005,9 @@ public class RestconfImpl implements RestconfService {
                 }
 
                 if (!rightNodeSchemaFound) {
-                    throw new ResponseException(Status.BAD_REQUEST,
-                                      "Schema node \"" + child.getLocalName() + "\" was not found in module.");
+                    throw new RestconfDocumentedException(
+                               "Schema node \"" + child.getLocalName() + "\" was not found in module.",
+                               ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT );
                 }
             }
 
@@ -1013,9 +1022,10 @@ public class RestconfImpl implements RestconfService {
                     }
 
                     if (!foundKey) {
-                        throw new ResponseException(Status.BAD_REQUEST,
+                        throw new RestconfDocumentedException(
                                        "Missing key in URI \"" + listKey.getLocalName() +
-                                       "\" of list \"" + schema.getQName().getLocalName() + "\"");
+                                       "\" of list \"" + schema.getQName().getLocalName() + "\"",
+                                       ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
                     }
                 }
             }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/AbstractRpcExecutor.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/AbstractRpcExecutor.java
new file mode 100644 (file)
index 0000000..0bc8428
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public abstract class AbstractRpcExecutor implements RpcExecutor {
+    private final RpcDefinition rpcDef;
+
+    public AbstractRpcExecutor( RpcDefinition rpcDef ){
+        this.rpcDef = rpcDef;
+    }
+
+    @Override
+    public RpcDefinition getRpcDefinition() {
+        return rpcDef;
+    }
+
+    protected RpcResult<CompositeNode> getRpcResult(
+                                            Future<RpcResult<CompositeNode>> fromFuture ) {
+        try {
+            return fromFuture.get();
+        }
+        catch( InterruptedException e ) {
+            throw new RestconfDocumentedException(
+                        "The operation was interrupted while executing and did not complete.",
+                        ErrorType.RPC, ErrorTag.PARTIAL_OPERATION );
+        }
+        catch( ExecutionException e ) {
+            Throwable cause = e.getCause();
+            if( cause instanceof CancellationException ) {
+                throw new RestconfDocumentedException(
+                        "The operation was cancelled while executing.",
+                        ErrorType.RPC, ErrorTag.PARTIAL_OPERATION );
+            }
+            else if( cause != null ){
+                while( cause.getCause() != null ) {
+                    cause = cause.getCause();
+                }
+
+                if( cause instanceof IllegalArgumentException ) {
+                    throw new RestconfDocumentedException(
+                            cause.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+                }
+
+                throw new RestconfDocumentedException(
+                       "The operation encountered an unexpected error while executing.", cause );
+            }
+            else {
+                throw new RestconfDocumentedException(
+                        "The operation encountered an unexpected error while executing.", e );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/BrokerRpcExecutor.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/BrokerRpcExecutor.java
new file mode 100644 (file)
index 0000000..249b657
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public class BrokerRpcExecutor extends AbstractRpcExecutor {
+    private final BrokerFacade broker;
+
+    public BrokerRpcExecutor( RpcDefinition rpcDef, BrokerFacade broker )
+    {
+        super( rpcDef );
+        this.broker = broker;
+    }
+
+    @Override
+    public RpcResult<CompositeNode> invokeRpc(CompositeNode rpcRequest) {
+        return getRpcResult( broker.invokeRpc( getRpcDefinition().getQName(), rpcRequest ) );
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/MountPointRpcExecutor.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/MountPointRpcExecutor.java
new file mode 100644 (file)
index 0000000..da19a00
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Provides an implementation which invokes rpc methods via a mounted yang data model.
+ * @author Devin Avery
+ *
+ */
+public class MountPointRpcExecutor extends AbstractRpcExecutor {
+    private final MountInstance mountPoint;
+
+    public MountPointRpcExecutor(RpcDefinition rpcDef, MountInstance mountPoint) {
+        super( rpcDef );
+        this.mountPoint = mountPoint;
+        Preconditions.checkNotNull( mountPoint, "MountInstance can not be null." );
+    }
+
+    @Override
+    public RpcResult<CompositeNode> invokeRpc( CompositeNode rpcRequest )
+                                                   throws RestconfDocumentedException {
+        return getRpcResult( mountPoint.rpc( getRpcDefinition().getQName(), rpcRequest ) );
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/RpcExecutor.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/RpcExecutor.java
new file mode 100644 (file)
index 0000000..f628a63
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public interface RpcExecutor {
+    RpcResult<CompositeNode> invokeRpc( CompositeNode rpcRequest );
+
+    RpcDefinition getRpcDefinition();
+}
\ No newline at end of file
index 874e8b0d1f8f5e7cf151a4c548624b01d72576a5..d978a2f0de25af2f26c106dea7c79a759fea4ce0 100644 (file)
@@ -85,7 +85,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         verifyJsonOutput(jsonOutput);
     }
 
-    private void verifyJsonOutputForEmptyData(String jsonOutput) {
+    private void verifyJsonOutputForEmptyData(final String jsonOutput) {
         assertNotNull(jsonOutput);
         StringReader strReader = new StringReader(jsonOutput);
         JsonReader jReader = new JsonReader(strReader);
@@ -104,7 +104,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         assertNull("Error during reading Json output: " + exception, exception);
     }
 
-    private void verifyJsonOutput(String jsonOutput) {
+    private void verifyJsonOutput(final String jsonOutput) {
         assertNotNull(jsonOutput);
         StringReader strReader = new StringReader(jsonOutput);
         JsonReader jReader = new JsonReader(strReader);
@@ -123,7 +123,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         assertNull("Error during reading Json output: " + exception, exception);
     }
 
-    private Cont jsonReadCont1(JsonReader jReader) throws IOException {
+    private Cont jsonReadCont1(final JsonReader jReader) throws IOException {
         jReader.beginObject();
         assertNotNull("cont1 is missing.", jReader.hasNext());
 
@@ -136,7 +136,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private Cont jsonReadCont1Elements(JsonReader jReader, Cont redData) throws IOException {
+    private Cont jsonReadCont1Elements(final JsonReader jReader, final Cont redData) throws IOException {
         jReader.beginObject();
         while (jReader.hasNext()) {
             String keyName = jReader.nextName();
@@ -163,7 +163,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private Lst jsonReadLst11(JsonReader jReader, Lst lst) throws IOException {
+    private Lst jsonReadLst11(final JsonReader jReader, final Lst lst) throws IOException {
         jReader.beginArray();
 
         while (jReader.hasNext()) {
@@ -174,7 +174,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lst;
     }
 
-    private LstItem jsonReadLst11Elements(JsonReader jReader) throws IOException {
+    private LstItem jsonReadLst11Elements(final JsonReader jReader) throws IOException {
         LstItem lstItem = new LstItem();
         jReader.beginObject();
         while (jReader.hasNext()) {
@@ -203,7 +203,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lstItem;
     }
 
-    private Lst jsonReadLst112(JsonReader jReader, Lst lst) throws IOException {
+    private Lst jsonReadLst112(final JsonReader jReader, final Lst lst) throws IOException {
         jReader.beginArray();
         while (jReader.hasNext()) {
             LstItem lstItem = jsonReadLst112Elements(jReader);
@@ -213,7 +213,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lst;
     }
 
-    private LstItem jsonReadLst112Elements(JsonReader jReader) throws IOException {
+    private LstItem jsonReadLst112Elements(final JsonReader jReader) throws IOException {
         LstItem lstItem = new LstItem();
         jReader.beginObject();
         if (jReader.hasNext()) {
@@ -227,7 +227,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private Lst jsonReadLst111(JsonReader jReader, Lst lst) throws IOException {
+    private Lst jsonReadLst111(final JsonReader jReader, final Lst lst) throws IOException {
         jReader.beginArray();
         while (jReader.hasNext()) {
             LstItem lstItem = jsonReadLst111Elements(jReader);
@@ -237,7 +237,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lst;
     }
 
-    private LstItem jsonReadLst111Elements(JsonReader jReader) throws IOException {
+    private LstItem jsonReadLst111Elements(final JsonReader jReader) throws IOException {
         LstItem lstItem = new LstItem();
         jReader.beginObject();
         if (jReader.hasNext()) {
@@ -250,7 +250,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lstItem;
     }
 
-    private Object nextValue(JsonReader jReader) throws IOException {
+    private Object nextValue(final JsonReader jReader) throws IOException {
         if (jReader.peek().equals(JsonToken.NULL)) {
             jReader.nextNull();
             return null;
@@ -261,14 +261,14 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         }
     }
 
-    private Cont jsonReadCont111(JsonReader jReader, Cont cont) throws IOException {
+    private Cont jsonReadCont111(final JsonReader jReader, Cont cont) throws IOException {
         jReader.beginObject();
         cont = jsonReadCont111Elements(jReader, cont);
         jReader.endObject();
         return cont;
     }
 
-    private Cont jsonReadCont111Elements(JsonReader jReader, Cont cont) throws IOException {
+    private Cont jsonReadCont111Elements(final JsonReader jReader, final Cont cont) throws IOException {
         while (jReader.hasNext()) {
             String keyName = jReader.nextName();
             if (keyName.equals("lf1111")) {
@@ -289,7 +289,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private Lst jsonReadLst1111(JsonReader jReader, Lst lst) throws IOException {
+    private Lst jsonReadLst1111(final JsonReader jReader, final Lst lst) throws IOException {
         jReader.beginArray();
         while (jReader.hasNext()) {
             LstItem lstItem = jsonReadLst1111Elements(jReader);
@@ -299,7 +299,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lst;
     }
 
-    private LstItem jsonReadLst1111Elements(JsonReader jReader) throws IOException {
+    private LstItem jsonReadLst1111Elements(final JsonReader jReader) throws IOException {
         jReader.beginObject();
         LstItem lstItem = new LstItem();
         while (jReader.hasNext()) {
@@ -312,7 +312,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lstItem;
     }
 
-    private LfLst jsonReadLflstValues(JsonReader jReader, LfLst lfLst) throws IOException {
+    private LfLst jsonReadLflstValues(final JsonReader jReader, final LfLst lfLst) throws IOException {
         jReader.beginArray();
         while (jReader.hasNext()) {
             lfLst.addLf(new Lf(nextValue(jReader)));
@@ -321,7 +321,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         return lfLst;
     }
 
-    private void checkDataFromJsonEmpty(Cont dataFromJson) {
+    private void checkDataFromJsonEmpty(final Cont dataFromJson) {
         assertTrue(dataFromJson.getLfs().isEmpty());
         assertTrue(dataFromJson.getLfLsts().isEmpty());
         assertTrue(dataFromJson.getConts().isEmpty());
@@ -357,9 +357,9 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         assertEquals(1, lst11_1.getLsts().size());
         assertEquals(
                 lst11_1.getLsts().get("lst111"),
-                new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", (int) 35))
-                        .addLstItem(new LstItem().addLf("lf1111", (int) 34)).addLstItem(new LstItem())
-                        .addLstItem(new LstItem()));
+                new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", 35))
+                .addLstItem(new LstItem().addLf("lf1111", 34)).addLstItem(new LstItem())
+                .addLstItem(new LstItem()));
         assertEquals(lst11_1.getConts().get("cont111"), new Cont("cont111"));
         // : lst11_1
 
@@ -378,10 +378,10 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         assertEquals(1, lst11_2_cont111.getLsts().size());
         assertTrue(lst11_2_cont111.getConts().isEmpty());
 
-        assertEquals(new LfLst("lflst1111").addLf((int) 1024).addLf((int) 4096),
+        assertEquals(new LfLst("lflst1111").addLf(1024).addLf(4096),
                 lst11_2_cont111.getLfLsts().get("lflst1111"));
         assertEquals(
-                new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", (int) 4)).addLstItem(
+                new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", 4)).addLstItem(
                         new LstItem().addLf("lf1111A", "lf1111A str12")), lst11_2_cont111.getLsts().get("lst1111"));
         // :-cont111
         assertEquals(lst11_2.getLsts().get("lst112"), new Lst("lst112").addLstItem(new LstItem()));
@@ -407,7 +407,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private void checkDataFromJson(Cont dataFromJson) {
+    private void checkDataFromJson(final Cont dataFromJson) {
         assertNotNull(dataFromJson.getLfs().get("lf11"));
         assertEquals(dataFromJson.getLfs().get("lf11"), new Lf("lf11", "lf"));
 
@@ -450,7 +450,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         checkLst11_2(lst11_2);
     }
 
-    private void checkLst11_2(LstItem lst11_2) {
+    private void checkLst11_2(final LstItem lst11_2) {
         assertNotNull(lst11_2);
         assertEquals(2, lst11_2.getLfs().size());
         assertEquals(1, lst11_2.getConts().size());
@@ -479,7 +479,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
                 new LstItem().addLf(new Lf("lf1121", "lf1121 str21")));
     }
 
-    private void checkLst11_1(LstItem lst11_1) {
+    private void checkLst11_1(final LstItem lst11_1) {
         assertNotNull(lst11_1);
 
         assertEquals(2, lst11_1.getLfs().size());
@@ -507,7 +507,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         checkLst11x(lst11_1.getLsts().get("lst112"), new LstItem().addLf(new Lf("lf1121", "lf1121 str11")));
     }
 
-    private void checkLst11x(Lst lst, LstItem... lstItems) {
+    private void checkLst11x(final Lst lst, final LstItem... lstItems) {
         assertNotNull(lst);
 
         Lst requiredLst = new Lst(lst.getName());
@@ -519,7 +519,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private void checkLst1111(Set<LstItem> lstItems, Lf lf11, Lf lf12, Lf lf21, Lf lf22) {
+    private void checkLst1111(final Set<LstItem> lstItems, final Lf lf11, final Lf lf12, final Lf lf21, final Lf lf22) {
         LstItem lst11_1_cont_lst1111_1 = null;
         LstItem lst11_1_cont_lst1111_2 = null;
         for (LstItem lstItem : lstItems) {
@@ -541,49 +541,49 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         // lst11_1
         MutableCompositeNode lst11_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1,
                 null, ModifyAction.CREATE, null);
-        cont1.getChildren().add(lst11_1);
+        cont1.getValue().add(lst11_1);
 
         MutableSimpleNode<?> lf111_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_1,
                 (short) 1, ModifyAction.CREATE, null);
-        lst11_1.getChildren().add(lf111_1);
+        lst11_1.getValue().add(lf111_1);
 
         // lst111_1_1
         MutableCompositeNode lst111_1_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
                 lst11_1, null, ModifyAction.CREATE, null);
-        lst11_1.getChildren().add(lst111_1_1);
+        lst11_1.getValue().add(lst111_1_1);
         MutableSimpleNode<?> lf1111_1_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111","simple:yang:types","2013-11-5"),
-                lst111_1_1, (int) 34, ModifyAction.CREATE, null);
-        lst111_1_1.getChildren().add(lf1111_1_1);
+                lst111_1_1, 34, ModifyAction.CREATE, null);
+        lst111_1_1.getValue().add(lf1111_1_1);
         lst111_1_1.init();
         // :lst111_1_1
 
         // lst111_1_2
         MutableCompositeNode lst111_1_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
                 lst11_1, null, ModifyAction.CREATE, null);
-        lst11_1.getChildren().add(lst111_1_2);
+        lst11_1.getValue().add(lst111_1_2);
         MutableSimpleNode<?> lf1111_1_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111","simple:yang:types","2013-11-5"),
-                lst111_1_2, (int) 35, ModifyAction.CREATE, null);
-        lst111_1_2.getChildren().add(lf1111_1_2);
+                lst111_1_2, 35, ModifyAction.CREATE, null);
+        lst111_1_2.getValue().add(lf1111_1_2);
         lst111_1_2.init();
         // :lst111_1_2
 
         // lst111_1_3
         MutableCompositeNode lst111_1_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
                 lst11_1, null, ModifyAction.CREATE, null);
-        lst11_1.getChildren().add(lst111_1_3);
+        lst11_1.getValue().add(lst111_1_3);
         lst111_1_2.init();
         // :lst111_1_3
 
         // lst111_1_4
         MutableCompositeNode lst111_1_4 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
                 lst11_1, null, ModifyAction.CREATE, null);
-        lst11_1.getChildren().add(lst111_1_4);
+        lst11_1.getValue().add(lst111_1_4);
         lst111_1_2.init();
         // :lst111_1_4
 
         MutableCompositeNode cont111_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"),
                 lst11_1, null, ModifyAction.CREATE, null);
-        lst11_1.getChildren().add(cont111_1);
+        lst11_1.getValue().add(cont111_1);
 
         lst11_1.init();
         // :lst11_1
@@ -591,39 +591,39 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         // lst11_2
         MutableCompositeNode lst11_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1,
                 null, ModifyAction.CREATE, null);
-        cont1.getChildren().add(lst11_2);
+        cont1.getValue().add(lst11_2);
 
         MutableSimpleNode<?> lf111_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_2,
                 (short) 2, ModifyAction.CREATE, null);
-        lst11_2.getChildren().add(lf111_2);
+        lst11_2.getValue().add(lf111_2);
 
         // cont111_2
         MutableCompositeNode cont111_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"),
                 lst11_2, null, ModifyAction.CREATE, null);
-        lst11_2.getChildren().add(cont111_2);
+        lst11_2.getValue().add(cont111_2);
 
         MutableSimpleNode<?> lflst1111_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111","simple:yang:types","2013-11-5"),
-                cont111_2, (int) 1024, ModifyAction.CREATE, null);
-        cont111_2.getChildren().add(lflst1111_2_2);
+                cont111_2, 1024, ModifyAction.CREATE, null);
+        cont111_2.getValue().add(lflst1111_2_2);
         MutableSimpleNode<?> lflst1111_2_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111","simple:yang:types","2013-11-5"),
-                cont111_2, (int) 4096, ModifyAction.CREATE, null);
-        cont111_2.getChildren().add(lflst1111_2_3);
+                cont111_2, 4096, ModifyAction.CREATE, null);
+        cont111_2.getValue().add(lflst1111_2_3);
 
         // lst1111_2
         MutableCompositeNode lst1111_2_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
                 cont111_2, null, ModifyAction.CREATE, null);
-        cont111_2.getChildren().add(lst1111_2_1);
+        cont111_2.getValue().add(lst1111_2_1);
         MutableSimpleNode<?> lf1111B_2_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111B","simple:yang:types","2013-11-5"),
                 lst1111_2_1, (short) 4, ModifyAction.CREATE, null);
-        lst1111_2_1.getChildren().add(lf1111B_2_1);
+        lst1111_2_1.getValue().add(lf1111B_2_1);
         lst1111_2_1.init();
 
         MutableCompositeNode lst1111_2_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
                 cont111_2, null, ModifyAction.CREATE, null);
-        cont111_2.getChildren().add(lst1111_2_2);
+        cont111_2.getValue().add(lst1111_2_2);
         MutableSimpleNode<?> lf1111A_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111A","simple:yang:types","2013-11-5"),
                 lst1111_2_2, "lf1111A str12", ModifyAction.CREATE, null);
-        lst1111_2_2.getChildren().add(lf1111A_2_2);
+        lst1111_2_2.getValue().add(lf1111A_2_2);
         lst1111_2_2.init();
         // :lst1111_2
 
@@ -632,7 +632,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
 
         MutableCompositeNode lst112_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst112","simple:yang:types","2013-11-5"), lst11_2,
                 null, ModifyAction.CREATE, null);
-        lst11_2.getChildren().add(lst112_2);
+        lst11_2.getValue().add(lst112_2);
         lst112_2.init();
         lst11_2.init();
 
@@ -641,25 +641,25 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
         // lst11_3
         MutableCompositeNode lst11_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1,
                 null, ModifyAction.CREATE, null);
-        cont1.getChildren().add(lst11_3);
+        cont1.getValue().add(lst11_3);
 
         MutableSimpleNode<?> lf111_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_3,
                 (short) 3, ModifyAction.CREATE, null);
-        lst11_3.getChildren().add(lf111_3);
+        lst11_3.getValue().add(lf111_3);
 
         // cont111_3
         MutableCompositeNode cont111_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"),
                 lst11_3, null, ModifyAction.CREATE, null);
-        lst11_3.getChildren().add(cont111_3);
+        lst11_3.getValue().add(cont111_3);
 
         MutableCompositeNode lst1111_3_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
                 cont111_3, null, ModifyAction.CREATE, null);
-        cont111_3.getChildren().add(lst1111_3_1);
+        cont111_3.getValue().add(lst1111_3_1);
         lst1111_3_1.init();
 
         MutableCompositeNode lst1111_3_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
                 cont111_3, null, ModifyAction.CREATE, null);
-        cont111_3.getChildren().add(lst1111_3_2);
+        cont111_3.getValue().add(lst1111_3_2);
         lst1111_3_2.init();
 
         cont111_3.init();
index 745f11c210db6c44f90ba97ccacfd6624dc1eb4e..fdd3aa6684303babcabc9c849792e37c6cbf758e 100644 (file)
@@ -73,17 +73,17 @@ public class CnSnToJsonIdentityrefTest extends YangAndXmlAndDataSchemaLoader {
         assertTrue(mtch.matches());
     }
 
-    private CompositeNode prepareCompositeNode(Object value) {
+    private CompositeNode prepareCompositeNode(final Object value) {
         MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont","identityref:module","2013-12-2"), null, null,
                 ModifyAction.CREATE, null);
         MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont1","identityref:module","2013-12-2"), cont, null,
                 ModifyAction.CREATE, null);
-        cont.getChildren().add(cont1);
+        cont.getValue().add(cont1);
 
         MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1","identityref:module","2013-12-2"), cont1, value,
                 ModifyAction.CREATE, null);
 
-        cont1.getChildren().add(lf1);
+        cont1.getValue().add(lf1);
         cont1.init();
         cont.init();
 
index dd1502ba79f5c1325aefbeca443fde34e997da90..42e1e3f739a002259e4b833dd1e9dbafdb373b78 100644 (file)
@@ -27,6 +27,7 @@ import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
 import org.slf4j.Logger;
@@ -46,7 +47,7 @@ public class CnSnToJsonNotExistingLeafTypeTest extends YangAndXmlAndDataSchemaLo
         String jsonOutput = null;
         jsonOutput = TestUtils
                 .writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(),
-                        Collections.EMPTY_SET, prepareDataSchemaNode(),
+                        Collections.<Module>emptySet(), prepareDataSchemaNode(),
                         StructuredDataToJsonProvider.INSTANCE);
         assertNotNull(jsonOutput);
         assertTrue(jsonOutput.contains("\"lf1\": \"\""));
@@ -57,7 +58,7 @@ public class CnSnToJsonNotExistingLeafTypeTest extends YangAndXmlAndDataSchemaLo
                 TestUtils.buildQName("cont", "simple:uri", "2012-12-17"), null, null, ModifyAction.CREATE, null);
         MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(
                 TestUtils.buildQName("lf1", "simple:uri", "2012-12-17"), cont, "any value", ModifyAction.CREATE, null);
-        cont.getChildren().add(lf1);
+        cont.getValue().add(lf1);
         cont.init();
         return cont;
     }
index 348edbd2945d6d1fb2f86ea0d1e3026a81132c47..052bb1a2be762ffca684a54109f724bd4d188ce9 100644 (file)
@@ -99,32 +99,32 @@ public class CnSnToJsonWithDataFromSeveralModulesTest extends YangAndXmlAndDataS
 
         MutableCompositeNode cont_m1 = NodeFactory.createMutableCompositeNode(
                 TestUtils.buildQName("cont_m1", uri1, rev1), data, null, null, null);
-        data.getChildren().add(cont_m1);
+        data.getValue().add(cont_m1);
 
         MutableSimpleNode<?> lf1_m1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1_m1", uri1, rev1),
                 cont_m1, "lf1 m1 value", null, null);
-        cont_m1.getChildren().add(lf1_m1);
+        cont_m1.getValue().add(lf1_m1);
         cont_m1.init();
 
         MutableCompositeNode contB_m1 = NodeFactory.createMutableCompositeNode(
                 TestUtils.buildQName("contB_m1", uri1, rev1), data, null, null, null);
-        data.getChildren().add(contB_m1);
+        data.getValue().add(contB_m1);
         contB_m1.init();
 
         String uri2 = "module:two";
         String rev2 = "2014-01-17";
         MutableCompositeNode cont_m2 = NodeFactory.createMutableCompositeNode(
                 TestUtils.buildQName("cont_m2", uri2, rev2), data, null, null, null);
-        data.getChildren().add(cont_m2);
+        data.getValue().add(cont_m2);
 
         MutableSimpleNode<?> lf1_m2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1_m2", uri2, rev2),
                 cont_m1, "lf1 m2 value", null, null);
-        cont_m2.getChildren().add(lf1_m2);
+        cont_m2.getValue().add(lf1_m2);
         cont_m2.init();
 
         MutableCompositeNode contB_m2 = NodeFactory.createMutableCompositeNode(
                 TestUtils.buildQName("contB_m2", uri2, rev2), data, null, null, null);
-        data.getChildren().add(contB_m2);
+        data.getValue().add(contB_m2);
         contB_m2.init();
 
         data.init();
index f81c1d63f5af572509a76e2fa5b1da05bafa71bb..2ada6e13e9a64c2e62101f693027e3686645d025 100644 (file)
@@ -25,6 +25,7 @@ import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
 import org.slf4j.Logger;
@@ -41,7 +42,7 @@ public class CnSnToXmlNotExistingLeafTypeTest {
         boolean nullPointerExceptionRaised = false;
         try {
             TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(),
-                    Collections.EMPTY_SET, prepareDataSchemaNode(), StructuredDataToXmlProvider.INSTANCE);
+                    Collections.<Module>emptySet(), prepareDataSchemaNode(), StructuredDataToXmlProvider.INSTANCE);
         } catch (WebApplicationException | IOException e) {
             LOG.error("WebApplicationException or IOException was raised");
         } catch (NullPointerException e) {
@@ -56,7 +57,7 @@ public class CnSnToXmlNotExistingLeafTypeTest {
                 TestUtils.buildQName("cont", "simple:uri", "2012-12-17"), null, null, ModifyAction.CREATE, null);
         MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(
                 TestUtils.buildQName("lf1", "simple:uri", "2012-12-17"), cont, "any value", ModifyAction.CREATE, null);
-        cont.getChildren().add(lf1);
+        cont.getValue().add(lf1);
         cont.init();
         return cont;
     }
index 6b4b15325238dd84e39f6745f1d9f6731fb85d2e..fc54795fcce5a468cb0d6e780f561a3052fe2eeb 100644 (file)
@@ -28,11 +28,11 @@ import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
 
 /**
- * 
+ *
  * CnSn = Composite node and Simple node data structure Class contains test of
  * serializing simple nodes data values according data types from YANG schema to
  * XML file
- * 
+ *
  */
 public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
     @BeforeClass
@@ -139,9 +139,9 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
         serializeToXml(
                 prepareCnStructForYangData(
                         TypeDefinitionAwareCodec.BINARY_DEFAULT_CODEC
-                                .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"),
+                        .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"),
                         elName), "<" + elName + ">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567</"
-                        + elName + ">");
+                                + elName + ">");
     }
 
     @Test
@@ -198,7 +198,7 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
                         + elName + ">str</" + elName + ">");
     }
 
-    private void serializeToXml(CompositeNode compositeNode, String... xmlRepresentation)
+    private void serializeToXml(final CompositeNode compositeNode, final String... xmlRepresentation)
             throws TransformerFactoryConfigurationError {
         String xmlString = "";
         try {
@@ -220,12 +220,12 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private CompositeNode prepareIdentityrefData(String prefix, boolean valueAsQName) {
+    private CompositeNode prepareIdentityrefData(final String prefix, final boolean valueAsQName) {
         MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
                 TestUtils.buildQName("cont", "basic:module", "2013-12-2"), null, null, ModifyAction.CREATE, null);
         MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
                 TestUtils.buildQName("cont1", "basic:module", "2013-12-2"), cont, null, ModifyAction.CREATE, null);
-        cont.getChildren().add(cont1);
+        cont.getValue().add(cont1);
 
         Object value = null;
         if (valueAsQName) {
@@ -235,20 +235,20 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
         }
         MutableSimpleNode<Object> lf11 = NodeFactory.createMutableSimpleNode(
                 TestUtils.buildQName("lf11", "basic:module", "2013-12-2"), cont1, value, ModifyAction.CREATE, null);
-        cont1.getChildren().add(lf11);
+        cont1.getValue().add(lf11);
         cont1.init();
         cont.init();
 
         return cont;
     }
 
-    private CompositeNode prepareCnStructForYangData(Object data, String leafName) {
+    private CompositeNode prepareCnStructForYangData(final Object data, final String leafName) {
         MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
                 ModifyAction.CREATE, null);
 
         MutableSimpleNode<Object> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(leafName), cont, data,
                 ModifyAction.CREATE, null);
-        cont.getChildren().add(lf1);
+        cont.getValue().add(lf1);
         cont.init();
 
         return cont;
@@ -262,8 +262,8 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
                 cont, Boolean.TRUE, ModifyAction.CREATE, null);
         MutableSimpleNode<Object> lfLfref = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfLfref"), cont,
                 "true", ModifyAction.CREATE, null);
-        cont.getChildren().add(lfBoolean);
-        cont.getChildren().add(lfLfref);
+        cont.getValue().add(lfBoolean);
+        cont.getValue().add(lfLfref);
         cont.init();
 
         return cont;
index a3e33ce30b6eca4192215a6cc21bc0402abb8897..ac7fe20818f31fc7fbb5bfd24b4399b2113cadee 100644 (file)
@@ -18,15 +18,18 @@ import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
 /**
- * 
+ *
  * CnSn = Composite node and Simple node data structure Class contains test of
  * serializing simple nodes data values according data types from YANG schema to
  * XML file
- * 
+ *
  */
 public class CnSnToXmlWithChoiceTest extends YangAndXmlAndDataSchemaLoader {
     @BeforeClass
@@ -56,13 +59,13 @@ public class CnSnToXmlWithChoiceTest extends YangAndXmlAndDataSchemaLoader {
 
     }
 
-    private CompositeNode prepareCnStructForYangData(String lfName, Object data) {
+    private CompositeNode prepareCnStructForYangData(final String lfName, final Object data) {
         MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
                 ModifyAction.CREATE, null);
 
         MutableSimpleNode<Object> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(lfName), cont, data,
                 ModifyAction.CREATE, null);
-        cont.getChildren().add(lf1);
+        cont.getValue().add(lf1);
         cont.init();
 
         return cont;
index 9e726baf55d29254e41692081fe3f64017247062..0c9e95173fd3f1e309b6e512a90260eaf8bbb899 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 
@@ -17,7 +19,9 @@ import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 
 public class JsonIdentityrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
@@ -36,13 +40,13 @@ public class JsonIdentityrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
-        List<Node<?>> childs = compositeNode.getChildren();
+        List<Node<?>> childs = compositeNode.getValue();
         assertEquals(1, childs.size());
         Node<?> nd = childs.iterator().next();
         assertTrue(nd instanceof CompositeNode);
         assertEquals("cont1", nd.getNodeType().getLocalName());
 
-        childs = ((CompositeNode) nd).getChildren();
+        childs = ((CompositeNode) nd).getValue();
         assertEquals(4, childs.size());
         SimpleNode<?> lf11 = null;
         SimpleNode<?> lf12 = null;
index 2030d9125a142032e340b3025eeb078a5434a00d..79dd026fd0dc5cf21b69d7dae886070b009a5999 100644 (file)
@@ -7,14 +7,18 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 
 public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
@@ -37,7 +41,7 @@ public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
         SimpleNode<?> lf2 = null;
-        for (Node<?> childNode : compositeNode.getChildren()) {
+        for (Node<?> childNode : compositeNode.getValue()) {
             if (childNode instanceof SimpleNode) {
                 if (childNode.getNodeType().getLocalName().equals("lf2")) {
                     lf2 = (SimpleNode<?>) childNode;
@@ -48,7 +52,7 @@ public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
         assertNotNull(lf2);
         assertTrue(lf2.getValue() instanceof String);
-        assertEquals("121", (String) lf2.getValue());
+        assertEquals("121", lf2.getValue());
 
     }
 
index 8b1dc3475f6f9f986c61658124942e7f1804d234..3c70cca0f87806d28b73273423fa7b546b1631c6 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -16,13 +15,11 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import javax.ws.rs.WebApplicationException;
-
 import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -32,8 +29,6 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.gson.JsonSyntaxException;
-
 public class JsonToCnSnTest {
 
     private static final Logger LOG = LoggerFactory.getLogger(JsonToCnSnTest.class);
@@ -58,13 +53,13 @@ public class JsonToCnSnTest {
         CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-leaflist-items.json", true,
                 JsonToCompositeNodeProvider.INSTANCE);
         assertNotNull(compositeNode);
-        assertEquals(3, compositeNode.getChildren().size());
+        assertEquals(3, compositeNode.getValue().size());
 
         boolean lflst1_1 = false;
         boolean lflst1_2 = false;
         boolean lflst1_3 = false;
 
-        for (Node<?> node : compositeNode.getChildren()) {
+        for (Node<?> node : compositeNode.getValue()) {
             assertEquals("lflst1", node.getNodeType().getLocalName());
             assertTrue(node instanceof SimpleNode<?>);
             SimpleNode<?> simpleNode = (SimpleNode<?>) node;
@@ -105,9 +100,9 @@ public class JsonToCnSnTest {
         assertNotNull(compositeNode);
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
-        assertNotNull(compositeNode.getChildren());
-        assertEquals(1, compositeNode.getChildren().size());
-        Node<?> lfNode = compositeNode.getChildren().iterator().next();
+        assertNotNull(compositeNode.getValue());
+        assertEquals(1, compositeNode.getValue().size());
+        Node<?> lfNode = compositeNode.getValue().iterator().next();
 
         assertTrue(lfNode instanceof SimpleNode<?>);
         assertEquals(null, ((SimpleNode<?>) lfNode).getValue());
@@ -116,44 +111,39 @@ public class JsonToCnSnTest {
 
     @Test
     public void incorrectTopLevelElementsTest() {
-        Throwable cause1 = null;
+        RestconfDocumentedException cause1 = null;
         try {
-            TestUtils
-                    .readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE);
-        } catch (WebApplicationException e) {
+            TestUtils.readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE);
+        } catch (RestconfDocumentedException e) {
             cause1 = e;
         }
 
         assertNotNull(cause1);
-        assertTrue(cause1
-                .getCause()
-                .getMessage()
-                .contains(
-                        "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
+        assertTrue(cause1.getErrors().get( 0 ).getErrorMessage().contains(
+            "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
 
-        Throwable cause2 = null;
+        RestconfDocumentedException cause2 = null;
         try {
             TestUtils
                     .readInputToCnSn("/json-to-cnsn/wrong-top-level2.json", true, JsonToCompositeNodeProvider.INSTANCE);
-        } catch (WebApplicationException e) {
+        } catch (RestconfDocumentedException e) {
             cause2 = e;
         }
         assertNotNull(cause2);
-        assertTrue(cause2.getCause().getMessage().contains("Json Object should contain one element"));
+        assertTrue(cause2.getErrors().get( 0 ).getErrorMessage().contains(
+                                                     "Json Object should contain one element"));
 
-        Throwable cause3 = null;
+        RestconfDocumentedException cause3 = null;
         try {
             TestUtils
+
                     .readInputToCnSn("/json-to-cnsn/wrong-top-level3.json", true, JsonToCompositeNodeProvider.INSTANCE);
-        } catch (WebApplicationException e) {
+        } catch (RestconfDocumentedException e) {
             cause3 = e;
         }
         assertNotNull(cause3);
-        assertTrue(cause3
-                .getCause()
-                .getMessage()
-                .contains(
-                        "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
+        assertTrue(cause3.getErrors().get( 0 ).getErrorMessage().contains(
+            "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
 
     }
 
@@ -170,7 +160,7 @@ public class JsonToCnSnTest {
 
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
         assertTrue(compositeNode instanceof CompositeNode);
-        List<Node<?>> children = ((CompositeNode) compositeNode).getChildren();
+        List<Node<?>> children = compositeNode.getValue();
         assertEquals(1, children.size());
         assertEquals("lflst2", children.get(0).getNodeType().getLocalName());
         assertEquals("45", children.get(0).getValue());
@@ -178,8 +168,8 @@ public class JsonToCnSnTest {
         String reason = null;
         try {
             TestUtils.readInputToCnSn("/json-to-cnsn/empty-data1.json", true, JsonToCompositeNodeProvider.INSTANCE);
-        } catch (JsonSyntaxException e) {
-            reason = e.getMessage();
+        } catch (RestconfDocumentedException e) {
+            reason = e.getErrors().get( 0 ).getErrorMessage();
         }
 
         assertTrue(reason.contains("Expected value at line"));
@@ -190,7 +180,7 @@ public class JsonToCnSnTest {
      * Tests whether namespace <b>stay unchanged</b> if concrete values are
      * present in composite or simple node and if the method for update is
      * called.
-     * 
+     *
      */
     @Test
     public void notSupplyNamespaceIfAlreadySupplied() {
@@ -233,13 +223,13 @@ public class JsonToCnSnTest {
 
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
-        List<Node<?>> childs = compositeNode.getChildren();
+        List<Node<?>> childs = compositeNode.getValue();
         assertEquals(1, childs.size());
         Node<?> nd = childs.iterator().next();
         assertTrue(nd instanceof CompositeNode);
         assertEquals("cont1", nd.getNodeType().getLocalName());
 
-        childs = ((CompositeNode) nd).getChildren();
+        childs = ((CompositeNode) nd).getValue();
         assertEquals(4, childs.size());
         SimpleNode<?> lf11 = null;
         SimpleNode<?> lf12 = null;
@@ -274,28 +264,22 @@ public class JsonToCnSnTest {
         assertEquals("iden_local", ((QName) lf14.getValue()).getLocalName());
         assertEquals("identity:module", ((QName) lf14.getValue()).getNamespace().toString());
     }
-    
+
     @Ignore
     @Test
     public void loadDataAugmentedSchemaMoreEqualNamesTest() {
-        boolean exceptionCaught = false;
-        try {
-            loadAndNormalizeData("/common/augment/json/dataa.json", "/common/augment/yang", "cont", "main");
-            loadAndNormalizeData("/common/augment/json/datab.json", "/common/augment/yang", "cont", "main");
-        } catch (ResponseException e) {
-            exceptionCaught = true;
-        }
-        
-        assertFalse(exceptionCaught);
+        loadAndNormalizeData("/common/augment/json/dataa.json", "/common/augment/yang", "cont", "main");
+        loadAndNormalizeData("/common/augment/json/datab.json", "/common/augment/yang", "cont", "main");
+
     }
 
-    private void simpleTest(String jsonPath, String yangPath, String topLevelElementName, String namespace,
-            String moduleName) {
+    private void simpleTest(final String jsonPath, final String yangPath, final String topLevelElementName, final String namespace,
+            final String moduleName) {
         CompositeNode compNode = loadAndNormalizeData(jsonPath, yangPath, topLevelElementName, moduleName);
         verifyCompositeNode(compNode, namespace);
     }
 
-    private CompositeNode loadAndNormalizeData(String jsonPath, String yangPath, String topLevelElementName, String moduleName) {
+    private CompositeNode loadAndNormalizeData(final String jsonPath, final String yangPath, final String topLevelElementName, final String moduleName) {
         CompositeNode compositeNode = TestUtils.readInputToCnSn(jsonPath, false, JsonToCompositeNodeProvider.INSTANCE);
         assertNotNull(compositeNode);
 
@@ -312,8 +296,8 @@ public class JsonToCnSnTest {
         return compNode;
     }
 
-    private void verityMultipleItemsInList(CompositeNode compositeNode) {
-        List<Node<?>> childrenNodes = compositeNode.getChildren();
+    private void verityMultipleItemsInList(final CompositeNode compositeNode) {
+        List<Node<?>> childrenNodes = compositeNode.getValue();
         assertEquals(4, childrenNodes.size());
         boolean lf11Found = false;
         boolean cont11Found = false;
@@ -322,7 +306,7 @@ public class JsonToCnSnTest {
             assertEquals("lst1", lst1Item.getNodeType().getLocalName());
             assertTrue(lst1Item instanceof CompositeNode);
 
-            List<Node<?>> childrenLst1 = ((CompositeNode) lst1Item).getChildren();
+            List<Node<?>> childrenLst1 = ((CompositeNode) lst1Item).getValue();
             assertEquals(1, childrenLst1.size());
             String localName = childrenLst1.get(0).getNodeType().getLocalName();
             if (localName.equals("lf11")) {
@@ -338,7 +322,7 @@ public class JsonToCnSnTest {
             } else if (localName.equals("lst11")) {
                 lst11Found = true;
                 assertTrue(childrenLst1.get(0) instanceof CompositeNode);
-                assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getChildren().size());
+                assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getValue().size());
             }
 
         }
@@ -347,7 +331,7 @@ public class JsonToCnSnTest {
         assertTrue(lst11Found);
     }
 
-    private void verifyCompositeNode(CompositeNode compositeNode, String namespace) {
+    private void verifyCompositeNode(final CompositeNode compositeNode, final String namespace) {
         boolean cont1Found = false;
         boolean lst1Found = false;
         boolean lflst1_1Found = false;
@@ -357,16 +341,16 @@ public class JsonToCnSnTest {
         // assertEquals(namespace,
         // compositeNode.getNodeType().getNamespace().toString());
 
-        for (Node<?> node : compositeNode.getChildren()) {
+        for (Node<?> node : compositeNode.getValue()) {
             if (node.getNodeType().getLocalName().equals("cont1")) {
                 if (node instanceof CompositeNode) {
                     cont1Found = true;
-                    assertEquals(0, ((CompositeNode) node).getChildren().size());
+                    assertEquals(0, ((CompositeNode) node).getValue().size());
                 }
             } else if (node.getNodeType().getLocalName().equals("lst1")) {
                 if (node instanceof CompositeNode) {
                     lst1Found = true;
-                    assertEquals(0, ((CompositeNode) node).getChildren().size());
+                    assertEquals(0, ((CompositeNode) node).getValue().size());
                 }
             } else if (node.getNodeType().getLocalName().equals("lflst1")) {
                 if (node instanceof SimpleNode) {
@@ -399,8 +383,8 @@ public class JsonToCnSnTest {
         try {
             TestUtils.readInputToCnSn("/json-to-cnsn/unsupported-json-format.json", true,
                     JsonToCompositeNodeProvider.INSTANCE);
-        } catch (WebApplicationException e) {
-            exceptionMessage = e.getCause().getMessage();
+        } catch (RestconfDocumentedException e) {
+            exceptionMessage = e.getErrors().get( 0 ).getErrorMessage();
         }
         assertTrue(exceptionMessage.contains("Root element of Json has to be Object"));
     }
index 18199de8c63ca056ed8aacbf947fe0d36f2afa0d..ddab7004408f4d60aa3e89f8660f8aa9749bce7b 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
@@ -19,8 +20,6 @@ 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;
@@ -34,7 +33,8 @@ 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.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
 import org.opendaylight.controller.sal.streams.listeners.Notificator;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -120,7 +120,7 @@ public class BrokerFacadeTest {
         assertSame( "readOperationalDataBehindMountPoint", dataNode, actualNode );
     }
 
-    @Test(expected=ResponseException.class)
+    @Test(expected=RestconfDocumentedException.class)
     public void testReadOperationalDataWithNoDataBroker() {
         brokerFacade.setDataService( null );
 
@@ -129,26 +129,19 @@ public class BrokerFacadeTest {
 
     @SuppressWarnings("unchecked")
     @Test
-    public void testInvokeRpc() {
+    public void testInvokeRpc() throws Exception {
         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 );
+        Future<RpcResult<CompositeNode>> actualFuture = brokerFacade.invokeRpc( qname, dataNode );
+        assertNotNull( "Future is null", actualFuture );
+        RpcResult<CompositeNode> actualResult = actualFuture.get();
 
         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)
+    @Test(expected=RestconfDocumentedException.class)
     public void testInvokeRpcWithNoConsumerSession() {
         brokerFacade.setContext( null );
 
@@ -218,7 +211,7 @@ public class BrokerFacadeTest {
         inOrder.verify( mockTransaction ).commit();
     }
 
-    @Test(expected=ResponseException.class)
+    @Test(expected=RestconfDocumentedException.class)
     public void testCommitConfigurationDataPostAlreadyExists() {
         when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
         mockTransaction.putConfigurationData( instanceID, dataNode );
@@ -226,10 +219,10 @@ public class BrokerFacadeTest {
             .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());
+        }
+        catch (RestconfDocumentedException e) {
+            assertEquals("getErrorTag",
+                    RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get( 0 ).getErrorTag());
             throw e;
         }
     }
@@ -259,7 +252,7 @@ public class BrokerFacadeTest {
         inOrder.verify( mockTransaction ).commit();
     }
 
-    @Test(expected=ResponseException.class)
+    @Test(expected=RestconfDocumentedException.class)
     public void testCommitConfigurationDataPostBehindMountPointAlreadyExists() {
 
         when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
@@ -269,10 +262,10 @@ public class BrokerFacadeTest {
         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());
+        }
+        catch (RestconfDocumentedException e) {
+            assertEquals("getErrorTag",
+                    RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get( 0 ).getErrorTag());
             throw e;
         }
     }
index 0492b3efd4f1b7a1696c1452a5d69ee9fec07c12..07d781028b99feaa03cd8dc610f499f63a0ca1dc 100644 (file)
@@ -64,7 +64,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
     @Ignore
     @Test
     public void saveCnSnWithLeafListInstIdentifierToXmlTest() throws WebApplicationException, IOException,
-            URISyntaxException, XMLStreamException {
+    URISyntaxException, XMLStreamException {
         CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList());
         String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
                 StructuredDataToXmlProvider.INSTANCE);
@@ -94,7 +94,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
 
     @Test
     public void saveCnSnWithLeafListInstIdentifierToJsonTest() throws WebApplicationException, IOException,
-            URISyntaxException {
+    URISyntaxException {
         CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList());
         String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
                 StructuredDataToJsonProvider.INSTANCE);
@@ -111,7 +111,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
         assertTrue(strInOutput);
     }
 
-    private void validateXmlOutput(String xml) throws XMLStreamException {
+    private void validateXmlOutput(final String xml) throws XMLStreamException {
         XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
         XMLEventReader eventReader;
 
@@ -152,7 +152,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
 
     }
 
-    private void validateXmlOutputWithLeafList(String xml) throws XMLStreamException {
+    private void validateXmlOutputWithLeafList(final String xml) throws XMLStreamException {
         XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
         XMLEventReader eventReader;
 
@@ -188,7 +188,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
 
     }
 
-    private CompositeNode prepareCnSn(InstanceIdentifier instanceIdentifier) throws URISyntaxException {
+    private CompositeNode prepareCnSn(final InstanceIdentifier instanceIdentifier) throws URISyntaxException {
         MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
                 TestUtils.buildQName("cont", "instance:identifier:module", "2014-01-17"), null, null,null,null);
         MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
@@ -200,13 +200,13 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
                 lst11, instanceIdentifier,null,null);
 
 
-        lst11.getChildren().add(lf111);
+        lst11.getValue().add(lf111);
         lst11.init();
 
-        cont1.getChildren().add(lst11);
+        cont1.getValue().add(lst11);
         cont1.init();
 
-        cont.getChildren().add(cont1);
+        cont.getValue().add(cont1);
         cont.init();
 
         return cont;
index 767aaf36c149a9a61763d71f9e7722f997e9a595..51687e2a1285601e4efff6c3737001a9f12488f3 100644 (file)
@@ -14,6 +14,7 @@ import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -46,6 +47,7 @@ public class CodecsExceptionsCatchingTest extends JerseyTest {
         resourceConfig = resourceConfig.registerInstances(restConf, StructuredDataToXmlProvider.INSTANCE,
                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
                 JsonToCompositeNodeProvider.INSTANCE);
+        resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
         return resourceConfig;
     }
 
index 5689a8287578d6bdc00b165df9b81264675c6385..c0c86c3f25384fdbd3ea979debef62fa7f1512ab 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014 Brocade Communications Systems, Inc.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -9,51 +10,81 @@ package org.opendaylight.controller.sal.restconf.impl.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.io.FileNotFoundException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 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 com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class InvokeRpcMethodTest {
 
-    private static Set<Module> modules;
+    private RestconfImpl restconfImpl = null;
+    private static ControllerContext controllerContext = null;
 
-    private class AnswerImpl implements Answer<RpcResult<CompositeNode>> {
-        @Override
-        public RpcResult<CompositeNode> answer(InvocationOnMock invocation) throws Throwable {
-            CompositeNode compNode = (CompositeNode) invocation.getArguments()[1];
-            return new DummyRpcResult.Builder<CompositeNode>().result(compNode).isSuccessful(true).build();
-        }
-    }
 
     @BeforeClass
-    public static void initialization() {
-        modules = TestUtils.loadModulesFrom("/invoke-rpc");
-        assertEquals(1, modules.size());
-        Module module = TestUtils.resolveModule("invoke-rpc-module", modules);
+    public static void init() throws FileNotFoundException {
+        Set<Module> allModules = new HashSet<Module>( TestUtils
+                .loadModulesFrom("/full-versions/yangs") );
+        allModules.addAll( TestUtils.loadModulesFrom("/invoke-rpc") );
+        assertNotNull(allModules);
+        Module module = TestUtils.resolveModule("invoke-rpc-module", allModules);
         assertNotNull(module);
+        SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+        controllerContext = spy( ControllerContext.getInstance() );
+        controllerContext.setSchemas(schemaContext);
+
+    }
+
+    @Before
+    public void initMethod()
+    {
+        restconfImpl = RestconfImpl.getInstance();
+        restconfImpl.setControllerContext( controllerContext );
     }
 
     /**
@@ -63,9 +94,8 @@ public class InvokeRpcMethodTest {
      * from string - first argument).
      */
     @Test
-    public void invokeRpcMethodTest() {
-        ControllerContext contContext = ControllerContext.getInstance();
-        contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules));
+    public void invokeRpcMtethodTest() {
+        ControllerContext contContext = controllerContext;
         try {
             contContext.findModuleNameByNamespace(new URI("invoke:rpc:module"));
         } catch (URISyntaxException e) {
@@ -78,24 +108,14 @@ public class InvokeRpcMethodTest {
         restconf.setBroker(mockedBrokerFacade);
         restconf.setControllerContext(contContext);
 
-        when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenAnswer(new AnswerImpl());
+        CompositeNode payload = preparePayload();
 
-        StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", preparePayload());
+        when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class)))
+            .thenReturn( Futures.<RpcResult<CompositeNode>>immediateFuture(
+                                               Rpcs.<CompositeNode>getRpcResult( true ) ) );
 
-        CompositeNode rpcCompNode = structData.getData();
-        CompositeNode cont = null;
-        assertEquals("invoke:rpc:module", rpcCompNode.getNodeType().getNamespace().toString());
-        assertEquals("rpc-test", rpcCompNode.getNodeType().getLocalName());
-
-        for (Node<?> node : rpcCompNode.getChildren()) {
-            if (node.getNodeType().getLocalName().equals("cont")
-                    && node.getNodeType().getNamespace().toString().equals("nmspc")) {
-                if (node instanceof CompositeNode) {
-                    cont = (CompositeNode) node;
-                }
-            }
-        }
-        assertNotNull(cont);
+        StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", payload);
+        assertTrue(structData == null);
 
     }
 
@@ -104,10 +124,215 @@ public class InvokeRpcMethodTest {
                 TestUtils.buildQName("cont", "nmspc", "2013-12-04"), null, null, ModifyAction.CREATE, null);
         MutableSimpleNode<?> lf = NodeFactory.createMutableSimpleNode(
                 TestUtils.buildQName("lf", "nmspc", "2013-12-04"), cont, "any value", ModifyAction.CREATE, null);
-        cont.getChildren().add(lf);
+        cont.getValue().add(lf);
         cont.init();
 
         return cont;
     }
 
+    @Test
+    public void testInvokeRpcWithNoPayloadRpc_FailNoErrors() {
+        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( false );
+
+        BrokerFacade brokerFacade = mock(BrokerFacade.class);
+        when( brokerFacade.invokeRpc(
+                 eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+                 any(CompositeNode.class)))
+            .thenReturn( Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ) );
+
+        restconfImpl.setBroker(brokerFacade);
+
+        try {
+            restconfImpl.invokeRpc("toaster:cancel-toast", "");
+            fail("Expected an exception to be thrown.");
+        }
+        catch (RestconfDocumentedException e) {
+            verifyRestconfDocumentedException( e, 0, ErrorType.RPC, ErrorTag.OPERATION_FAILED,
+                                               Optional.<String>absent(), Optional.<String>absent() );
+        }
+    }
+
+    void verifyRestconfDocumentedException( final RestconfDocumentedException e, final int index,
+                                            final ErrorType expErrorType, final ErrorTag expErrorTag,
+                                            final Optional<String> expErrorMsg,
+                                            final Optional<String> expAppTag ) {
+        RestconfError actual = null;
+        try {
+            actual = e.getErrors().get( index );
+        }
+        catch( ArrayIndexOutOfBoundsException ex ) {
+            fail( "RestconfError not found at index " + index );
+        }
+
+        assertEquals( "getErrorType", expErrorType, actual.getErrorType() );
+        assertEquals( "getErrorTag", expErrorTag, actual.getErrorTag() );
+        assertNotNull( "getErrorMessage is null", actual.getErrorMessage() );
+
+        if( expErrorMsg.isPresent() ) {
+            assertEquals( "getErrorMessage", expErrorMsg.get(), actual.getErrorMessage() );
+        }
+
+        if( expAppTag.isPresent() ) {
+            assertEquals( "getErrorAppTag", expAppTag.get(), actual.getErrorAppTag() );
+        }
+    }
+
+    @Test
+    public void testInvokeRpcWithNoPayloadRpc_FailWithRpcError() {
+        List<RpcError> rpcErrors = Arrays.asList(
+            RpcErrors.getRpcError( null, "bogusTag", null, ErrorSeverity.ERROR, "foo",
+                                   RpcError.ErrorType.TRANSPORT, null ),
+            RpcErrors.getRpcError( "app-tag", "in-use", null, ErrorSeverity.WARNING, "bar",
+                                   RpcError.ErrorType.RPC, null ));
+
+        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( false, rpcErrors );
+
+        BrokerFacade brokerFacade = mock(BrokerFacade.class);
+        when( brokerFacade.invokeRpc(
+                 eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+                 any(CompositeNode.class)))
+            .thenReturn( Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ) );
+
+        restconfImpl.setBroker(brokerFacade);
+
+        try {
+            restconfImpl.invokeRpc("toaster:cancel-toast", "");
+            fail("Expected an exception to be thrown.");
+        }
+        catch (RestconfDocumentedException e) {
+            verifyRestconfDocumentedException( e, 0, ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED,
+                                               Optional.of( "foo" ), Optional.<String>absent() );
+            verifyRestconfDocumentedException( e, 1, ErrorType.RPC, ErrorTag.IN_USE,
+                                               Optional.of( "bar" ), Optional.of( "app-tag" ) );
+        }
+    }
+
+    @Test
+    public void testInvokeRpcWithNoPayload_Success() {
+        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( true );
+
+        BrokerFacade brokerFacade = mock(BrokerFacade.class);
+        when( brokerFacade.invokeRpc(
+                 eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+                 any( CompositeNode.class )))
+            .thenReturn( Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ) );
+
+        restconfImpl.setBroker(brokerFacade);
+
+        StructuredData output = restconfImpl.invokeRpc("toaster:cancel-toast",
+                "");
+        assertEquals(null, output);
+        //additional validation in the fact that the restconfImpl does not throw an exception.
+    }
+
+    @Test
+    public void testInvokeRpcMethodExpectingNoPayloadButProvidePayload() {
+        try {
+            restconfImpl.invokeRpc("toaster:cancel-toast", " a payload ");
+            fail("Expected an exception");
+        } catch (RestconfDocumentedException e) {
+            verifyRestconfDocumentedException( e, 0, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+                                               Optional.<String>absent(), Optional.<String>absent() );
+        }
+    }
+
+    @Test
+    public void testInvokeRpcMethodWithBadMethodName() {
+        try {
+            restconfImpl.invokeRpc("toaster:bad-method", "");
+            fail("Expected an exception");
+        }
+        catch (RestconfDocumentedException e) {
+            verifyRestconfDocumentedException( e, 0, ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT,
+                                               Optional.<String>absent(), Optional.<String>absent() );
+        }
+    }
+
+    @Test
+    public void testInvokeRpcMethodWithInput() {
+        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( true );
+
+        CompositeNode payload = mock(CompositeNode.class);
+
+        BrokerFacade brokerFacade = mock(BrokerFacade.class);
+        when( brokerFacade.invokeRpc(
+                 eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)make-toast")),
+                 any(CompositeNode.class)))
+            .thenReturn( Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ) );
+
+        restconfImpl.setBroker(brokerFacade);
+
+        StructuredData output = restconfImpl.invokeRpc("toaster:make-toast",
+                payload);
+        assertEquals(null, output);
+        //additional validation in the fact that the restconfImpl does not throw an exception.
+    }
+
+    @Test
+    public void testThrowExceptionWhenSlashInModuleName() {
+        try {
+            restconfImpl.invokeRpc("toaster/slash", "");
+            fail("Expected an exception.");
+        }
+        catch (RestconfDocumentedException e) {
+            verifyRestconfDocumentedException( e, 0, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+                                               Optional.<String>absent(), Optional.<String>absent() );
+        }
+    }
+
+    @Test
+    public void testInvokeRpcWithNoPayloadWithOutput_Success() {
+        CompositeNode compositeNode = mock( CompositeNode.class );
+        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( true, compositeNode,
+                                                            Collections.<RpcError>emptyList() );
+
+        BrokerFacade brokerFacade = mock(BrokerFacade.class);
+        when( brokerFacade.invokeRpc(
+                        eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)testOutput")),
+                        any( CompositeNode.class )))
+            .thenReturn( Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ) );
+
+        restconfImpl.setBroker(brokerFacade);
+
+        StructuredData output = restconfImpl.invokeRpc("toaster:testOutput", "");
+        assertNotNull( output );
+        assertSame( compositeNode, output.getData() );
+        assertNotNull( output.getSchema() );
+    }
+
+    @Test
+    public void testMountedRpcCallNoPayload_Success() throws Exception
+    {
+        RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( true );
+
+        ListenableFuture<RpcResult<CompositeNode>> mockListener = mock( ListenableFuture.class );
+        when( mockListener.get() ).thenReturn( rpcResult );
+
+        QName cancelToastQName = QName.create( "cancelToast" );
+
+        RpcDefinition mockRpc = mock( RpcDefinition.class );
+        when( mockRpc.getQName() ).thenReturn( cancelToastQName );
+
+        MountInstance mockMountPoint = mock( MountInstance.class );
+        when( mockMountPoint.rpc( eq( cancelToastQName ), any( CompositeNode.class ) ) )
+        .thenReturn( mockListener );
+
+        InstanceIdWithSchemaNode mockedInstanceId = mock( InstanceIdWithSchemaNode.class );
+        when( mockedInstanceId.getMountPoint() ).thenReturn( mockMountPoint );
+
+        ControllerContext mockedContext = mock( ControllerContext.class );
+        String cancelToastStr = "toaster:cancel-toast";
+        when( mockedContext.urlPathArgDecode( cancelToastStr ) ).thenReturn( cancelToastStr );
+        when( mockedContext.getRpcDefinition( cancelToastStr ) ).thenReturn( mockRpc );
+        when( mockedContext.toMountPointIdentifier(  "opendaylight-inventory:nodes/node/"
+                + "REMOTE_HOST/yang-ext:mount/toaster:cancel-toast" ) ).thenReturn( mockedInstanceId );
+
+        restconfImpl.setControllerContext( mockedContext );
+        StructuredData output = restconfImpl.invokeRpc(
+                "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/toaster:cancel-toast",
+                "");
+        assertEquals(null, output);
+
+        //additional validation in the fact that the restconfImpl does not throw an exception.
+    }
 }
index 6d2723c2f17391e8fff4d30e983d236aa5e39c10..f5aa453fa245d2e4f9273350f35dcb1c47cfbd47 100644 (file)
@@ -15,7 +15,7 @@ import java.net.URISyntaxException;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
@@ -26,48 +26,28 @@ public class NormalizeNodeTest extends YangAndXmlAndDataSchemaLoader {
         dataLoad("/normalize-node/yang/");
     }
 
-    @Test
+    @Test(expected=RestconfDocumentedException.class)
     public void namespaceNotNullAndInvalidNamespaceAndNoModuleNameTest() {
-        boolean exceptionReised = false;
-        try {
-            TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath);
-        } catch (ResponseException e) {
-            exceptionReised = true;
-        }
-        assertTrue(exceptionReised);
+
+        TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath);
     }
 
     @Test
     public void namespaceNullTest() {
-        String exceptionMessage = null;
-        try {
-            TestUtils.normalizeCompositeNode(prepareCnSn(null), modules, schemaNodePath);
-        } catch (ResponseException e) {
-            exceptionMessage = String.valueOf(e.getResponse().getEntity());
-        }
-        assertNull(exceptionMessage);
+
+        TestUtils.normalizeCompositeNode(prepareCnSn(null), modules, schemaNodePath);
     }
 
     @Test
     public void namespaceValidNamespaceTest() {
-        String exceptionMessage = null;
-        try {
-            TestUtils.normalizeCompositeNode(prepareCnSn("normalize:node:module"), modules, schemaNodePath);
-        } catch (ResponseException e) {
-            exceptionMessage = String.valueOf(e.getResponse().getEntity());
-        }
-        assertNull(exceptionMessage);
+
+        TestUtils.normalizeCompositeNode(prepareCnSn("normalize:node:module"), modules, schemaNodePath);
     }
 
     @Test
     public void namespaceValidModuleNameTest() {
-        String exceptionMessage = null;
-        try {
-            TestUtils.normalizeCompositeNode(prepareCnSn("normalize-node-module"), modules, schemaNodePath);
-        } catch (ResponseException e) {
-            exceptionMessage = String.valueOf(e.getResponse().getEntity());
-        }
-        assertNull(exceptionMessage);
+
+        TestUtils.normalizeCompositeNode(prepareCnSn("normalize-node-module"), modules, schemaNodePath);
     }
 
     private CompositeNode prepareCnSn(String namespace) {
index a6391894c2f044dd13d98518db473c952e44d1e8..53183c611cf54329d5555b2de8b56b01cedfdf0d 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.restconf.impl.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.FileNotFoundException;
 
@@ -18,16 +19,16 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 public class RestGetAugmentedElementWhenEqualNamesTest {
-    
+
     private static ControllerContext controllerContext = ControllerContext.getInstance();
-    
+
     @Rule
     public ExpectedException exception = ExpectedException.none();
-    
+
     @BeforeClass
     public static void init() throws FileNotFoundException {
         SchemaContext schemaContextTestModule = TestUtils.loadSchemaContext("/common/augment/yang");
@@ -41,17 +42,15 @@ public class RestGetAugmentedElementWhenEqualNamesTest {
         iiWithData = controllerContext.toInstanceIdentifier("main:cont/augment-main-b:cont1");
         assertEquals("ns:augment:main:b", iiWithData.getSchemaNode().getQName().getNamespace().toString());
     }
-    
+
     @Test
     public void nodeWithoutNamespaceHasMoreAugments() {
-        boolean exceptionCaught = false;
         try {
             controllerContext.toInstanceIdentifier("main:cont/cont1");
-        } catch (ResponseException e) {
-            assertTrue(((String) e.getResponse().getEntity()).contains("is added as augment from more than one module"));
-            exceptionCaught = true;
+            fail( "Expected exception" );
+        } catch (RestconfDocumentedException e) {
+            assertTrue(e.getErrors().get( 0 ).getErrorMessage().contains(
+                                    "is added as augment from more than one module"));
         }
-        assertTrue(exceptionCaught);
     }
-
 }
index 4198e20b838e15391c650f5ffd34afdcc5693840..893622f60a18ae8a0b8e5e394f9631d0f418374c 100644 (file)
@@ -34,11 +34,11 @@ import javax.ws.rs.core.Response;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 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.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -92,6 +92,7 @@ public class RestGetOperationTest extends JerseyTest {
         resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
                 JsonToCompositeNodeProvider.INSTANCE);
+        resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
         return resourceConfig;
     }
 
@@ -145,15 +146,15 @@ public class RestGetOperationTest extends JerseyTest {
 
     /**
      * MountPoint test. URI represents mount point.
-     * 
+     *
      * Slashes in URI behind mount point. lst1 element with key
      * GigabitEthernet0%2F0%2F0%2F0 (GigabitEthernet0/0/0/0) is requested via
      * GET HTTP operation. It is tested whether %2F character is replaced with
      * simple / in InstanceIdentifier parameter in method
      * {@link BrokerFacade#readConfigurationDataBehindMountPoint(MountInstance, InstanceIdentifier)}
      * which is called in method {@link RestconfImpl#readConfigurationData}
-     * 
-     * 
+     *
+     *
      * @throws ParseException
      */
     @Test
index c6e2f1434371ed9fbd4e294ed7661d2acb5d3c38..ce460fe4746d9137f0775f6536297e5cc841ab44 100644 (file)
@@ -38,6 +38,7 @@ import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountService;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -52,6 +53,8 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
+import com.google.common.util.concurrent.Futures;
+
 public class RestPostOperationTest extends JerseyTest {
 
     private static String xmlDataAbsolutePath;
@@ -99,6 +102,7 @@ public class RestPostOperationTest extends JerseyTest {
         resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
                 JsonToCompositeNodeProvider.INSTANCE);
+        resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
         return resourceConfig;
     }
 
@@ -116,7 +120,7 @@ public class RestPostOperationTest extends JerseyTest {
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
         uri = "/operations/test-module:rpc-wrongtest";
-        assertEquals(404, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
+        assertEquals(400, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
     }
 
     @Test
@@ -173,7 +177,8 @@ public class RestPostOperationTest extends JerseyTest {
     private void mockInvokeRpc(CompositeNode result, boolean sucessful) {
         RpcResult<CompositeNode> rpcResult = new DummyRpcResult.Builder<CompositeNode>().result(result)
                 .isSuccessful(sucessful).build();
-        when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(rpcResult);
+        when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class)))
+            .thenReturn(Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ));
     }
 
     private void mockCommitConfigurationDataPostMethod(TransactionStatus statusName) {
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java
new file mode 100644 (file)
index 0000000..fc5d7be
--- /dev/null
@@ -0,0 +1,966 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.api.Draft02;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.io.ByteStreams;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+
+/**
+ * Unit tests for RestconfDocumentedExceptionMapper.
+ *
+ * @author Thomas Pantelis
+ */
+public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
+
+    interface ErrorInfoVerifier {
+        void verifyXML( Node errorInfoNode );
+        void verifyJson( JsonElement errorInfoElement );
+    }
+
+    static class ComplexErrorInfoVerifier implements ErrorInfoVerifier {
+
+        Map<String, String> expErrorInfo;
+
+        public ComplexErrorInfoVerifier( Map<String, String> expErrorInfo ) {
+            this.expErrorInfo = expErrorInfo;
+        }
+
+        @Override
+        public void verifyXML( Node errorInfoNode ) {
+
+            Map<String, String> mutableExpMap = Maps.newHashMap( expErrorInfo );
+            NodeList childNodes = errorInfoNode.getChildNodes();
+            for( int i = 0; i < childNodes.getLength(); i++ ) {
+                Node child = childNodes.item( i );
+                if( child  instanceof Element ) {
+                    String expValue = mutableExpMap.remove( child.getNodeName() );
+                    assertNotNull( "Found unexpected \"error-info\" child node: " +
+                                   child.getNodeName(), expValue );
+                    assertEquals( "Text content for \"error-info\" child node " +
+                                   child.getNodeName(), expValue, child.getTextContent() );
+                }
+            }
+
+            if( !mutableExpMap.isEmpty() ) {
+                fail( "Missing \"error-info\" child nodes: " + mutableExpMap );
+            }
+        }
+
+        @Override
+        public void verifyJson( JsonElement errorInfoElement ) {
+
+            assertTrue( "\"error-info\" Json element is not an Object",
+                    errorInfoElement.isJsonObject() );
+
+            Map<String, String> actualErrorInfo = Maps.newHashMap();
+            for( Entry<String, JsonElement> entry: errorInfoElement.getAsJsonObject().entrySet() ) {
+                String leafName = entry.getKey();
+                JsonElement leafElement = entry.getValue();
+                actualErrorInfo.put( leafName, leafElement.getAsString() );
+            }
+
+            Map<String, String> mutableExpMap = Maps.newHashMap( expErrorInfo );
+            for( Entry<String,String> actual: actualErrorInfo.entrySet() ) {
+                String expValue = mutableExpMap.remove( actual.getKey() );
+                assertNotNull( "Found unexpected \"error-info\" child node: " +
+                                actual.getKey(), expValue );
+                assertEquals( "Text content for \"error-info\" child node " +
+                              actual.getKey(), expValue, actual.getValue() );
+            }
+
+            if( !mutableExpMap.isEmpty() ) {
+                fail( "Missing \"error-info\" child nodes: " + mutableExpMap );
+            }
+        }
+    }
+
+    static class SimpleErrorInfoVerifier implements ErrorInfoVerifier {
+
+        String expTextContent;
+
+        public SimpleErrorInfoVerifier( String expErrorInfo ) {
+            this.expTextContent = expErrorInfo;
+        }
+
+        void verifyContent( String actualContent ) {
+            assertNotNull( "Actual \"error-info\" text content is null", actualContent );
+            assertTrue( "", actualContent.contains( expTextContent ) );
+        }
+
+        @Override
+        public void verifyXML( Node errorInfoNode ) {
+            verifyContent( errorInfoNode.getTextContent() );
+        }
+
+        @Override
+        public void verifyJson( JsonElement errorInfoElement ) {
+            verifyContent( errorInfoElement.getAsString() );
+        }
+    }
+
+    static RestconfService mockRestConf = mock( RestconfService.class );
+
+    static XPath XPATH = XPathFactory.newInstance().newXPath();
+    static XPathExpression ERROR_LIST;
+    static XPathExpression ERROR_TYPE;
+    static XPathExpression ERROR_TAG;
+    static XPathExpression ERROR_MESSAGE;
+    static XPathExpression ERROR_APP_TAG;
+    static XPathExpression ERROR_INFO;
+
+    @BeforeClass
+    public static void init() throws Exception {
+        ControllerContext.getInstance().setGlobalSchema( TestUtils.loadSchemaContext("/modules") );
+
+        NamespaceContext nsContext = new NamespaceContext() {
+            @Override
+            public Iterator getPrefixes( String namespaceURI ) {
+                return null;
+            }
+
+            @Override
+            public String getPrefix( String namespaceURI ) {
+                return null;
+            }
+
+            @Override
+            public String getNamespaceURI( String prefix ) {
+                return "ietf-restconf".equals( prefix ) ? Draft02.RestConfModule.NAMESPACE : null;
+            }
+        };
+
+        XPATH.setNamespaceContext( nsContext );
+        ERROR_LIST = XPATH.compile( "ietf-restconf:errors/ietf-restconf:error" );
+        ERROR_TYPE = XPATH.compile( "ietf-restconf:error-type" );
+        ERROR_TAG = XPATH.compile( "ietf-restconf:error-tag" );
+        ERROR_MESSAGE = XPATH.compile( "ietf-restconf:error-message" );
+        ERROR_APP_TAG = XPATH.compile( "ietf-restconf:error-app-tag" );
+        ERROR_INFO = XPATH.compile( "ietf-restconf:error-info" );
+    }
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        reset( mockRestConf );
+        super.setUp();
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig resourceConfig = new ResourceConfig();
+        resourceConfig = resourceConfig.registerInstances( mockRestConf, StructuredDataToXmlProvider.INSTANCE,
+                                                           StructuredDataToJsonProvider.INSTANCE );
+        resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
+        return resourceConfig;
+    }
+
+    void stageMockEx( RestconfDocumentedException ex ) {
+        reset( mockRestConf );
+        when( mockRestConf.readOperationalData( any( String.class ) ) ).thenThrow( ex );
+    }
+
+    void testJsonResponse( RestconfDocumentedException ex, Status expStatus, ErrorType expErrorType,
+                           ErrorTag expErrorTag, String expErrorMessage, String expErrorAppTag,
+                           ErrorInfoVerifier errorInfoVerifier ) throws Exception {
+
+        stageMockEx( ex );
+
+        Response resp = target("/operational/foo").request( MediaType.APPLICATION_JSON ).get();
+
+        InputStream stream = verifyResponse( resp, MediaType.APPLICATION_JSON, expStatus );
+
+        verifyJsonResponseBody( stream, expErrorType, expErrorTag, expErrorMessage,
+                                expErrorAppTag, errorInfoVerifier );
+    }
+
+    @Test
+    public void testToJsonResponseWithMessageOnly() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error" ), Status.INTERNAL_SERVER_ERROR,
+                          ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error", null, null );
+
+        // To test verification code
+//        String json =
+//            "{ errors: {" +
+//            "    error: [{" +
+//            "      error-tag : \"operation-failed\"" +
+//            "      ,error-type : \"application\"" +
+//            "      ,error-message : \"An error occurred\"" +
+//            "      ,error-info : {" +
+//            "        session-id: \"123\"" +
+//            "        ,address: \"1.2.3.4\"" +
+//            "      }" +
+//            "    }]" +
+//            "  }" +
+//            "}";
+//
+//        verifyJsonResponseBody( new java.io.StringBufferInputStream(json ), ErrorType.APPLICATION,
+//            ErrorTag.OPERATION_FAILED, "An error occurred", null,
+//            com.google.common.collect.ImmutableMap.of( "session-id", "123", "address", "1.2.3.4" ) );
+    }
+
+    @Test
+    public void testToJsonResponseWithInUseErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.IN_USE ),
+                          Status.CONFLICT, ErrorType.PROTOCOL,
+                          ErrorTag.IN_USE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithInvalidValueErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.RPC,
+                                                           ErrorTag.INVALID_VALUE ),
+                          Status.BAD_REQUEST, ErrorType.RPC,
+                          ErrorTag.INVALID_VALUE, "mock error", null, null );
+
+    }
+
+    @Test
+    public void testToJsonResponseWithTooBigErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.TRANSPORT,
+                                                           ErrorTag.TOO_BIG ),
+                          Status.REQUEST_ENTITY_TOO_LARGE, ErrorType.TRANSPORT,
+                          ErrorTag.TOO_BIG, "mock error", null, null );
+
+    }
+
+    @Test
+    public void testToJsonResponseWithMissingAttributeErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.MISSING_ATTRIBUTE ),
+                          Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                          ErrorTag.MISSING_ATTRIBUTE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithBadAttributeErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.BAD_ATTRIBUTE ),
+                          Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                          ErrorTag.BAD_ATTRIBUTE, "mock error", null, null );
+    }
+    @Test
+    public void testToJsonResponseWithUnknownAttributeErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.UNKNOWN_ATTRIBUTE ),
+                          Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                          ErrorTag.UNKNOWN_ATTRIBUTE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithBadElementErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.BAD_ELEMENT ),
+                          Status.BAD_REQUEST,
+                          ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithUnknownElementErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.UNKNOWN_ELEMENT ),
+                          Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                          ErrorTag.UNKNOWN_ELEMENT, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithUnknownNamespaceErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.UNKNOWN_NAMESPACE ),
+                          Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                          ErrorTag.UNKNOWN_NAMESPACE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithMalformedMessageErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.MALFORMED_MESSAGE ),
+                          Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                          ErrorTag.MALFORMED_MESSAGE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithAccessDeniedErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.ACCESS_DENIED ),
+                          Status.FORBIDDEN, ErrorType.PROTOCOL,
+                          ErrorTag.ACCESS_DENIED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithLockDeniedErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.LOCK_DENIED ),
+                          Status.CONFLICT, ErrorType.PROTOCOL,
+                          ErrorTag.LOCK_DENIED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithResourceDeniedErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.RESOURCE_DENIED ),
+                          Status.CONFLICT, ErrorType.PROTOCOL,
+                          ErrorTag.RESOURCE_DENIED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithRollbackFailedErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.ROLLBACK_FAILED ),
+                          Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+                          ErrorTag.ROLLBACK_FAILED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithDataExistsErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.DATA_EXISTS ),
+                          Status.CONFLICT, ErrorType.PROTOCOL,
+                          ErrorTag.DATA_EXISTS, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithDataMissingErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.DATA_MISSING ),
+                          Status.CONFLICT, ErrorType.PROTOCOL,
+                          ErrorTag.DATA_MISSING, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithOperationNotSupportedErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.OPERATION_NOT_SUPPORTED ),
+                          Status.NOT_IMPLEMENTED, ErrorType.PROTOCOL,
+                          ErrorTag.OPERATION_NOT_SUPPORTED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithOperationFailedErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.OPERATION_FAILED ),
+                          Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+                          ErrorTag.OPERATION_FAILED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithPartialOperationErrorTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.PARTIAL_OPERATION ),
+                          Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+                          ErrorTag.PARTIAL_OPERATION, "mock error", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithErrorAppTag() throws Exception {
+
+        testJsonResponse( new RestconfDocumentedException( new RestconfError(
+                                   ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                                   "mock error", "mock-app-tag" ) ),
+                          Status.BAD_REQUEST, ErrorType.APPLICATION,
+                          ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag", null );
+    }
+
+    @Test
+    public void testToJsonResponseWithMultipleErrors() throws Exception {
+
+        List<RestconfError> errorList = Arrays.asList(
+                new RestconfError( ErrorType.APPLICATION, ErrorTag.LOCK_DENIED, "mock error1" ),
+                new RestconfError( ErrorType.RPC, ErrorTag.ROLLBACK_FAILED, "mock error2" ) );
+        stageMockEx( new RestconfDocumentedException( errorList ) );
+
+        Response resp = target("/operational/foo").request( MediaType.APPLICATION_JSON ).get();
+
+        InputStream stream = verifyResponse( resp, MediaType.APPLICATION_JSON, Status.CONFLICT );
+
+        JsonArray arrayElement = parseJsonErrorArrayElement( stream );
+
+        assertEquals( "\"error\" Json array element length", 2, arrayElement.size() );
+
+        verifyJsonErrorNode( arrayElement.get( 0 ), ErrorType.APPLICATION, ErrorTag.LOCK_DENIED,
+                             "mock error1", null, null );
+
+        verifyJsonErrorNode( arrayElement.get( 1 ), ErrorType.RPC, ErrorTag.ROLLBACK_FAILED,
+                             "mock error2", null, null );
+    }
+
+    @Test
+    public void testToJsonResponseWithErrorInfo() throws Exception {
+
+        String errorInfo = "<address>1.2.3.4</address> <session-id>123</session-id>";
+        testJsonResponse( new RestconfDocumentedException( new RestconfError(
+                                               ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                                               "mock error", "mock-app-tag", errorInfo ) ),
+                          Status.BAD_REQUEST, ErrorType.APPLICATION,
+                          ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag",
+                          new ComplexErrorInfoVerifier( ImmutableMap.of(
+                                                "session-id", "123", "address", "1.2.3.4" ) ) );
+    }
+
+    @Test
+    public void testToJsonResponseWithExceptionCause() throws Exception {
+
+        Exception cause = new Exception( "mock exception cause" );
+        testJsonResponse( new RestconfDocumentedException( "mock error", cause ),
+                          Status.INTERNAL_SERVER_ERROR, ErrorType.APPLICATION,
+                          ErrorTag.OPERATION_FAILED, "mock error", null,
+                          new SimpleErrorInfoVerifier( cause.getMessage() ) );
+    }
+
+    void testXMLResponse( RestconfDocumentedException ex, Status expStatus, ErrorType expErrorType,
+                          ErrorTag expErrorTag, String expErrorMessage,
+                          String expErrorAppTag, ErrorInfoVerifier errorInfoVerifier ) throws Exception
+    {
+        stageMockEx( ex );
+
+        Response resp = target("/operational/foo").request( MediaType.APPLICATION_XML ).get();
+
+        InputStream stream = verifyResponse( resp, MediaType.APPLICATION_XML, expStatus );
+
+        verifyXMLResponseBody( stream, expErrorType, expErrorTag, expErrorMessage,
+                               expErrorAppTag, errorInfoVerifier );
+    }
+
+    @Test
+    public void testToXMLResponseWithMessageOnly() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error" ), Status.INTERNAL_SERVER_ERROR,
+                         ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error", null, null );
+
+        // To test verification code
+//        String xml =
+//            "<errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">"+
+//            "  <error>" +
+//            "    <error-type>application</error-type>"+
+//            "    <error-tag>operation-failed</error-tag>"+
+//            "    <error-message>An error occurred</error-message>"+
+//            "    <error-info>" +
+//            "      <session-id>123</session-id>" +
+//            "      <address>1.2.3.4</address>" +
+//            "    </error-info>" +
+//            "  </error>" +
+//            "</errors>";
+//
+//        verifyXMLResponseBody( new java.io.StringBufferInputStream(xml), ErrorType.APPLICATION,
+//                ErrorTag.OPERATION_FAILED, "An error occurred", null,
+//                com.google.common.collect.ImmutableMap.of( "session-id", "123", "address", "1.2.3.4" ) );
+    }
+
+    @Test
+    public void testToXMLResponseWithInUseErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.IN_USE ),
+                         Status.CONFLICT, ErrorType.PROTOCOL,
+                         ErrorTag.IN_USE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithInvalidValueErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.RPC,
+                                                           ErrorTag.INVALID_VALUE ),
+                         Status.BAD_REQUEST, ErrorType.RPC,
+                         ErrorTag.INVALID_VALUE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithTooBigErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.TRANSPORT,
+                                                           ErrorTag.TOO_BIG ),
+                         Status.REQUEST_ENTITY_TOO_LARGE, ErrorType.TRANSPORT,
+                         ErrorTag.TOO_BIG, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithMissingAttributeErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.MISSING_ATTRIBUTE ),
+                         Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                         ErrorTag.MISSING_ATTRIBUTE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithBadAttributeErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.BAD_ATTRIBUTE ),
+                         Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                         ErrorTag.BAD_ATTRIBUTE, "mock error", null, null );
+    }
+    @Test
+    public void testToXMLResponseWithUnknownAttributeErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.UNKNOWN_ATTRIBUTE ),
+                         Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                         ErrorTag.UNKNOWN_ATTRIBUTE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithBadElementErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.BAD_ELEMENT ),
+                         Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                         ErrorTag.BAD_ELEMENT, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithUnknownElementErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.UNKNOWN_ELEMENT ),
+                         Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                         ErrorTag.UNKNOWN_ELEMENT, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithUnknownNamespaceErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.UNKNOWN_NAMESPACE ),
+                         Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                         ErrorTag.UNKNOWN_NAMESPACE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithMalformedMessageErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.MALFORMED_MESSAGE ),
+                         Status.BAD_REQUEST, ErrorType.PROTOCOL,
+                         ErrorTag.MALFORMED_MESSAGE, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithAccessDeniedErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.ACCESS_DENIED ),
+                         Status.FORBIDDEN, ErrorType.PROTOCOL,
+                         ErrorTag.ACCESS_DENIED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithLockDeniedErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.LOCK_DENIED ),
+                          Status.CONFLICT, ErrorType.PROTOCOL,
+                          ErrorTag.LOCK_DENIED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithResourceDeniedErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.RESOURCE_DENIED ),
+                         Status.CONFLICT, ErrorType.PROTOCOL,
+                         ErrorTag.RESOURCE_DENIED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithRollbackFailedErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.ROLLBACK_FAILED ),
+                         Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+                         ErrorTag.ROLLBACK_FAILED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithDataExistsErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.DATA_EXISTS ),
+                         Status.CONFLICT, ErrorType.PROTOCOL,
+                         ErrorTag.DATA_EXISTS, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithDataMissingErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.DATA_MISSING ),
+                         Status.CONFLICT, ErrorType.PROTOCOL,
+                         ErrorTag.DATA_MISSING, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithOperationNotSupportedErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.OPERATION_NOT_SUPPORTED ),
+                         Status.NOT_IMPLEMENTED, ErrorType.PROTOCOL,
+                         ErrorTag.OPERATION_NOT_SUPPORTED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithOperationFailedErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.OPERATION_FAILED ),
+                         Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+                         ErrorTag.OPERATION_FAILED, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithPartialOperationErrorTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+                                                           ErrorTag.PARTIAL_OPERATION ),
+                         Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+                         ErrorTag.PARTIAL_OPERATION, "mock error", null, null );
+    }
+
+    @Test
+    public void testToXMLResponseWithErrorAppTag() throws Exception {
+
+        testXMLResponse( new RestconfDocumentedException( new RestconfError(
+                                              ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                                              "mock error", "mock-app-tag" ) ),
+                         Status.BAD_REQUEST, ErrorType.APPLICATION,
+                         ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag", null );
+    }
+
+    @Test
+    public void testToXMLResponseWithErrorInfo() throws Exception {
+
+        String errorInfo = "<address>1.2.3.4</address> <session-id>123</session-id>";
+        testXMLResponse( new RestconfDocumentedException( new RestconfError(
+                                               ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                                               "mock error", "mock-app-tag", errorInfo ) ),
+                         Status.BAD_REQUEST, ErrorType.APPLICATION,
+                         ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag",
+                         new ComplexErrorInfoVerifier( ImmutableMap.of(
+                                              "session-id", "123", "address", "1.2.3.4" ) ) );
+    }
+
+    @Test
+    public void testToXMLResponseWithExceptionCause() throws Exception {
+
+        Exception cause = new Exception( "mock exception cause" );
+        testXMLResponse( new RestconfDocumentedException( "mock error", cause ),
+                         Status.INTERNAL_SERVER_ERROR, ErrorType.APPLICATION,
+                         ErrorTag.OPERATION_FAILED, "mock error", null,
+                         new SimpleErrorInfoVerifier( cause.getMessage() ) );
+    }
+
+    @Test
+    public void testToXMLResponseWithMultipleErrors() throws Exception {
+
+        List<RestconfError> errorList = Arrays.asList(
+                new RestconfError( ErrorType.APPLICATION, ErrorTag.LOCK_DENIED, "mock error1" ),
+                new RestconfError( ErrorType.RPC, ErrorTag.ROLLBACK_FAILED, "mock error2" ) );
+        stageMockEx( new RestconfDocumentedException( errorList ) );
+
+        Response resp = target("/operational/foo").request( MediaType.APPLICATION_XML ).get();
+
+        InputStream stream = verifyResponse( resp, MediaType.APPLICATION_XML, Status.CONFLICT );
+
+        Document doc = parseXMLDocument( stream );
+
+        NodeList children = getXMLErrorList( doc, 2 );
+
+        verifyXMLErrorNode( children.item( 0 ), ErrorType.APPLICATION, ErrorTag.LOCK_DENIED,
+                            "mock error1", null, null );
+
+        verifyXMLErrorNode( children.item( 1 ), ErrorType.RPC, ErrorTag.ROLLBACK_FAILED,
+                            "mock error2", null, null );
+    }
+
+    @Test
+    public void testToResponseWithAcceptHeader() throws Exception {
+
+        stageMockEx( new RestconfDocumentedException( "mock error" ) );
+
+        Response resp = target("/operational/foo")
+                                  .request().header( "Accept", MediaType.APPLICATION_JSON ).get();
+
+        InputStream stream = verifyResponse( resp, MediaType.APPLICATION_JSON,
+                                             Status.INTERNAL_SERVER_ERROR );
+
+        verifyJsonResponseBody( stream, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error",
+                                null, null );
+    }
+
+    @Test
+    public void testToResponseWithStatusOnly() throws Exception {
+
+        // The StructuredDataToJsonProvider should throw a RestconfDocumentedException with no data
+
+        when( mockRestConf.readOperationalData( any( String.class ) ) )
+            .thenReturn( new StructuredData( null, null, null ) );
+
+        Response resp = target("/operational/foo").request( MediaType.APPLICATION_JSON ).get();
+
+        verifyResponse( resp, MediaType.TEXT_PLAIN, Status.NOT_FOUND );
+    }
+
+    InputStream verifyResponse( Response resp, String expMediaType, Status expStatus ) {
+        assertEquals( "getMediaType", MediaType.valueOf( expMediaType ), resp.getMediaType() );
+        assertEquals( "getStatus", expStatus.getStatusCode(), resp.getStatus() );
+
+        Object entity = resp.getEntity();
+        assertEquals( "Response entity", true, entity instanceof InputStream );
+        InputStream stream = (InputStream)entity;
+        return stream;
+    }
+
+    void verifyJsonResponseBody( InputStream stream, ErrorType expErrorType, ErrorTag expErrorTag,
+                                 String expErrorMessage, String expErrorAppTag,
+                                 ErrorInfoVerifier errorInfoVerifier ) throws Exception {
+
+        JsonArray arrayElement = parseJsonErrorArrayElement( stream );
+
+        assertEquals( "\"error\" Json array element length", 1, arrayElement.size() );
+
+        verifyJsonErrorNode( arrayElement.get( 0 ),  expErrorType, expErrorTag, expErrorMessage,
+                             expErrorAppTag, errorInfoVerifier );
+    }
+
+    private JsonArray parseJsonErrorArrayElement( InputStream stream ) throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ByteStreams.copy( stream, bos );
+
+        System.out.println("JSON: "+bos.toString());
+
+        JsonParser parser = new JsonParser();
+        JsonElement rootElement;
+
+        try {
+            rootElement = parser.parse(
+                          new InputStreamReader( new ByteArrayInputStream( bos.toByteArray() ) ) );
+        }
+        catch( Exception e ) {
+            throw new IllegalArgumentException( "Invalid JSON response:\n" + bos.toString(), e );
+        }
+
+        assertTrue( "Root element of Json is not an Object", rootElement.isJsonObject() );
+
+        Set<Entry<String, JsonElement>> errorsEntrySet = rootElement.getAsJsonObject().entrySet();
+        assertEquals( "Json Object element set count", 1, errorsEntrySet.size() );
+
+        Entry<String, JsonElement> errorsEntry = errorsEntrySet.iterator().next();
+        JsonElement errorsElement = errorsEntry.getValue();
+        assertEquals( "First Json element name", "errors", errorsEntry.getKey() );
+        assertTrue( "\"errors\" Json element is not an Object", errorsElement.isJsonObject() );
+
+        Set<Entry<String, JsonElement>> errorListEntrySet = errorsElement.getAsJsonObject().entrySet();
+        assertEquals( "Root \"errors\" element child count", 1, errorListEntrySet.size() );
+
+        JsonElement errorListElement = errorListEntrySet.iterator().next().getValue();
+        assertEquals( "\"errors\" child Json element name", "error",
+                      errorListEntrySet.iterator().next().getKey() );
+        assertTrue( "\"error\" Json element is not an Array", errorListElement.isJsonArray() );
+
+        return errorListElement.getAsJsonArray();
+    }
+
+    void verifyJsonErrorNode( JsonElement errorEntryElement, ErrorType expErrorType, ErrorTag expErrorTag,
+                              String expErrorMessage, String expErrorAppTag,
+                              ErrorInfoVerifier errorInfoVerifier ) {
+
+        JsonElement errorInfoElement = null;
+        Map<String, String> actualErrorInfo = null;
+        Map<String, String> leafMap = Maps.newHashMap();
+        for( Entry<String, JsonElement> entry: errorEntryElement.getAsJsonObject().entrySet() ) {
+            String leafName = entry.getKey();
+            JsonElement leafElement = entry.getValue();
+
+            if( "error-info".equals( leafName ) ) {
+                assertNotNull( "Found unexpected \"error-info\" element", errorInfoVerifier );
+                errorInfoElement = leafElement;
+            }
+            else {
+                assertTrue( "\"error\" leaf Json element " + leafName +
+                            " is not a Primitive", leafElement.isJsonPrimitive() );
+
+                leafMap.put( leafName, leafElement.getAsString() );
+            }
+        }
+
+        assertEquals( "error-type", expErrorType.getErrorTypeTag(), leafMap.remove( "error-type" ) );
+        assertEquals( "error-tag", expErrorTag.getTagValue(), leafMap.remove( "error-tag" ) );
+
+        verifyOptionalJsonLeaf( leafMap.remove( "error-message" ), expErrorMessage, "error-message" );
+        verifyOptionalJsonLeaf( leafMap.remove( "error-app-tag" ), expErrorAppTag, "error-app-tag" );
+
+        if( !leafMap.isEmpty() ) {
+            fail( "Found unexpected Json leaf elements for \"error\" element: " + leafMap );
+        }
+
+        if( errorInfoVerifier != null ) {
+            assertNotNull( "Missing \"error-info\" element", errorInfoElement );
+            errorInfoVerifier.verifyJson( errorInfoElement );
+        }
+    }
+
+    void verifyOptionalJsonLeaf( String actualValue, String expValue, String tagName ) {
+        if( expValue != null ) {
+            assertEquals( tagName, expValue, actualValue );
+        }
+        else {
+            assertNull( "Found unexpected \"error\" leaf entry for: " + tagName, actualValue );
+        }
+    }
+
+    void verifyXMLResponseBody( InputStream stream, ErrorType expErrorType, ErrorTag expErrorTag,
+                                String expErrorMessage, String expErrorAppTag,
+                                ErrorInfoVerifier errorInfoVerifier )
+                                                                    throws Exception {
+
+        Document doc = parseXMLDocument( stream );
+
+        NodeList children = getXMLErrorList( doc, 1 );
+
+        verifyXMLErrorNode( children.item( 0 ), expErrorType, expErrorTag, expErrorMessage,
+                            expErrorAppTag, errorInfoVerifier );
+    }
+
+    private Document parseXMLDocument( InputStream stream ) throws IOException {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setCoalescing(true);
+        factory.setIgnoringElementContentWhitespace(true);
+        factory.setIgnoringComments(true);
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ByteStreams.copy( stream, bos );
+
+        System.out.println("XML: "+bos.toString());
+
+        Document doc = null;
+        try {
+            doc = factory.newDocumentBuilder().parse( new ByteArrayInputStream( bos.toByteArray() ) );
+        }
+        catch( Exception e ) {
+            throw new IllegalArgumentException( "Invalid XML response:\n" + bos.toString(), e );
+        }
+        return doc;
+    }
+
+    void verifyXMLErrorNode( Node errorNode, ErrorType expErrorType, ErrorTag expErrorTag,
+                             String expErrorMessage, String expErrorAppTag,
+                             ErrorInfoVerifier errorInfoVerifier ) throws Exception {
+
+        String errorType = (String)ERROR_TYPE.evaluate( errorNode, XPathConstants.STRING );
+        assertEquals( "error-type", expErrorType.getErrorTypeTag(), errorType );
+
+        String errorTag = (String)ERROR_TAG.evaluate( errorNode, XPathConstants.STRING );
+        assertEquals( "error-tag", expErrorTag.getTagValue(), errorTag );
+
+        verifyOptionalXMLLeaf( errorNode, ERROR_MESSAGE, expErrorMessage, "error-message" );
+        verifyOptionalXMLLeaf( errorNode, ERROR_APP_TAG, expErrorAppTag, "error-app-tag" );
+
+        Node errorInfoNode = (Node)ERROR_INFO.evaluate( errorNode, XPathConstants.NODE );
+        if( errorInfoVerifier != null ) {
+            assertNotNull( "Missing \"error-info\" node", errorInfoNode );
+
+            errorInfoVerifier.verifyXML( errorInfoNode );
+        }
+        else {
+            assertNull( "Found unexpected \"error-info\" node", errorInfoNode );
+        }
+    }
+
+    void verifyOptionalXMLLeaf( Node fromNode, XPathExpression xpath, String expValue,
+                                String tagName ) throws Exception {
+        if( expValue != null ) {
+            String actual = (String)xpath.evaluate( fromNode, XPathConstants.STRING );
+            assertEquals( tagName, expValue, actual );
+        }
+        else {
+            assertNull( "Found unexpected \"error\" leaf entry for: " + tagName,
+                        xpath.evaluate( fromNode, XPathConstants.NODE ) );
+        }
+    }
+
+    NodeList getXMLErrorList( Node fromNode, int count ) throws Exception {
+        NodeList errorList = (NodeList)ERROR_LIST.evaluate( fromNode, XPathConstants.NODESET );
+        assertNotNull( "Root errors node is empty", errorList );
+        assertEquals( "Root errors node child count", count, errorList.getLength() );
+        return errorList;
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfErrorTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfErrorTest.java
new file mode 100644 (file)
index 0000000..70ad768
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.opendaylight.controller.sal.common.util.RpcErrors.getRpcError;
+
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcError;
+
+/**
+ * Unit tests for RestconfError.
+ *
+ * @author Devin Avery
+ * @author Thomas Pantelis
+ *
+ */
+public class RestconfErrorTest {
+
+    static class Contains extends BaseMatcher<String> {
+
+        private final String text;
+
+        public Contains( String text ) {
+            this.text = text;
+        }
+
+        @Override
+        public void describeTo( Description desc ) {
+            desc.appendText( "contains " ).appendValue( text );
+        }
+
+        @Override
+        public boolean matches( Object arg ) {
+            return arg != null && arg.toString().contains( text );
+        }
+    }
+
+    @Test
+    public void testErrorTagValueOf()
+    {
+        assertEquals( ErrorTag.IN_USE,
+                ErrorTag.valueOfCaseInsensitive( ErrorTag.IN_USE.getTagValue() ) );
+    }
+
+    @Test
+    public void testErrorTagValueOfIsLowercase()
+    {
+        assertEquals( "in-use",
+                ErrorTag.IN_USE.getTagValue() );
+    }
+
+    @Test
+    public void testErrorTypeGetErrorTypeTagIsLowerCase()
+    {
+       assertEquals( ErrorType.APPLICATION.name().toLowerCase(),
+               ErrorType.APPLICATION.getErrorTypeTag() );
+    }
+
+    @Test
+    public void testErrorTypeValueOf()
+    {
+       assertEquals( ErrorType.APPLICATION,
+                     ErrorType.valueOfCaseInsensitive( ErrorType.APPLICATION.getErrorTypeTag() ) );
+    }
+
+    @Test
+    public void testErrorTagStatusCodes()
+    {
+        Map<String,Status> lookUpMap = new HashMap<String,Status>();
+
+        lookUpMap.put( "in-use", Status.fromStatusCode(409));
+        lookUpMap.put( "invalid-value", Status.fromStatusCode(400));
+        lookUpMap.put( "too-big", Status.fromStatusCode(413));
+        lookUpMap.put( "missing-attribute", Status.fromStatusCode(400));
+        lookUpMap.put( "bad-attribute", Status.fromStatusCode(400));
+        lookUpMap.put( "unknown-attribute", Status.fromStatusCode(400));
+        lookUpMap.put( "bad-element", Status.fromStatusCode(400));
+        lookUpMap.put( "unknown-element", Status.fromStatusCode(400));
+        lookUpMap.put( "unknown-namespace", Status.fromStatusCode(400));
+        lookUpMap.put( "access-denied", Status.fromStatusCode(403));
+        lookUpMap.put( "lock-denied", Status.fromStatusCode(409));
+        lookUpMap.put( "resource-denied", Status.fromStatusCode(409));
+        lookUpMap.put( "rollback-failed", Status.fromStatusCode(500));
+        lookUpMap.put( "data-exists", Status.fromStatusCode(409));
+        lookUpMap.put( "data-missing", Status.fromStatusCode(409));
+        lookUpMap.put( "operation-not-supported", Status.fromStatusCode(501));
+        lookUpMap.put( "operation-failed", Status.fromStatusCode(500));
+        lookUpMap.put( "partial-operation", Status.fromStatusCode(500));
+        lookUpMap.put( "malformed-message", Status.fromStatusCode(400));
+
+        for( ErrorTag tag : ErrorTag.values() )
+        {
+            Status expectedStatusCode = lookUpMap.get( tag.getTagValue() );
+            assertNotNull( "Failed to find " + tag.getTagValue(), expectedStatusCode );
+            assertEquals( "Status Code does not match", expectedStatusCode, tag.getStatusCode() );
+        }
+    }
+
+    @Test
+    public void testRestConfDocumentedException_NoCause()
+    {
+        String expectedMessage = "Message";
+        ErrorType expectedErrorType = ErrorType.RPC;
+        ErrorTag expectedErrorTag = ErrorTag.IN_USE;
+        RestconfError e =
+                new RestconfError( expectedErrorType,
+                                                 expectedErrorTag, expectedMessage );
+
+        validateRestConfError(expectedMessage, expectedErrorType, expectedErrorTag,
+                              null, (String)null, e);
+    }
+
+    @Test
+    public void testRestConfDocumentedException_WithAppTag()
+    {
+        String expectedMessage = "Message";
+        ErrorType expectedErrorType = ErrorType.RPC;
+        ErrorTag expectedErrorTag = ErrorTag.IN_USE;
+        String expectedErrorAppTag = "application.tag";
+
+        RestconfError e =
+                new RestconfError( expectedErrorType,
+                                                 expectedErrorTag, expectedMessage, expectedErrorAppTag );
+
+        validateRestConfError(expectedMessage, expectedErrorType, expectedErrorTag,
+                              expectedErrorAppTag, (String)null, e);
+    }
+
+    @Test
+    public void testRestConfDocumentedException_WithAppTagErrorInfo()
+    {
+        String expectedMessage = "Message";
+        ErrorType expectedErrorType = ErrorType.RPC;
+        ErrorTag expectedErrorTag = ErrorTag.IN_USE;
+        String expectedErrorAppTag = "application.tag";
+        String errorInfo = "<extra><sessionid>session.id</sessionid></extra>";
+
+        RestconfError e = new RestconfError( expectedErrorType,
+                                             expectedErrorTag,
+                                             expectedMessage,
+                                             expectedErrorAppTag,
+                                             errorInfo );
+
+        validateRestConfError(expectedMessage, expectedErrorType, expectedErrorTag,
+                expectedErrorAppTag, errorInfo, e);
+    }
+
+    @Test
+    public void testRestConfErrorWithRpcError() {
+
+        // All fields set
+        RpcError rpcError = getRpcError( "mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(),
+                                         "mock error-info", RpcError.ErrorSeverity.ERROR,
+                                         "mock error-message", RpcError.ErrorType.PROTOCOL,
+                                         new Exception( "mock cause" ) );
+
+        validateRestConfError( "mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE,
+                               "mock app-tag", "mock error-info",
+                               new RestconfError( rpcError ) );
+
+        // All fields set except 'info' - expect error-info set to 'cause'
+        rpcError = getRpcError( "mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(),
+                                null, RpcError.ErrorSeverity.ERROR,
+                                "mock error-message", RpcError.ErrorType.PROTOCOL,
+                                new Exception( "mock cause" ) );
+
+        validateRestConfError( "mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE,
+                               "mock app-tag", new Contains( "mock cause" ),
+                               new RestconfError( rpcError ) );
+
+        // Some fields set - expect error-info set to ErrorSeverity
+        rpcError = getRpcError( null, ErrorTag.ACCESS_DENIED.getTagValue(),
+                                null, RpcError.ErrorSeverity.ERROR,
+                                null, RpcError.ErrorType.RPC, null );
+
+        validateRestConfError( null, ErrorType.RPC, ErrorTag.ACCESS_DENIED,
+                               null, "<severity>error</severity>",
+                               new RestconfError( rpcError ) );
+
+        // 'tag' field not mapped to ErrorTag - expect error-tag set to OPERATION_FAILED
+        rpcError = getRpcError( null, "not mapped",
+                                null, RpcError.ErrorSeverity.WARNING,
+                                null, RpcError.ErrorType.TRANSPORT, null );
+
+        validateRestConfError( null, ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED,
+                               null, "<severity>warning</severity>",
+                               new RestconfError( rpcError ) );
+
+        // No fields set - edge case
+        rpcError = getRpcError( null, null, null, null, null, null, null );
+
+        validateRestConfError( null, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED,
+                               null, (String)null, new RestconfError( rpcError ) );
+    }
+
+    private void validateRestConfError(String expectedMessage, ErrorType expectedErrorType,
+            ErrorTag expectedErrorTag, String expectedErrorAppTag, String errorInfo, RestconfError e) {
+
+        validateRestConfError( expectedMessage, expectedErrorType, expectedErrorTag,
+                               expectedErrorAppTag, equalTo( errorInfo ), e );
+    }
+
+    private void validateRestConfError(String expectedMessage, ErrorType expectedErrorType,
+            ErrorTag expectedErrorTag, String expectedErrorAppTag,
+            Matcher<String> errorInfoMatcher, RestconfError e) {
+
+        assertEquals( "getErrorMessage", expectedMessage, e.getErrorMessage() );
+        assertEquals( "getErrorType", expectedErrorType, e.getErrorType() );
+        assertEquals( "getErrorTag", expectedErrorTag, e.getErrorTag() );
+        assertEquals( "getErrorAppTag", expectedErrorAppTag, e.getErrorAppTag() );
+        assertThat( "getErrorInfo", e.getErrorInfo(), errorInfoMatcher );
+        e.toString(); // really just checking for NPE etc. Don't care about contents.
+    }
+}
index b681653d6b1a48b7020ac72d8960c86c07463ad0..e2559f4b70ab27e2e6d990996e84bd8fbfb47045 100644 (file)
@@ -7,8 +7,17 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.test;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
 import java.io.FileNotFoundException;
 import java.util.Set;
+
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -19,32 +28,45 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
+/**
+ * @See {@link InvokeRpcMethodTest}
+ *
+ */
 public class RestconfImplTest {
 
-    private static final RestconfImpl restconfImpl = RestconfImpl.getInstance();
+    private RestconfImpl restconfImpl = null;
+    private static ControllerContext controllerContext = null;
 
     @BeforeClass
     public static void init() throws FileNotFoundException {
-        Set<Module> allModules = TestUtils.loadModulesFrom("/full-versions/yangs");
+        Set<Module> allModules = TestUtils
+                .loadModulesFrom("/full-versions/yangs");
         assertNotNull(allModules);
         SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
-        ControllerContext controllerContext = ControllerContext.getInstance();
+        controllerContext = spy( ControllerContext.getInstance() );
         controllerContext.setSchemas(schemaContext);
-        restconfImpl.setControllerContext(controllerContext);
+
+    }
+
+    @Before
+    public void initMethod()
+    {
+        restconfImpl = RestconfImpl.getInstance();
+        restconfImpl.setControllerContext( controllerContext );
     }
 
     @Test
     public void testExample() throws FileNotFoundException {
-        CompositeNode loadedCompositeNode = TestUtils.readInputToCnSn("/parts/ietf-interfaces_interfaces.xml", XmlToCompositeNodeProvider.INSTANCE);
+        CompositeNode loadedCompositeNode = TestUtils.readInputToCnSn(
+                "/parts/ietf-interfaces_interfaces.xml",
+                XmlToCompositeNodeProvider.INSTANCE);
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
-        when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
-        assertEquals(loadedCompositeNode, brokerFacade.readOperationalData(null));
+        when(brokerFacade.readOperationalData(any(InstanceIdentifier.class)))
+                .thenReturn(loadedCompositeNode);
+        assertEquals(loadedCompositeNode,
+                brokerFacade.readOperationalData(null));
     }
 
+
 }
index eef9e414e93e75d90ec29719d7f93b85952c9400..33d4b325bef2c6abc6424c044e8a572acb619ac2 100644 (file)
@@ -26,7 +26,7 @@ import org.opendaylight.controller.sal.core.api.mount.MountService;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -67,15 +67,13 @@ public class URITest {
 
     @Test
     public void testToInstanceIdentifierListWithNullKey() {
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 400 Bad Request");
+        exception.expect(RestconfDocumentedException.class);
         controllerContext.toInstanceIdentifier("simple-nodes:user/null/boo");
     }
 
     @Test
     public void testToInstanceIdentifierListWithMissingKey() {
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 400 Bad Request");
+        exception.expect(RestconfDocumentedException.class);
         controllerContext.toInstanceIdentifier("simple-nodes:user/foo");
     }
 
@@ -96,29 +94,25 @@ public class URITest {
 
     @Test
     public void testToInstanceIdentifierChoiceException() {
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 400 Bad Request");
+        exception.expect(RestconfDocumentedException.class);
         controllerContext.toInstanceIdentifier("simple-nodes:food/snack");
     }
 
     @Test
     public void testToInstanceIdentifierCaseException() {
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 400 Bad Request");
+        exception.expect(RestconfDocumentedException.class);
         controllerContext.toInstanceIdentifier("simple-nodes:food/sports-arena");
     }
 
     @Test
     public void testToInstanceIdentifierChoiceCaseException() {
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 400 Bad Request");
+        exception.expect(RestconfDocumentedException.class);
         controllerContext.toInstanceIdentifier("simple-nodes:food/snack/sports-arena");
     }
-    
+
     @Test
     public void testToInstanceIdentifierWithoutNode() {
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 400 Bad Request");
+        exception.expect(RestconfDocumentedException.class);
         controllerContext.toInstanceIdentifier("simple-nodes");
     }
 
@@ -142,24 +136,22 @@ public class URITest {
 
     @Test
     public void testMountPointWithoutMountService() throws FileNotFoundException {
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 503 Service Unavailable"); 
-        
+        exception.expect(RestconfDocumentedException.class);
+
         controllerContext.setMountService(null);
         InstanceIdWithSchemaNode instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class/student/name");
     }
-    
+
     @Test
     public void testMountPointWithoutMountPointSchema() {
         initMountService(false);
-        exception.expect(ResponseException.class);
-        exception.expectMessage("HTTP 400 Bad Request"); 
-        
+        exception.expect(RestconfDocumentedException.class);
+
         InstanceIdWithSchemaNode instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class");
     }
-    
+
     public void initMountService(boolean withSchema) {
         MountService mountService = mock(MountService.class);
         controllerContext.setMountService(mountService);
index 7a949b8f2df962ad9efcf6d93b532296263cb98a..e5b0bf507d03212bf2efedaaa18cc2f28f734567 100644 (file)
@@ -50,13 +50,13 @@ public class XmlLeafrefToCnSnTest {
         verifyCommonPartAOfXml(compNode, "", nameSpace);
     }
 
-    private void verifyNullAndEmptyStringSingleNode(CompositeNode compNode, String nameSpace) {
+    private void verifyNullAndEmptyStringSingleNode(final CompositeNode compNode, final String nameSpace) {
         assertEquals("cont", compNode.getNodeType().getLocalName());
 
         SimpleNode<?> lf2 = null;
         SimpleNode<?> lf3 = null;
         int found = 0;
-        for (Node<?> child : compNode.getChildren()) {
+        for (Node<?> child : compNode.getValue()) {
             if (found == 0x3)
                 break;
             if (child instanceof SimpleNode<?>) {
@@ -91,11 +91,11 @@ public class XmlLeafrefToCnSnTest {
         String nameSpaceCont = "data:container:yang";
         assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString());
         assertEquals("cont", compNode.getNodeType().getLocalName());
-        assertEquals(3, compNode.getChildren().size());
+        assertEquals(3, compNode.getValue().size());
         CompositeNode lst1_1 = null;
         CompositeNode lst1_2 = null;
         int loopCount = 0;
-        for (Node<?> node : compNode.getChildren()) {
+        for (Node<?> node : compNode.getValue()) {
             if (node.getNodeType().getLocalName().equals("lf1")) {
                 assertEquals(nameSpaceList, node.getNodeType().getNamespace().toString());
                 assertTrue(node instanceof SimpleNode<?>);
@@ -120,7 +120,7 @@ public class XmlLeafrefToCnSnTest {
         // lst1_2
         SimpleNode<?> lflst11 = null;
         CompositeNode cont11 = null;
-        for (Node<?> node : lst1_2.getChildren()) {
+        for (Node<?> node : lst1_2.getValue()) {
             String nodeName = node.getNodeType().getLocalName();
             if (nodeName.equals("lflst11")) {
                 assertTrue(node instanceof SimpleNode<?>);
@@ -134,9 +134,9 @@ public class XmlLeafrefToCnSnTest {
         }
         assertEquals("221", lflst11.getValue());
 
-        assertEquals(1, cont11.getChildren().size());
-        assertTrue(cont11.getChildren().get(0) instanceof SimpleNode<?>);
-        SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getChildren().get(0);
+        assertEquals(1, cont11.getValue().size());
+        assertTrue(cont11.getValue().get(0) instanceof SimpleNode<?>);
+        SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getValue().get(0);
         assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString());
         assertEquals("lf111", cont11_lf111.getNodeType().getLocalName());
         assertEquals((short) 100, cont11_lf111.getValue());
@@ -154,7 +154,7 @@ public class XmlLeafrefToCnSnTest {
         SimpleNode<?> lflst1_2 = null;
         CompositeNode lst1 = null;
         int lflst1Count = 0;
-        for (Node<?> node : compNode.getChildren()) {
+        for (Node<?> node : compNode.getValue()) {
             if (node.getNodeType().getLocalName().equals("lf1")) {
                 assertTrue(node instanceof SimpleNode<?>);
                 lf1 = (SimpleNode<?>) node;
@@ -183,11 +183,11 @@ public class XmlLeafrefToCnSnTest {
         assertEquals("", lf1.getValue());
         assertEquals("", lflst1_1.getValue());
         assertEquals("", lflst1_2.getValue());
-        assertEquals(1, lst1.getChildren().size());
-        assertEquals("lf11", lst1.getChildren().get(0).getNodeType().getLocalName());
+        assertEquals(1, lst1.getValue().size());
+        assertEquals("lf11", lst1.getValue().get(0).getNodeType().getLocalName());
 
-        assertTrue(lst1.getChildren().get(0) instanceof SimpleNode<?>);
-        assertEquals("", lst1.getChildren().get(0).getValue());
+        assertTrue(lst1.getValue().get(0) instanceof SimpleNode<?>);
+        assertEquals("", lst1.getValue().get(0).getValue());
 
     }
 
@@ -201,7 +201,7 @@ public class XmlLeafrefToCnSnTest {
     }
 
     /**
-     * 
+     *
      * Test case like <lf11 xmlns="namespace1"
      * xmlns:x="namespace">identity</lf11>
      */
@@ -213,7 +213,7 @@ public class XmlLeafrefToCnSnTest {
     }
 
     /**
-     * 
+     *
      * Test case like <cont1 xmlns="namespace1"> <lf11
      * xmlns:x="namespace">identity</lf11> </cont1>
      */
@@ -224,7 +224,7 @@ public class XmlLeafrefToCnSnTest {
     }
 
     /**
-     * 
+     *
      * Test case like <cont1 xmlns="namespace1" xmlns:x="namespace">
      * <lf11>x:identity</lf11> </cont1>
      */
@@ -236,7 +236,7 @@ public class XmlLeafrefToCnSnTest {
     }
 
     /**
-     * 
+     *
      * Test case like (without namespace in xml) <cont1> <lf11>x:identity</lf11>
      * </cont1>
      */
@@ -247,7 +247,7 @@ public class XmlLeafrefToCnSnTest {
     }
 
     /**
-     * 
+     *
      * Test case like (without namespace in xml) <cont1> <lf11>identity</lf11>
      * </cont1>
      */
@@ -257,7 +257,7 @@ public class XmlLeafrefToCnSnTest {
                 "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "identityref:module");
     }
 
-    private void verifyCommonPartAOfXml(CompositeNode compNode, String suf, String nameSpace) {
+    private void verifyCommonPartAOfXml(final CompositeNode compNode, final String suf, final String nameSpace) {
         SimpleNode<?> lf1suf = null;
         SimpleNode<?> lflst1suf_1 = null;
         SimpleNode<?> lflst1suf_2 = null;
@@ -267,7 +267,7 @@ public class XmlLeafrefToCnSnTest {
 
         int lflstCount = 0;
 
-        for (Node<?> node : compNode.getChildren()) {
+        for (Node<?> node : compNode.getValue()) {
             String localName = node.getNodeType().getLocalName();
             if (localName.equals("lf1" + suf)) {
                 assertTrue(node instanceof SimpleNode<?>);
@@ -307,23 +307,23 @@ public class XmlLeafrefToCnSnTest {
         assertEquals("131", lflst1suf_2.getValue());
         assertEquals("str1", lflst1suf_3.getValue());
 
-        assertEquals(1, lst1suf.getChildren().size());
+        assertEquals(1, lst1suf.getValue().size());
 
-        assertTrue(lst1suf.getChildren().get(0) instanceof SimpleNode<?>);
-        SimpleNode<?> lst11_lf11 = (SimpleNode<?>) lst1suf.getChildren().get(0);
+        assertTrue(lst1suf.getValue().get(0) instanceof SimpleNode<?>);
+        SimpleNode<?> lst11_lf11 = (SimpleNode<?>) lst1suf.getValue().get(0);
         assertEquals(nameSpace, lst11_lf11.getNodeType().getNamespace().toString());
         assertEquals("lf11" + suf, lst11_lf11.getNodeType().getLocalName());
         assertEquals("str2", lst11_lf11.getValue());
 
-        assertTrue(cont1suf.getChildren().get(0) instanceof SimpleNode<?>);
-        SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getChildren().get(0);
+        assertTrue(cont1suf.getValue().get(0) instanceof SimpleNode<?>);
+        SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getValue().get(0);
         assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString());
         assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName());
         assertEquals((short) 100, cont1_lf11.getValue());
     }
 
-    private void testIdentityrefToCnSn(String xmlPath, String yangPath, String moduleName, String schemaName,
-            int moduleCount, String resultLocalName, String resultNamespace) {
+    private void testIdentityrefToCnSn(final String xmlPath, final String yangPath, final String moduleName, final String schemaName,
+            final int moduleCount, final String resultLocalName, final String resultNamespace) {
         CompositeNode compositeNode = TestUtils.readInputToCnSn(xmlPath, false, XmlToCompositeNodeProvider.INSTANCE);
         assertNotNull(compositeNode);
 
@@ -339,16 +339,16 @@ public class XmlLeafrefToCnSnTest {
         assertEquals(resultNamespace, qName.getNamespace().toString());
     }
 
-    private SimpleNode<?> getLf11(CompositeNode compositeNode) {
+    private SimpleNode<?> getLf11(final CompositeNode compositeNode) {
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
-        List<Node<?>> childs = compositeNode.getChildren();
+        List<Node<?>> childs = compositeNode.getValue();
         assertEquals(1, childs.size());
         Node<?> nd = childs.iterator().next();
         assertTrue(nd instanceof CompositeNode);
         assertEquals("cont1", nd.getNodeType().getLocalName());
 
-        childs = ((CompositeNode) nd).getChildren();
+        childs = ((CompositeNode) nd).getValue();
         SimpleNode<?> lf11 = null;
         for (Node<?> child : childs) {
             assertTrue(child instanceof SimpleNode);
index f1a18d56a8de60241b64436aa299f2f3c3915de5..5008d28bbfb26ea0e8d9ef8ab2b1814e8736671d 100644 (file)
@@ -7,14 +7,18 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 
 public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
@@ -34,7 +38,7 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
         SimpleNode<?> lf2 = null;
-        for (Node<?> childNode : compositeNode.getChildren()) {
+        for (Node<?> childNode : compositeNode.getValue()) {
             if (childNode instanceof SimpleNode) {
                 if (childNode.getNodeType().getLocalName().equals("lf2")) {
                     lf2 = (SimpleNode<?>) childNode;
@@ -45,7 +49,7 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
         assertNotNull(lf2);
         assertTrue(lf2.getValue() instanceof String);
-        assertEquals("121", (String) lf2.getValue());
+        assertEquals("121", lf2.getValue());
     }
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/yangs/toaster.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/yangs/toaster.yang
new file mode 100644 (file)
index 0000000..571ed0c
--- /dev/null
@@ -0,0 +1,197 @@
+  module toaster {
+
+    yang-version 1;
+
+    namespace
+      "http://netconfcentral.org/ns/toaster";
+
+    prefix toast;
+
+    organization "Netconf Central";
+
+    contact
+      "Andy Bierman <andy@netconfcentral.org>";
+
+    description
+      "YANG version of the TOASTER-MIB.";
+
+    revision "2009-11-20" {
+      description
+        "Toaster module in progress.";
+    }
+
+
+    identity toast-type {
+      description
+        "Base for all bread types supported by the toaster.
+           New bread types not listed here nay be added in the 
+           future.";
+    }
+
+    identity white-bread {
+      base toast:toast-type;
+      description "White bread.";
+    }
+
+    identity wheat-bread {
+      base toast-type;
+      description "Wheat bread.";
+    }
+
+    identity wonder-bread {
+      base toast-type;
+      description "Wonder bread.";
+    }
+
+    identity frozen-waffle {
+      base toast-type;
+      description "Frozen waffle.";
+    }
+
+    identity frozen-bagel {
+      base toast-type;
+      description "Frozen bagel.";
+    }
+
+    identity hash-brown {
+      base toast-type;
+      description "Hash browned potatos.";
+    }
+
+    typedef DisplayString {
+      type string {
+        length "0 .. 255";
+      }
+      description
+        "YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION.";
+      reference
+        "RFC 2579, section 2.";
+
+    }
+
+    container toaster {
+      presence
+        "Indicates the toaster service is available";
+      description
+        "Top-level container for all toaster database objects.";
+      leaf toasterManufacturer {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's manufacturer. For instance, 
+                Microsoft Toaster.";
+      }
+
+      leaf toasterModelNumber {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's model. For instance,
+               Radiant Automatic.";
+      }
+
+      leaf toasterStatus {
+        type enumeration {
+          enum "up" {
+            value 1;
+            description
+              "The toaster knob position is up.
+                      No toast is being made now.";
+          }
+          enum "down" {
+            value 2;
+            description
+              "The toaster knob position is down.
+                      Toast is being made now.";
+          }
+        }
+        config false;
+        mandatory true;
+        description
+          "This variable indicates the current state of 
+               the toaster.";
+      }
+    }  // container toaster
+
+    rpc make-toast {
+      description
+        "Make some toast.
+           The toastDone notification will be sent when 
+           the toast is finished.
+           An 'in-use' error will be returned if toast
+           is already being made.
+           A 'resource-denied' error will be returned 
+           if the toaster service is disabled.";
+      input {
+        leaf toasterDoneness {
+          type uint32 {
+            range "1 .. 10";
+          }
+          default '5';
+          description
+            "This variable controls how well-done is the 
+                   ensuing toast. It should be on a scale of 1 to 10.
+                   Toast made at 10 generally is considered unfit 
+                   for human consumption; toast made at 1 is warmed 
+                   lightly.";
+        }
+
+        leaf toasterToastType {
+          type identityref {
+            base toast:toast-type;
+          }
+          default 'wheat-bread';
+          description
+            "This variable informs the toaster of the type of 
+                   material that is being toasted. The toaster 
+                   uses this information, combined with 
+                   toasterDoneness, to compute for how 
+                   long the material must be toasted to achieve 
+                   the required doneness.";
+        }
+      }
+    }  // rpc make-toast
+
+    rpc testOutput { 
+        output {
+            leaf textOut {
+                type string;
+            }        
+        }
+    }
+
+    rpc cancel-toast {
+      description
+        "Stop making toast, if any is being made.
+           A 'resource-denied' error will be returned 
+           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.";
+          }
+        }
+        description
+          "Indicates the final toast status";
+      }
+    }  // notification toastDone
+  }  // module toaster
index 423d2e48ce7ba73dfdf7eb55528b6c9baf4710ed..8954c058116639b6dae8af9227930209fcfdb81e 100644 (file)
@@ -7,7 +7,6 @@
     <version>1.1-SNAPSHOT</version>
   </parent>
 
-  <groupId>org.opendaylight.controller</groupId>
   <artifactId>sal-rest-docgen</artifactId>
   <packaging>bundle</packaging>
 
@@ -94,7 +93,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.4.0</version>
         <extensions>true</extensions>
         <configuration>
 
index 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 ea08f94ebce89eb51553163eee625db100fef746..c2be488d9301f3b759c2f8e7b5a00e4262e8374e 100644 (file)
@@ -28,130 +28,129 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /* InstanceIdentifierUtils provides utility functions related to InstanceIdentifiers.
  */
-public class InstanceIdentifierUtils {
-
-  /**
-   * Creates an Instance Identifier (path) for node with specified id
-   *
-   * @param nodeId
-   * @return
-   */
-  public static final InstanceIdentifier<Node> createNodePath(NodeId nodeId) {
-    return InstanceIdentifier.builder(Nodes.class) //
-        .child(Node.class, new NodeKey(nodeId)) //
-        .build();
-  }
-
-  /**
-   * Shorten's node child path to node path.
-   *
-   * @param nodeChild child of node, from which we want node path.
-   * @return
-   */
-  public static final InstanceIdentifier<Node> getNodePath(InstanceIdentifier<?> nodeChild) {
-    return nodeChild.firstIdentifierOf(Node.class);
-  }
-
-
-  /**
-   * Creates a table path by appending table specific location to node path
-   *
-   * @param nodePath
-   * @param tableKey
-   * @return
-   */
-  public static final InstanceIdentifier<Table> createTablePath(InstanceIdentifier<Node> nodePath, TableKey tableKey) {
-    return InstanceIdentifier.builder(nodePath)
-        .augmentation(FlowCapableNode.class)
-        .child(Table.class, tableKey)
-        .build();
-  }
-
-  /**
-   * Creates a path for particular flow, by appending flow-specific information
-   * to table path.
-   *
-   * @param table
-   * @param flowKey
-   * @return
-   */
-  public static InstanceIdentifier<Flow> createFlowPath(InstanceIdentifier<Table> table, FlowKey flowKey) {
-    return InstanceIdentifier.builder(table)
-        .child(Flow.class, flowKey)
-        .build();
-  }
-
-  /**
-   * Extract table id from table path.
-   *
-   * @param tablePath
-   * @return
-   */
-  public static Short getTableId(InstanceIdentifier<Table> tablePath) {
-    return tablePath.firstKeyOf(Table.class, TableKey.class).getId();
-  }
-
-  /**
-   * Extracts NodeConnectorKey from node connector path.
-   */
-  public static NodeConnectorKey getNodeConnectorKey(InstanceIdentifier<?> nodeConnectorPath) {
-    return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
-  }
-
-  /**
-   * Extracts NodeKey from node path.
-   */
-  public static NodeKey getNodeKey(InstanceIdentifier<?> nodePath) {
-    return nodePath.firstKeyOf(Node.class, NodeKey.class);
-  }
-
-
-  //
-  public static final InstanceIdentifier<NodeConnector> createNodeConnectorIdentifier(String nodeIdValue,
-                                                                                      String nodeConnectorIdValue) {
-    return InstanceIdentifier.builder(createNodePath(new NodeId(nodeIdValue))) //
-        .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorIdValue))) //
-        .build();
-  }
-
-  /**
-   * @param nodeConnectorRef
-   * @return
-   */
-  public static InstanceIdentifier<Node> generateNodeInstanceIdentifier(NodeConnectorRef nodeConnectorRef) {
-    return nodeConnectorRef.getValue().firstIdentifierOf(Node.class);
-  }
-
-  /**
-   * @param nodeConnectorRef
-   * @param flowTableKey
-   * @return
-   */
-  public static InstanceIdentifier<Table> generateFlowTableInstanceIdentifier(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
-    return InstanceIdentifier.builder(generateNodeInstanceIdentifier(nodeConnectorRef))
-        .augmentation(FlowCapableNode.class)
-        .child(Table.class, flowTableKey)
-        .build();
-  }
-
-  /**
-   * @param nodeConnectorRef
-   * @param flowTableKey
-   * @param flowKey
-   * @return
-   */
-  public static InstanceIdentifier<Flow> generateFlowInstanceIdentifier(NodeConnectorRef nodeConnectorRef,
-                                                                        TableKey flowTableKey,
-                                                                        FlowKey flowKey) {
-    return InstanceIdentifier.builder(generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey))
-        .child(Flow.class, flowKey)
-        .build();
-  }
-
-  public static InstanceIdentifier<Topology> generateTopologyInstanceIdentifier(String topologyId) {
-    return InstanceIdentifier.builder(NetworkTopology.class)
-        .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
-        .build();
-  }
+public final class InstanceIdentifierUtils {
+
+    private InstanceIdentifierUtils() {
+        throw new UnsupportedOperationException("Utility class should never be instantiated");
+    }
+
+    /**
+     * Creates an Instance Identifier (path) for node with specified id
+     *
+     * @param nodeId
+     * @return
+     */
+    public static final InstanceIdentifier<Node> createNodePath(final NodeId nodeId) {
+        return InstanceIdentifier.builder(Nodes.class) //
+                .child(Node.class, new NodeKey(nodeId)) //
+                .build();
+    }
+
+    /**
+     * Shorten's node child path to node path.
+     *
+     * @param nodeChild child of node, from which we want node path.
+     * @return
+     */
+    public static final InstanceIdentifier<Node> getNodePath(final InstanceIdentifier<?> nodeChild) {
+        return nodeChild.firstIdentifierOf(Node.class);
+    }
+
+
+    /**
+     * Creates a table path by appending table specific location to node path
+     *
+     * @param nodePath
+     * @param tableKey
+     * @return
+     */
+    public static final InstanceIdentifier<Table> createTablePath(final InstanceIdentifier<Node> nodePath, final TableKey tableKey) {
+        return nodePath.builder()
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, tableKey)
+                .build();
+    }
+
+    /**
+     * Creates a path for particular flow, by appending flow-specific information
+     * to table path.
+     *
+     * @param table
+     * @param flowKey
+     * @return
+     */
+    public static InstanceIdentifier<Flow> createFlowPath(final InstanceIdentifier<Table> table, final FlowKey flowKey) {
+        return table.child(Flow.class, flowKey);
+    }
+
+    /**
+     * Extract table id from table path.
+     *
+     * @param tablePath
+     * @return
+     */
+    public static Short getTableId(final InstanceIdentifier<Table> tablePath) {
+        return tablePath.firstKeyOf(Table.class, TableKey.class).getId();
+    }
+
+    /**
+     * Extracts NodeConnectorKey from node connector path.
+     */
+    public static NodeConnectorKey getNodeConnectorKey(final InstanceIdentifier<?> nodeConnectorPath) {
+        return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
+    }
+
+    /**
+     * Extracts NodeKey from node path.
+     */
+    public static NodeKey getNodeKey(final InstanceIdentifier<?> nodePath) {
+        return nodePath.firstKeyOf(Node.class, NodeKey.class);
+    }
+
+
+    //
+    public static final InstanceIdentifier<NodeConnector> createNodeConnectorIdentifier(final String nodeIdValue,
+            final String nodeConnectorIdValue) {
+        return createNodePath(new NodeId(nodeIdValue))
+                .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorIdValue)));
+    }
+
+    /**
+     * @param nodeConnectorRef
+     * @return
+     */
+    public static InstanceIdentifier<Node> generateNodeInstanceIdentifier(final NodeConnectorRef nodeConnectorRef) {
+        return nodeConnectorRef.getValue().firstIdentifierOf(Node.class);
+    }
+
+    /**
+     * @param nodeConnectorRef
+     * @param flowTableKey
+     * @return
+     */
+    public static InstanceIdentifier<Table> generateFlowTableInstanceIdentifier(final NodeConnectorRef nodeConnectorRef, final TableKey flowTableKey) {
+        return generateNodeInstanceIdentifier(nodeConnectorRef).builder()
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, flowTableKey)
+                .build();
+    }
+
+    /**
+     * @param nodeConnectorRef
+     * @param flowTableKey
+     * @param flowKey
+     * @return
+     */
+    public static InstanceIdentifier<Flow> generateFlowInstanceIdentifier(final NodeConnectorRef nodeConnectorRef,
+            final TableKey flowTableKey,
+            final FlowKey flowKey) {
+        return generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey).child(Flow.class, flowKey);
+    }
+
+    public static InstanceIdentifier<Topology> generateTopologyInstanceIdentifier(final String topologyId) {
+        return InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
+                .build();
+    }
 }
 
index 3520d812d7e1b0a2e591b28f69a29630b61df08b..50f74cc33f99e40c91e3b2241c970ff650391928 100644 (file)
@@ -7,11 +7,19 @@
  */
 package org.opendaylight.controller.sample.l2switch.md.flow;
 
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
 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.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
@@ -23,128 +31,110 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 /**
  */
 public class FlowWriterServiceImplTest {
-  private DataBrokerService dataBrokerService;
-  private NodeConnectorRef srcNodeConnectorRef;
-  private NodeConnectorRef destNodeConnectorRef;
-  private MacAddress destMacAddress;
-  private MacAddress srcMacAddress;
-  private DataModificationTransaction dataModificationTransaction;
-  private NetworkGraphService networkGraphService;
+    private DataBrokerService dataBrokerService;
+    private NodeConnectorRef srcNodeConnectorRef;
+    private NodeConnectorRef destNodeConnectorRef;
+    private MacAddress destMacAddress;
+    private MacAddress srcMacAddress;
+    private DataModificationTransaction dataModificationTransaction;
+    private NetworkGraphService networkGraphService;
 
-  @Before
-  public void init() {
-    dataBrokerService = mock(DataBrokerService.class);
-    networkGraphService = mock(NetworkGraphService.class);
-    //build source node connector ref
-    InstanceIdentifier<Nodes> srcNodesInstanceIdentifier
-        = InstanceIdentifier.builder(Nodes.class)
-        .build();
-    InstanceIdentifier<Node> srcNodeInstanceIdentifier
-        = InstanceIdentifier.builder(srcNodesInstanceIdentifier)
-        .child(Node.class, new NodeKey(new NodeId("openflow:1")))
-        .build();
-    InstanceIdentifier<NodeConnector> srcNodeConnectorInstanceIdentifier
-        = InstanceIdentifier.builder(srcNodeInstanceIdentifier)
-        .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:2")))
-        .build();
-    srcNodeConnectorRef = new NodeConnectorRef(srcNodeConnectorInstanceIdentifier);
+    @Before
+    public void init() {
+        dataBrokerService = mock(DataBrokerService.class);
+        networkGraphService = mock(NetworkGraphService.class);
+        //build source node connector ref
+        InstanceIdentifier<Nodes> srcNodesInstanceIdentifier = InstanceIdentifier.create(Nodes.class);
+        InstanceIdentifier<Node> srcNodeInstanceIdentifier = srcNodesInstanceIdentifier
+                .child(Node.class, new NodeKey(new NodeId("openflow:1")));
+        InstanceIdentifier<NodeConnector> srcNodeConnectorInstanceIdentifier = srcNodeInstanceIdentifier
+                .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:2")));
+        srcNodeConnectorRef = new NodeConnectorRef(srcNodeConnectorInstanceIdentifier);
 
-    //build dest node connector ref
-    InstanceIdentifier<Nodes> nodesInstanceIdentifier
+        //build dest node connector ref
+        InstanceIdentifier<Nodes> nodesInstanceIdentifier
         = InstanceIdentifier.builder(Nodes.class)
         .build();
-    InstanceIdentifier<Node> nodeInstanceIdentifier
-        = InstanceIdentifier.builder(nodesInstanceIdentifier)
-        .child(Node.class, new NodeKey(new NodeId("openflow:2")))
-        .build();
-    InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier
-        = InstanceIdentifier.builder(nodeInstanceIdentifier)
-        .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:2:2")))
-        .build();
-    destNodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier);
-    destMacAddress = new MacAddress("00:0a:95:9d:68:16");
-    srcMacAddress = new MacAddress("00:0a:95:8c:97:24");
-    dataModificationTransaction = mock(DataModificationTransaction.class);
-    when(dataBrokerService.beginTransaction()).thenReturn(dataModificationTransaction);
-  }
+        InstanceIdentifier<Node> nodeInstanceIdentifier =
+                nodesInstanceIdentifier.child(Node.class, new NodeKey(new NodeId("openflow:2")));
+        InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier =
+                nodeInstanceIdentifier.child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:2:2")));
+        destNodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier);
+        destMacAddress = new MacAddress("00:0a:95:9d:68:16");
+        srcMacAddress = new MacAddress("00:0a:95:8c:97:24");
+        dataModificationTransaction = mock(DataModificationTransaction.class);
+        when(dataBrokerService.beginTransaction()).thenReturn(dataModificationTransaction);
+    }
 
-  @Test
-  public void testFlowWriterServiceImpl_NPEWhenDataBrokerServiceIsNull() throws Exception {
-    try {
-      new FlowWriterServiceImpl(null, networkGraphService);
-      fail("Expected null pointer exception.");
-    } catch(NullPointerException npe) {
-      assertEquals("dataBrokerService should not be null.", npe.getMessage());
+    @Test
+    public void testFlowWriterServiceImpl_NPEWhenDataBrokerServiceIsNull() throws Exception {
+        try {
+            new FlowWriterServiceImpl(null, networkGraphService);
+            fail("Expected null pointer exception.");
+        } catch(NullPointerException npe) {
+            assertEquals("dataBrokerService should not be null.", npe.getMessage());
+        }
     }
-  }
 
-  @Test
-  public void testAddMacToMacFlow_NPEWhenNullSourceMacDestMacAndNodeConnectorRef() throws Exception {
-    FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
-    try {
-      flowWriterService.addMacToMacFlow(null, null, null);
-      fail("Expected null pointer exception.");
-    } catch(NullPointerException npe) {
-      assertEquals("Destination mac address should not be null.", npe.getMessage());
+    @Test
+    public void testAddMacToMacFlow_NPEWhenNullSourceMacDestMacAndNodeConnectorRef() throws Exception {
+        FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+        try {
+            flowWriterService.addMacToMacFlow(null, null, null);
+            fail("Expected null pointer exception.");
+        } catch(NullPointerException npe) {
+            assertEquals("Destination mac address should not be null.", npe.getMessage());
+        }
     }
-  }
 
-  @Test
-  public void testAddMacToMacFlow_NPEWhenSourceMacNullMac() throws Exception {
-    FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
-    try {
-      flowWriterService.addMacToMacFlow(null, null, destNodeConnectorRef);
-      fail("Expected null pointer exception.");
-    } catch(NullPointerException npe) {
-      assertEquals("Destination mac address should not be null.", npe.getMessage());
+    @Test
+    public void testAddMacToMacFlow_NPEWhenSourceMacNullMac() throws Exception {
+        FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+        try {
+            flowWriterService.addMacToMacFlow(null, null, destNodeConnectorRef);
+            fail("Expected null pointer exception.");
+        } catch(NullPointerException npe) {
+            assertEquals("Destination mac address should not be null.", npe.getMessage());
+        }
     }
-  }
 
-  @Test
-  public void testAddMacToMacFlow_NPEWhenNullSourceMacNodeConnectorRef() throws Exception {
-    FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
-    try {
-      flowWriterService.addMacToMacFlow(null, destMacAddress, null);
-      fail("Expected null pointer exception.");
-    } catch(NullPointerException npe) {
-      assertEquals("Destination port should not be null.", npe.getMessage());
+    @Test
+    public void testAddMacToMacFlow_NPEWhenNullSourceMacNodeConnectorRef() throws Exception {
+        FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+        try {
+            flowWriterService.addMacToMacFlow(null, destMacAddress, null);
+            fail("Expected null pointer exception.");
+        } catch(NullPointerException npe) {
+            assertEquals("Destination port should not be null.", npe.getMessage());
+        }
     }
-  }
 
-  @Test
-  public void testAddMacToMacFlow_WhenNullSourceMac() throws Exception {
-    FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
-    flowWriterService.addMacToMacFlow(null, destMacAddress, destNodeConnectorRef);
-    verify(dataBrokerService, times(1)).beginTransaction();
-    verify(dataModificationTransaction, times(1)).commit();
-  }
+    @Test
+    public void testAddMacToMacFlow_WhenNullSourceMac() throws Exception {
+        FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+        flowWriterService.addMacToMacFlow(null, destMacAddress, destNodeConnectorRef);
+        verify(dataBrokerService, times(1)).beginTransaction();
+        verify(dataModificationTransaction, times(1)).commit();
+    }
 
-  @Test
-  public void testAddMacToMacFlow_WhenSrcAndDestMacAreSame() throws Exception {
-    FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
-    flowWriterService.addMacToMacFlow(new MacAddress(destMacAddress.getValue()), destMacAddress, destNodeConnectorRef);
-    verify(dataBrokerService, never()).beginTransaction();
-    verify(dataModificationTransaction, never()).commit();
+    @Test
+    public void testAddMacToMacFlow_WhenSrcAndDestMacAreSame() throws Exception {
+        FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+        flowWriterService.addMacToMacFlow(new MacAddress(destMacAddress.getValue()), destMacAddress, destNodeConnectorRef);
+        verify(dataBrokerService, never()).beginTransaction();
+        verify(dataModificationTransaction, never()).commit();
 
-  }
+    }
 
-  @Test
-  public void testAddMacToMacFlow_SunnyDay() throws Exception {
-    FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
-    flowWriterService.addMacToMacFlow(srcMacAddress, destMacAddress, destNodeConnectorRef);
-    verify(dataBrokerService, times(1)).beginTransaction();
-    verify(dataModificationTransaction, times(1)).commit();
-  }
+    @Test
+    public void testAddMacToMacFlow_SunnyDay() throws Exception {
+        FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+        flowWriterService.addMacToMacFlow(srcMacAddress, destMacAddress, destNodeConnectorRef);
+        verify(dataBrokerService, times(1)).beginTransaction();
+        verify(dataModificationTransaction, times(1)).commit();
+    }
 
 }
index b4da5a3d226f05bfd02fe21890ea0307e7efb2ce..2ecd7e7b684fe8bdafd6af17527cbb21daeee83f 100644 (file)
@@ -37,7 +37,9 @@ 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.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -157,14 +159,15 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
                 LOG.info( "Toaster is already making toast" );
 
                 RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Arrays.asList(
-                        RpcErrors.getRpcError( null, null, null, null,
-                                               "Toaster is busy", null, null ) ) );
+                        RpcErrors.getRpcError( "", "in-use", null, ErrorSeverity.WARNING,
+                                               "Toaster is busy", ErrorType.APPLICATION, 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 ) ) );
+                        RpcErrors.getRpcError( "out-of-stock", "resource-denied", null, null,
+                                               "Toaster is out of bread",
+                                               ErrorType.APPLICATION, null ) ) );
                 return Futures.immediateFuture(result);
             }
             else {
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 442c504cce28ebc96b26e7bba589563ee3bef1d4..1b74d49c4f6fc4b30069c12fd5d9416e5561af63 100644 (file)
@@ -30,8 +30,8 @@ public class ArrayAttributeReadingStrategy extends AbstractAttributeReadingStrat
     @Override
     AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException {
         List<Object> innerList = Lists.newArrayList();
-        for (int i = 0; i < configNodes.size(); i++) {
-            innerList.add(innerStrategy.readElement(Lists.newArrayList(configNodes.get(i))).getValue());
+        for (XmlElement configNode : configNodes) {
+            innerList.add(innerStrategy.readElement(Lists.newArrayList(configNode)).getValue());
         }
         return AttributeConfigElement.create(getNullableDefault(), innerList);
     }
index bf9eee7f267fd5ded0f73f431443eecb9fa76183..08f3c73ac2646025ff8e617a4cc0a95f3afec492 100644 (file)
@@ -8,20 +8,16 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
 
 import com.google.common.base.Preconditions;
+import java.util.List;
+import java.util.Map;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
 
 public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
 
     private static final Object PREFIX_SEPARATOR = ":";
-    private static final Logger logger = LoggerFactory.getLogger(ObjectNameAttributeReadingStrategy.class);
 
     public ObjectNameAttributeReadingStrategy(String nullableDefault) {
         super(nullableDefault);
@@ -39,8 +35,7 @@ public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReading
     }
 
     private ObjectNameAttributeMappingStrategy.MappedDependency resolve(XmlElement firstChild) throws NetconfDocumentedException{
-        XmlElement typeElement = null;
-        typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+        XmlElement typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
         Map.Entry<String, String> prefixNamespace = typeElement.findNamespaceOfTextContent();
 
         String serviceName = checkPrefixAndExtractServiceName(typeElement, prefixNamespace);
@@ -54,7 +49,7 @@ public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReading
 
     public static String checkPrefixAndExtractServiceName(XmlElement typeElement, Map.Entry<String, String> prefixNamespace) throws NetconfDocumentedException {
         String serviceName = typeElement.getTextContent();
-
+        // FIXME: comparing Entry with String:
         Preconditions.checkState(!prefixNamespace.equals(""), "Service %s value not prefixed with namespace",
                 XmlNetconfConstants.TYPE_KEY);
         String prefix = prefixNamespace.getKey() + PREFIX_SEPARATOR;
index cb8f66081b7dee8b0205b34132ed0b131dac98c6..8f6a7cd1e4d2e4f19918d97fdfbb8f928060a696 100644 (file)
@@ -12,13 +12,8 @@ import com.google.common.base.Preconditions;
 import java.util.List;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
-    private static final Logger logger = LoggerFactory.getLogger(SimpleAttributeReadingStrategy.class);
-
-
     public SimpleAttributeReadingStrategy(String nullableDefault) {
         super(nullableDefault);
     }
@@ -29,20 +24,7 @@ public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStra
         Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + xmlElement
                 + " but was " + configNodes.size());
 
-        String textContent = "";
-        try{
-            textContent = readElementContent(xmlElement);
-        }catch(IllegalStateException | NullPointerException e) {
-            // yuma sends <attribute /> for empty value instead of <attribute></attribute>
-            logger.warn("Ignoring exception caused by failure to read text element", e);
-        }
-
-        if (null == textContent){
-            throw new NetconfDocumentedException(String.format("This element should contain text %s", xmlElement),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.invalid_value,
-                    NetconfDocumentedException.ErrorSeverity.error);
-        }
+        String textContent = readElementContent(xmlElement);
         return AttributeConfigElement.create(postprocessNullableDefault(getNullableDefault()),
                 postprocessParsedValue(textContent));
     }
index 01844f27d4cb8609d8df9b4916f7fbe69a47eac2..4d984acee0206c1cce11b23f6f4f0dd1415506f8 100644 (file)
@@ -10,28 +10,21 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
-
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import java.util.Map;
-import java.util.Map.Entry;
 
 public class ObjectMapper extends AttributeIfcSwitchStatement<AttributeMappingStrategy<?, ? extends OpenType<?>>> {
 
-    private final ServiceRegistryWrapper dependencyTracker;
-
-    public ObjectMapper(ServiceRegistryWrapper depTracker) {
-        this.dependencyTracker = depTracker;
-    }
 
     public Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> prepareMapping(
             Map<String, AttributeIfc> configDefinition) {
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/AbstractAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/AbstractAttributeWritingStrategy.java
deleted file mode 100644 (file)
index 61465f9..0000000
+++ /dev/null
@@ -1,14 +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.confignetconfconnector.mapping.attributes.toxml;
-
-public abstract class AbstractAttributeWritingStrategy {
-    protected Object preprocess(Object value) {
-        return value;
-    }
-}
index 66b945d14b8eca0dce2157bedba23bed403f0fa6..68c8c6fce39eed748dcd9f9725c1c0c16c85c133 100644 (file)
@@ -40,8 +40,9 @@ public class ObjectNameAttributeWritingStrategy implements AttributeWritingStrat
         String refName = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getRefName();
         String namespaceForType = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getNamespace();
 
-        Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(XmlNetconfConstants.PREFIX, XmlNetconfConstants.TYPE_KEY), XmlNetconfConstants.PREFIX,
-                moduleName, Optional.<String>of(namespaceForType));
+        Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document,  XmlNetconfConstants.TYPE_KEY, XmlNetconfConstants.PREFIX,
+                namespaceForType, moduleName);
+
         innerNode.appendChild(typeElement);
 
         final Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, refName, Optional.<String>absent());
index a74afd08122ef026d235f90192207dc121a627d8..644df0a7f95aa38b02952b45914b97c3414ae400 100644 (file)
@@ -46,7 +46,7 @@ public class RuntimeBeanEntryWritingStrategy extends CompositeAttributeWritingSt
             Util.checkType(runtimeBeanInstanceMappingEntry.getValue(), Map.class);
             Map<?, ?> innerMap = (Map<?, ?>) runtimeBeanInstanceMappingEntry.getValue();
             Element runtimeInstanceNode = XmlUtil.createElement(getDocument(), "_"
-                    + (String) runtimeBeanInstanceMappingEntry.getKey(), Optional.<String>absent());
+                    + runtimeBeanInstanceMappingEntry.getKey(), Optional.<String>absent());
             innerNode.appendChild(runtimeInstanceNode);
 
             for (Entry<?, ?> innerObjectEntry : innerMap.entrySet()) {
index ed3bb2a9d97b5db100aa73fa1c37588bca76d6ce..a2b8e0bfdf6b97a5cc4cdf1e361084e6be0d1078 100644 (file)
@@ -43,9 +43,8 @@ public class SimpleIdentityRefAttributeWritingStrategy extends SimpleAttributeWr
     @Override
     protected Element createElement(Document doc, String key, String value, Optional<String> namespace) {
         QName qName = QName.create(value);
-        String identity = qName.getLocalName();
+        String identityValue = qName.getLocalName();
         String identityNamespace = qName.getNamespace().toString();
-        Element element = XmlUtil.createPrefixedTextElement(doc, XmlUtil.createPrefixedValue(PREFIX, key), PREFIX, identity, Optional.<String>of(identityNamespace));
-        return element;
+        return XmlUtil.createTextElementWithNamespacedContent(doc, key, PREFIX, identityNamespace, identityValue);
     }
 }
index 854f99c5c0522902f1c2f7288c353ba66dfe28aa..1492066289d0569933e3b51a574bc03488a42df3 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.HashMultimap;
@@ -31,7 +33,6 @@ import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-import static com.google.common.base.Preconditions.checkState;
 
 
 public class Config {
@@ -97,13 +98,12 @@ public class Config {
         Map<String, Map<String, Collection<ObjectName>>> moduleToInstances = getMappedInstances(instancesToMap,
                 moduleConfigs);
 
-        Element root = dataElement;
         if (maybeNamespace.isPresent()) {
-            root.setAttributeNS(maybeNamespace.get(), dataElement.getNodeName(), "xmlns");
+            dataElement.setAttributeNS(maybeNamespace.get(), dataElement.getNodeName(), "xmlns");
         }
 
         Element modulesElement = XmlUtil.createElement(document, XmlNetconfConstants.MODULES_KEY, Optional.of(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
-        root.appendChild(modulesElement);
+        dataElement.appendChild(modulesElement);
         for (String moduleNamespace : moduleToInstances.keySet()) {
             for (Entry<String, Collection<ObjectName>> moduleMappingEntry : moduleToInstances.get(moduleNamespace)
                     .entrySet()) {
@@ -115,15 +115,15 @@ public class Config {
                 }
 
                 for (ObjectName objectName : moduleMappingEntry.getValue()) {
-                    modulesElement.appendChild(mapping.toXml(objectName, serviceTracker, document, moduleNamespace));
+                    modulesElement.appendChild(mapping.toXml(objectName, document, moduleNamespace));
                 }
 
             }
         }
 
-        root.appendChild(Services.toXml(serviceTracker, document));
+        dataElement.appendChild(Services.toXml(serviceTracker, document));
 
-        return root;
+        return dataElement;
     }
 
     // TODO refactor, replace string representing namespace with namespace class
index 0fe5fad29c1d4ad20e5cb67c3d8c21357e791f46..ff1d719c57877c2df4710701d9d6f0bd65075b07 100644 (file)
@@ -11,7 +11,12 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.confi
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenType;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
@@ -29,35 +34,33 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.edi
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import javax.management.openmbean.OpenType;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 public final class InstanceConfig {
     private static final Logger logger = LoggerFactory.getLogger(InstanceConfig.class);
 
     private final Map<String, AttributeIfc> yangToAttrConfig;
+    private final String nullableDummyContainerName;
     private final Map<String, AttributeIfc> jmxToAttrConfig;
     private final ConfigRegistryClient configRegistryClient;
 
-    public InstanceConfig(ConfigRegistryClient configRegistryClient, Map<String, AttributeIfc> yangNamesToAttributes) {
+    public InstanceConfig(ConfigRegistryClient configRegistryClient, Map<String, AttributeIfc> yangNamesToAttributes,
+                          String nullableDummyContainerName) {
+
         this.yangToAttrConfig = yangNamesToAttributes;
+        this.nullableDummyContainerName = nullableDummyContainerName;
         this.jmxToAttrConfig = reverseMap(yangNamesToAttributes);
         this.configRegistryClient = configRegistryClient;
     }
 
-    private Map<String, Object> getMappedConfiguration(ObjectName on, ServiceRegistryWrapper depTracker) {
+    private Map<String, Object> getMappedConfiguration(ObjectName on) {
 
         // TODO make field, mappingStrategies can be instantiated only once
-        Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> mappingStrategies = new ObjectMapper(depTracker)
+        Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> mappingStrategies = new ObjectMapper()
                 .prepareMapping(jmxToAttrConfig);
 
         Map<String, Object> toXml = Maps.newHashMap();
@@ -84,24 +87,26 @@ public final class InstanceConfig {
         return toXml;
     }
 
-    public Element toXml(ObjectName on, ServiceRegistryWrapper depTracker, String namespace, Document document, Element rootElement) {
-
-        Element cfgElement = rootElement;
-
+    public Element toXml(ObjectName on, String namespace, Document document, Element rootElement) {
         Map<String, AttributeWritingStrategy> strats = new ObjectXmlWriter().prepareWriting(yangToAttrConfig, document);
-
-        Map<String, Object> mappedConfig = getMappedConfiguration(on, depTracker);
-
+        Map<String, Object> mappedConfig = getMappedConfiguration(on);
+        Element parentElement;
+        if (nullableDummyContainerName != null) {
+            Element dummyElement = XmlUtil.createElement(document, nullableDummyContainerName, Optional.of(namespace));
+            rootElement.appendChild(dummyElement);
+            parentElement = dummyElement;
+        } else {
+            parentElement = rootElement;
+        }
         for (Entry<String, ?> mappingEntry : mappedConfig.entrySet()) {
             try {
-                strats.get(mappingEntry.getKey()).writeElement(cfgElement, namespace, mappingEntry.getValue());
+                strats.get(mappingEntry.getKey()).writeElement(parentElement, namespace, mappingEntry.getValue());
             } catch (Exception e) {
                 throw new IllegalStateException("Unable to write value " + mappingEntry.getValue() + " for attribute "
                         + mappingEntry.getValue(), e);
             }
         }
-
-        return cfgElement;
+        return rootElement;
     }
 
     private void resolveConfiguration(InstanceConfigElementResolved mappedConfig, ServiceRegistryWrapper depTracker) {
@@ -129,34 +134,59 @@ public final class InstanceConfig {
     }
 
     public InstanceConfigElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper services, String moduleNamespace,
-                                                 EditStrategyType defaultStrategy, Multimap<String, String> providedServices, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
+                                                 EditStrategyType defaultStrategy,
+                                                 Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
         Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
 
         Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig, identityMap);
         List<XmlElement> recognisedChildren = Lists.newArrayList();
 
-        XmlElement type = null;
-        XmlElement name = null;
-        type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
-        name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
-        List<XmlElement> typeAndName = Lists.newArrayList(type, name);
+        XmlElement typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+        XmlElement nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
+        List<XmlElement> typeAndNameElements = Lists.newArrayList(typeElement, nameElement);
+
+        // if dummy container was defined in yang, set moduleElement to its content
+        if (nullableDummyContainerName != null) {
+            int size = moduleElement.getChildElements().size();
+            int expectedChildNodes = 1 + typeAndNameElements.size();
+            if (size > expectedChildNodes) {
+                throw new NetconfDocumentedException("Error reading module " + typeElement.getTextContent() + " : " +
+                        nameElement.getTextContent() + " - Expected " + expectedChildNodes +" child nodes, " +
+                        "one of them with name " + nullableDummyContainerName +
+                        ", got " + size + " elements.");
+            }
+            if (size == expectedChildNodes) {
+                try {
+                    moduleElement = moduleElement.getOnlyChildElement(nullableDummyContainerName, moduleNamespace);
+                } catch (NetconfDocumentedException e) {
+                    throw new NetconfDocumentedException("Error reading module " + typeElement.getTextContent() + " : " +
+                            nameElement.getTextContent() + " - Expected child node with name " + nullableDummyContainerName +
+                            "." + e.getMessage());
+                }
+            } // else 2 elements, no need to descend
+        }
 
         for (Entry<String, AttributeReadingStrategy> readStratEntry : strats.entrySet()) {
             List<XmlElement> configNodes = getConfigNodes(moduleElement, moduleNamespace, readStratEntry.getKey(),
-                    recognisedChildren, typeAndName);
+                    recognisedChildren, typeAndNameElements);
             AttributeConfigElement readElement = readStratEntry.getValue().readElement(configNodes);
             retVal.put(readStratEntry.getKey(), readElement);
         }
 
-        recognisedChildren.addAll(typeAndName);
-        moduleElement.checkUnrecognisedElements(recognisedChildren);
-
+        recognisedChildren.addAll(typeAndNameElements);
+        try {
+            moduleElement.checkUnrecognisedElements(recognisedChildren);
+        } catch (NetconfDocumentedException e) {
+            throw new NetconfDocumentedException("Error reading module " + typeElement.getTextContent() + " : " +
+                    nameElement.getTextContent() + " - " +
+                    e.getMessage(), e.getErrorType(), e.getErrorTag(),e.getErrorSeverity(),e.getErrorInfo());
+        }
         // TODO: add check for conflicts between global and local edit strategy
         String perInstanceEditStrategy = moduleElement.getAttribute(XmlNetconfConstants.OPERATION_ATTR_KEY,
                 XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
 
         InstanceConfigElementResolved instanceConfigElementResolved = perInstanceEditStrategy.equals("") ? new InstanceConfigElementResolved(
-                retVal, defaultStrategy, providedServices) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy, providedServices);
+                retVal, defaultStrategy) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy);
 
         resolveConfiguration(instanceConfigElementResolved, services);
         return instanceConfigElementResolved;
index c9605af5868db41a4910523d61347d2d83ae1729..ef5ba753d320d8198cbe5c1a09925835a4cc8533 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
-import com.google.common.collect.Multimap;
 import java.util.Map;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
@@ -24,20 +23,17 @@ public class InstanceConfigElementResolved {
 
     private final EditStrategyType editStrategy;
     private final Map<String, AttributeConfigElement> configuration;
-    private final Multimap<String, String> providedServices;
 
-    public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) throws NetconfDocumentedException {
-        EditStrategyType valueOf = null;
-        valueOf = parseStrategy(currentStrategy, defaultStrategy);
-        this.editStrategy = valueOf;
+    public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration,
+                                         EditStrategyType defaultStrategy)
+            throws NetconfDocumentedException {
+        this.editStrategy = parseStrategy(currentStrategy, defaultStrategy);
         this.configuration = configuration;
-        this.providedServices = providedServices;
     }
 
-    public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
+    public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy) {
         editStrategy = defaultStrategy;
         this.configuration = configuration;
-        this.providedServices = providedServices;
     }
 
 
@@ -49,7 +45,7 @@ public class InstanceConfigElementResolved {
 
 
     public EditConfigStrategy getEditStrategy() {
-        return editStrategy.getFittingStrategy(providedServices);
+        return editStrategy.getFittingStrategy();
     }
 
     public Map<String, AttributeConfigElement> getConfiguration() {
index a5a625a2d6859a373511a1c22ffc9b98c9df6521..0c2b0e228e8c6763aea207c978aabdc02cd11dc1 100644 (file)
@@ -9,8 +9,9 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.Map;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
@@ -18,76 +19,43 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.edi
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.opendaylight.yangtools.yang.common.QName;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-
 public class ModuleConfig {
 
     private final String moduleName;
     private final InstanceConfig instanceConfig;
-    private final Multimap<String, String> providedServices;
 
-    public ModuleConfig(String moduleName, InstanceConfig mbeanMapping, Collection<QName> providedServices) {
+    public ModuleConfig(String moduleName, InstanceConfig mbeanMapping) {
         this.moduleName = moduleName;
         this.instanceConfig = mbeanMapping;
-        this.providedServices = mapServices(providedServices);
     }
 
-    private Multimap<String, String> mapServices(Collection<QName> providedServices) {
-        Multimap<String, String> mapped = HashMultimap.create();
-
-        for (QName providedService : providedServices) {
-            String key = providedService.getNamespace().toString();
-            mapped.put(key, providedService.getLocalName());
-        }
-
-        return  mapped;
-    }
-
-    public InstanceConfig getMbeanMapping() {
-        return instanceConfig;
-    }
+    public Element toXml(ObjectName instanceON, Document document, String namespace) {
+        Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.<String>absent());
 
-    public Multimap<String, String> getProvidedServices() {
-        return providedServices;
-    }
+        // type belongs to config.yang namespace, but needs to be <type prefix:moduleNS>prefix:moduleName</type>
 
-    public Element toXml(ObjectName instanceON, ServiceRegistryWrapper depTracker, Document document, String namespace) {
-        Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.<String>absent());
-        // Xml.addNamespaceAttr(document, root, namespace);
+        Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document, XmlNetconfConstants.TYPE_KEY,
+                XmlNetconfConstants.PREFIX, namespace, moduleName);
 
-        final String prefix = getPrefix();
-        Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.TYPE_KEY), prefix,
-                moduleName, Optional.<String>of(namespace));
-        // Xml.addNamespaceAttr(document, typeElement,
-        // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
         root.appendChild(typeElement);
+        // name belongs to config.yang namespace
+        String instanceName = ObjectNameUtil.getInstanceName(instanceON);
+        Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, instanceName, Optional.<String>absent());
 
-        Element nameElement = XmlUtil.createTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.NAME_KEY),
-                ObjectNameUtil.getInstanceName(instanceON), Optional.<String>of(namespace));
-        // Xml.addNamespaceAttr(document, nameElement,
-        // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
         root.appendChild(nameElement);
 
-        root = instanceConfig.toXml(instanceON, depTracker, namespace, document, root);
+        root = instanceConfig.toXml(instanceON, namespace, document, root);
 
         return root;
     }
 
-    private String getPrefix() {
-        return XmlNetconfConstants.PREFIX;
-    }
-
     public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName,
                                          String moduleNamespace, EditStrategyType defaultStrategy, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
 
-        InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices, identityMap);
+        InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, identityMap);
         return new ModuleElementResolved(instanceName, ice);
     }
 
index b772eee0d7a9f3b37a5c8854cfe6b9d1650270b2..92b7a487e08cd00397f7cb943055c0e9d2660be4 100644 (file)
@@ -49,10 +49,6 @@ public class ModuleElementDefinition {
         return instanceName;
     }
 
-    public EditStrategyType getEditStrategyType() {
-        return editStrategy;
-    }
-
     public EditConfigStrategy getEditStrategy() {
         switch (editStrategy) {
             case delete :
index 1f63555e83d93b57565ec44027114bd801eea0e1..f86d641112585515198e9cbad18cce3c62a89389 100644 (file)
@@ -7,47 +7,30 @@
  */
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
-import org.opendaylight.yangtools.yang.common.QName;
-
+import java.util.Map;
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+import org.opendaylight.yangtools.yang.common.QName;
 
 public class ServiceRegistryWrapper {
 
     private ServiceReferenceReadableRegistry configServiceRefRegistry;
 
-    private long suffix = 1;
-
     public ServiceRegistryWrapper(ServiceReferenceReadableRegistry configServiceRefRegistry) {
         this.configServiceRefRegistry = configServiceRefRegistry;
     }
 
 
-    public boolean hasRefName(String namespace, String serviceName, ObjectName on) {
-        String qname = configServiceRefRegistry.getServiceInterfaceName(namespace, serviceName);
-        Map<String, ObjectName> forQName = configServiceRefRegistry.getServiceMapping().get(qname);
-        if(forQName==null){
-            return false;
-        }
-        return forQName.values().contains(on);
-    }
-
     public ObjectName getByServiceAndRefName(String namespace, String serviceName, String refName) {
         Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
 
-        Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace);
+        Preconditions.checkNotNull(serviceNameToRefNameToInstance, "No serviceInstances mapped to " + namespace);
 
         Map<String, String> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
-        Preconditions.checkArgument(refNameToInstance != null, "No serviceInstances mapped to " + serviceName + " , "
+        Preconditions.checkNotNull(refNameToInstance, "No serviceInstances mapped to " + serviceName + " , "
                 + serviceNameToRefNameToInstance.keySet());
 
         String instanceId = refNameToInstance.get(refName);
@@ -102,50 +85,4 @@ public class ServiceRegistryWrapper {
 
         return retVal;
     }
-
-    @VisibleForTesting
-    public String getNewDefaultRefName(String namespace, String serviceName, String moduleName, String instanceName) {
-        String refName;
-        refName = "ref_" + instanceName;
-
-        Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
-
-        Map<String, String> refNameToInstance;
-        if(serviceNameToRefNameToInstance == null || !serviceNameToRefNameToInstance.containsKey(serviceName)) {
-            refNameToInstance = Collections.emptyMap();
-        } else {
-            refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
-        }
-
-        final Set<String> refNamesAsSet = toSet(refNameToInstance.keySet());
-        if (refNamesAsSet.contains(refName)) {
-            refName = findAvailableRefName(refName, refNamesAsSet);
-        }
-
-        return refName;
-    }
-
-
-    private Set<String> toSet(Collection<String> values) {
-        Set<String> refNamesAsSet = Sets.newHashSet();
-
-        for (String refName : values) {
-            boolean resultAdd = refNamesAsSet.add(refName);
-            Preconditions.checkState(resultAdd,
-                    "Error occurred building services element, reference name {} was present twice", refName);
-        }
-
-        return refNamesAsSet;
-    }
-
-    private String findAvailableRefName(String refName, Set<String> refNamesAsSet) {
-        String availableRefName = "";
-
-        while (true) {
-            availableRefName = refName + "_" + suffix++;
-            if (!refNamesAsSet.contains(availableRefName)){
-                return availableRefName;
-            }
-        }
-    }
 }
index eb5c018cf3db0af76ced902576543861b732a4f6..559de7a756f51db69d5047c5c1bd0ac6918832ea 100644 (file)
@@ -131,11 +131,15 @@ public final class Services {
         for (String namespace : mappedServices.keySet()) {
 
             for (Entry<String, Map<String, String>> serviceEntry : mappedServices.get(namespace).entrySet()) {
+                // service belongs to config.yang namespace
                 Element serviceElement = XmlUtil.createElement(document, SERVICE_KEY, Optional.<String>absent());
                 root.appendChild(serviceElement);
 
-                Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(XmlNetconfConstants.PREFIX, TYPE_KEY), XmlNetconfConstants.PREFIX,
-                        serviceEntry.getKey(), Optional.of(namespace));
+                // type belongs to config.yang namespace
+                String serviceType = serviceEntry.getKey();
+                Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document, XmlNetconfConstants.TYPE_KEY,
+                        XmlNetconfConstants.PREFIX, namespace, serviceType);
+
                 serviceElement.appendChild(typeElement);
 
                 for (Entry<String, String> instanceEntry : serviceEntry.getValue().entrySet()) {
index 28b14178937aeca68acc76dcebd3370a0f45aaf2..67c178e219709ec0450941a1e189a63a5bdb30d7 100644 (file)
@@ -56,11 +56,4 @@ public final class ModuleRpcs {
         return rpc;
     }
 
-    public Map<String, String> getYangToJavaNames() {
-        return yangToJavaNames;
-    }
-
-    public Map<String, Map<String, InstanceRuntimeRpc>> getRpcMapping() {
-        return rpcMapping;
-    }
 }
index 6a49275f260d7c0d047d3b3642d1886b35458b93..44227bb4d816042c3aae502a52102da49ce2e534 100644 (file)
@@ -80,10 +80,7 @@ public class InstanceRuntime {
                 if (on.getKeyPropertyList().size() != keyListSize + 1){
                     return false;
                 }
-                if (!on.getKeyPropertyList().containsKey(string)){
-                    return false;
-                }
-                return true;
+                return on.getKeyPropertyList().containsKey(string);
             }
         }));
     }
@@ -94,7 +91,7 @@ public class InstanceRuntime {
 
     public Element toXml(ObjectName rootOn, Set<ObjectName> childRbeOns, Document document, String instanceIndex,
                          Element parentElement, String namespace) {
-        Element xml = instanceMapping.toXml(rootOn, null, namespace, document, parentElement);
+        Element xml = instanceMapping.toXml(rootOn, namespace, document, parentElement);
 
         if (instanceIndex != null) {
             xml.setAttribute(KEY_ATTRIBUTE_KEY, instanceIndex);
index 59767fec6e79546595d9a6bf9207e80482b09a94..4d67c75893a59cc9160902b35a9af34309d74936 100644 (file)
@@ -9,27 +9,21 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
 
 import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Set;
+import javax.management.ObjectName;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import java.util.Collection;
-import java.util.Set;
-
 public class ModuleRuntime {
 
     private final InstanceRuntime instanceRuntime;
 
-    public ModuleRuntime(String moduleName, InstanceRuntime instanceRuntime) {
+    public ModuleRuntime(InstanceRuntime instanceRuntime) {
         this.instanceRuntime = instanceRuntime;
     }
 
-    public InstanceRuntime getMbeanMapping() {
-        return instanceRuntime;
-    }
-
     private ObjectName findRoot(Collection<ObjectName> runtimeBeanOns) {
         for (ObjectName objectName : runtimeBeanOns) {
             if (objectName.getKeyPropertyList().size() == 3){
@@ -40,15 +34,16 @@ public class ModuleRuntime {
     }
 
     public Element toXml(String namespace, Collection<ObjectName> runtimeBeanOns,
-                         Document document, ModuleConfig moduleConfig, ObjectName configBeanON, ServiceRegistryWrapper serviceTracker) {
+                         Document document, ModuleConfig moduleConfig, ObjectName configBeanON) {
 
-        Element moduleElement = moduleConfig.toXml(configBeanON, serviceTracker, document, namespace);
+        Element moduleElement = moduleConfig.toXml(configBeanON, document, namespace);
 
         ObjectName rootName = findRoot(runtimeBeanOns);
 
         Set<ObjectName> childrenRuntimeBeans = Sets.newHashSet(runtimeBeanOns);
         childrenRuntimeBeans.remove(rootName);
 
+        // FIXME: why is this called and not used?
         instanceRuntime.toXml(rootName, childrenRuntimeBeans, document, moduleElement, namespace);
 
         return moduleElement;
index 439dea2a80c352252228333cc19b9a66adc7775f..b9518dc4d8825df28b875dbe03ccae8142fd7ca0 100644 (file)
@@ -8,26 +8,22 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
-
 import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-
 public class Runtime {
 
     private final Map<String, Map<String, ModuleRuntime>> moduleRuntimes;
@@ -63,7 +59,7 @@ public class Runtime {
         return retVal;
     }
 
-    public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document, ServiceRegistryWrapper serviceRegistry) {
+    public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document) {
         Element root = XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
 
         Element modulesElement = XmlUtil.createElement(document, XmlNetconfConstants.MODULES_KEY, Optional.of(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
@@ -86,11 +82,11 @@ public class Runtime {
                     Element runtimeXml;
                     ModuleConfig moduleConfig = moduleConfigs.get(localNamespace).get(moduleName);
                     if(instanceToRbe==null || !instanceToRbe.containsKey(instanceName)) {
-                        runtimeXml = moduleConfig.toXml(instanceON, serviceRegistry, document, localNamespace);
+                        runtimeXml = moduleConfig.toXml(instanceON, document, localNamespace);
                     } else {
                         ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName);
                         runtimeXml = moduleRuntime.toXml(localNamespace, instanceToRbe.get(instanceName), document,
-                                moduleConfig, instanceON, serviceRegistry);
+                                moduleConfig, instanceON);
                     }
                     modulesElement.appendChild(runtimeXml);
                 }
index 3ea26055f33c79212debc907caa259109f7101a2..319f539c25f02e9cbddf28b62288b5805fea8fd2 100644 (file)
@@ -13,6 +13,12 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
@@ -21,7 +27,6 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
-import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
@@ -43,13 +48,6 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
 public class EditConfig extends AbstractConfigNetconfOperation {
 
     private static final Logger logger = LoggerFactory.getLogger(EditConfig.class);
@@ -69,7 +67,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
 
     @VisibleForTesting
     Element getResponseInternal(final Document document,
-            final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException, NetconfConfigHandlingException {
+            final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
 
         if (editConfigExecution.shouldTest()) {
             executeTests(getConfigRegistryClient(), editConfigExecution);
@@ -232,11 +230,6 @@ public class EditConfig extends AbstractConfigNetconfOperation {
             return identityNameToSchemaNode.containsKey(idName);
         }
 
-        // FIXME method never used
-        public IdentitySchemaNode getIdentitySchemaNode(String idName) {
-            Preconditions.checkState(identityNameToSchemaNode.containsKey(idName), "No identity under name %s", idName);
-            return identityNameToSchemaNode.get(idName);
-        }
     }
 
     private static Map<String, Map<Date, IdentityMapping>> transformIdentities(Set<Module> modules) {
@@ -280,9 +273,8 @@ public class EditConfig extends AbstractConfigNetconfOperation {
                 String moduleName = moduleNameToMbe.getKey();
                 ModuleMXBeanEntry moduleMXBeanEntry = moduleNameToMbe.getValue();
 
-                ModuleConfig moduleConfig = new ModuleConfig(moduleName, new InstanceConfig(configRegistryClient,
-                        moduleMXBeanEntry.getAttributes()), moduleMXBeanEntry
-                        .getProvidedServices().values());
+                ModuleConfig moduleConfig = new ModuleConfig(moduleName,
+                        new InstanceConfig(configRegistryClient,moduleMXBeanEntry.getAttributes(), moduleMXBeanEntry.getNullableDummyContainerName()));
 
                 Map<String, ModuleConfig> moduleNameToModuleConfig = namespaceToModuleNameToModuleConfig.get(namespace);
                 if(moduleNameToModuleConfig == null) {
@@ -307,7 +299,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
 
         EditConfigXmlParser.EditConfigExecution editConfigExecution;
         Config cfg = getConfigMapping(getConfigRegistryClient(), yangStoreSnapshot);
-        editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, getConfigRegistryClient());
+        editConfigExecution = editConfigXmlParser.fromXml(xml, cfg);
 
         Element responseInternal;
         responseInternal = getResponseInternal(document, editConfigExecution);
index 547ffcda3db0941459d4c2163a7fdc9596bc5bb2..47220f18571a275641a7f0671cfe6da9e0e2ff1d 100644 (file)
@@ -11,8 +11,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.collect.Multimap;
+import java.util.Arrays;
+import java.util.Map;
 import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
-import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementDefinition;
@@ -20,7 +21,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
-import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -28,9 +28,6 @@ import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Arrays;
-import java.util.Map;
-
 public class EditConfigXmlParser {
 
     private static final Logger logger = LoggerFactory.getLogger(EditConfigXmlParser.class);
@@ -45,8 +42,7 @@ public class EditConfigXmlParser {
     public EditConfigXmlParser() {
     }
 
-    EditConfigXmlParser.EditConfigExecution fromXml(final XmlElement xml, final Config cfgMapping,
-                                                    TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient)
+    EditConfigXmlParser.EditConfigExecution fromXml(final XmlElement xml, final Config cfgMapping)
             throws NetconfDocumentedException {
 
         //TODO remove transactionProvider and CfgRegistry from parameters, accept only service ref store
index 6b81603dcd01cdffa0ce3d4b5c9486fc66db2b8d..25d772f4ac565c5ecd4d1e84c1b98d302b810f52 100644 (file)
@@ -8,12 +8,10 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import com.google.common.collect.Multimap;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
-
 import java.util.EnumSet;
 import java.util.Set;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
 
 public enum EditStrategyType {
     // can be default
@@ -58,12 +56,12 @@ public enum EditStrategyType {
         }
 
     }
-    public EditConfigStrategy getFittingStrategy(Multimap<String, String> providedServices) {
+    public EditConfigStrategy getFittingStrategy() {
         switch (this) {
         case merge:
-            return new MergeEditConfigStrategy(providedServices);
+            return new MergeEditConfigStrategy();
         case replace:
-            return new ReplaceEditConfigStrategy(providedServices);
+            return new ReplaceEditConfigStrategy();
         case delete:
             return new DeleteEditConfigStrategy();
         case remove:
index 3e5707cf6ddbc29f842d50fe5cde929458604a91..6ebeeaa07ba86034991ffd584448135bd2ec5b13 100644 (file)
@@ -8,9 +8,10 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.Attribute;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
@@ -19,23 +20,12 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.management.Attribute;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Map;
-import java.util.Map.Entry;
-
 public class MergeEditConfigStrategy extends AbstractEditConfigStrategy {
 
     private static final Logger logger = LoggerFactory.getLogger(MergeEditConfigStrategy.class);
-    private final Multimap<String, String> providedServices;
 
     public MergeEditConfigStrategy() {
-        this.providedServices = HashMultimap.create();
-    }
 
-    public MergeEditConfigStrategy(Multimap<String, String> providedServices) {
-        this.providedServices = providedServices;
     }
 
     @Override
@@ -49,32 +39,8 @@ public class MergeEditConfigStrategy extends AbstractEditConfigStrategy {
                 NetconfDocumentedException.ErrorTag.operation_failed,
                 NetconfDocumentedException.ErrorSeverity.error);
     }
-
-    private void addRefNames(ServiceRegistryWrapper services, Multimap<String, String> providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
-        for (Entry<String, String> namespaceToService : providedServices.entries()) {
-
-            if(services.hasRefName(namespaceToService.getKey(),
-                    namespaceToService.getValue(), on)){
-                continue;
-            }
-
-            String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
-                    ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
-            ta.saveServiceReference(
-                    ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on);
-        }
-    }
-
     @Override
     void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
-        try {
-            addRefNames(services, providedServices, ta, on);
-        } catch (InstanceNotFoundException e) {
-            throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance was not found.",e),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.operation_failed,
-                    NetconfDocumentedException.ErrorSeverity.error);
-        }
 
         for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
             try {
index c431766c4c5a61ebbf53928a529b63ea933d4f2b..c8adb2eae0d5d6472c9956cfc14c26faaa1e3dd3 100644 (file)
@@ -27,9 +27,8 @@ public class MissingInstanceHandlingStrategy extends AbstractEditConfigStrategy
     @Override
     void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
             String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
-        ObjectName on = null;
         try {
-            on = ta.createModule(module, instance);
+            ObjectName on = ta.createModule(module, instance);
             logger.trace("New instance for {} {} created under name {}", module, instance, on);
         } catch (InstanceAlreadyExistsException e1) {
             throw new NetconfConfigHandlingException(String.format("Unable to create instance for %s : %s.", module, instance),
@@ -42,6 +41,5 @@ public class MissingInstanceHandlingStrategy extends AbstractEditConfigStrategy
     @Override
     void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
             ObjectName objectName, ServiceRegistryWrapper services) {
-        return;
     }
 }
index bc3082ff50f51b4365280e6f37861c7c36cdaaf0..ab993c5ffdc4bf4c095d189fc6794c729697823d 100644 (file)
@@ -8,9 +8,10 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.Attribute;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
@@ -19,26 +20,10 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.management.Attribute;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Map;
-import java.util.Map.Entry;
-
 public class ReplaceEditConfigStrategy extends AbstractEditConfigStrategy {
 
     private static final Logger logger = LoggerFactory.getLogger(ReplaceEditConfigStrategy.class);
 
-    private final Multimap<String, String> providedServices;
-
-    public ReplaceEditConfigStrategy() {
-        this.providedServices = HashMultimap.create();
-    }
-
-    public ReplaceEditConfigStrategy(Multimap<String, String> providedServices) {
-        this.providedServices = providedServices;
-    }
-
     @Override
     void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
                                String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
@@ -51,32 +36,8 @@ public class ReplaceEditConfigStrategy extends AbstractEditConfigStrategy {
                 NetconfDocumentedException.ErrorSeverity.error);
     }
 
-    private void addRefNames(ServiceRegistryWrapper services, Multimap<String, String> providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
-        for (Entry<String, String> namespaceToService : providedServices.entries()) {
-
-            if(services.hasRefName(namespaceToService.getKey(),
-                    namespaceToService.getValue(), on)){
-                continue;
-            }
-
-            String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
-                    ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
-            ta.saveServiceReference(
-                    ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on);
-        }
-    }
-
     @Override
     void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
-        try {
-            addRefNames(services, providedServices, ta, on);
-        } catch (InstanceNotFoundException e) {
-            throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance not found. ",on),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.operation_failed,
-                    NetconfDocumentedException.ErrorSeverity.error);
-        }
-
         for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
             try {
                 AttributeConfigElement ace = configAttributeEntry.getValue();
index 4665c2cc89cf23d9f5efbb876b532b377ef22896..48b4bbc2a825e6fd00a3d31575ffac69c0b22630 100644 (file)
@@ -9,14 +9,16 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.get;
 
 import com.google.common.collect.Maps;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
-import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.InstanceRuntime;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.ModuleRuntime;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.Runtime;
@@ -24,7 +26,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.Abs
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
-import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
@@ -35,22 +36,15 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 public class Get extends AbstractConfigNetconfOperation {
 
     private final YangStoreSnapshot yangStoreSnapshot;
     private static final Logger logger = LoggerFactory.getLogger(Get.class);
-    private final TransactionProvider transactionProvider;
 
     public Get(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient,
-               String netconfSessionIdForReporting, TransactionProvider transactionProvider) {
+               String netconfSessionIdForReporting) {
         super(configRegistryClient, netconfSessionIdForReporting);
         this.yangStoreSnapshot = yangStoreSnapshot;
-        this.transactionProvider = transactionProvider;
     }
 
     private Map<String, Map<String, ModuleRuntime>> createModuleRuntimes(ConfigRegistryClient configRegistryClient,
@@ -68,7 +62,7 @@ public class Get extends AbstractConfigNetconfOperation {
                 Map<RuntimeBeanEntry, InstanceConfig> cache = Maps.newHashMap();
                 RuntimeBeanEntry root = null;
                 for (RuntimeBeanEntry rbe : mbe.getRuntimeBeans()) {
-                    cache.put(rbe, new InstanceConfig(configRegistryClient, rbe.getYangPropertiesToTypesMap()));
+                    cache.put(rbe, new InstanceConfig(configRegistryClient, rbe.getYangPropertiesToTypesMap(), mbe.getNullableDummyContainerName()));
                     if (rbe.isRoot()){
                         root = rbe;
                     }
@@ -79,7 +73,7 @@ public class Get extends AbstractConfigNetconfOperation {
                 }
 
                 InstanceRuntime rootInstanceRuntime = createInstanceRuntime(root, cache);
-                ModuleRuntime moduleRuntime = new ModuleRuntime(module, rootInstanceRuntime);
+                ModuleRuntime moduleRuntime = new ModuleRuntime(rootInstanceRuntime);
                 innerMap.put(module, moduleRuntime);
             }
 
@@ -137,9 +131,7 @@ public class Get extends AbstractConfigNetconfOperation {
 
         final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
 
-        ObjectName txOn = transactionProvider.getOrCreateTransaction();
-        ConfigTransactionClient ta = getConfigRegistryClient().getConfigTransactionClient(txOn);
-        final Element element = runtime.toXml(runtimeBeans, configBeans, document, new ServiceRegistryWrapper(ta));
+        final Element element = runtime.toXml(runtimeBeans, configBeans, document);
 
         logger.trace("{} operation successful", XmlNetconfConstants.GET);
 
index 82e07c1e7b29bd5b8eaffafc6e1a53cdeaa82828..03e0176e32892b034b413443d3edf35cca7afb3c 100644 (file)
@@ -76,7 +76,7 @@ public class GetConfig extends AbstractConfigNetconfOperation {
     }
 
     private Element getResponseInternal(final Document document, final ConfigRegistryClient configRegistryClient,
-            final Datastore source) throws NetconfDocumentedException {
+            final Datastore source) {
         Element dataElement = XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
         final Set<ObjectName> instances = Datastore.getInstanceQueryStrategy(source, this.transactionProvider)
                 .queryInstances(configRegistryClient);
index 7790e09ceeb245b926f9c1c4c71fe1f2dde16589..98eb17699973cc1e2448c5072421a0e29b205280 100644 (file)
@@ -56,7 +56,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation {
     }
 
     private Element toXml(Document doc, Object result, AttributeIfc returnType, String namespace, String elementName) throws NetconfDocumentedException {
-        AttributeMappingStrategy<?, ? extends OpenType<?>> mappingStrategy = new ObjectMapper(null).prepareStrategy(returnType);
+        AttributeMappingStrategy<?, ? extends OpenType<?>> mappingStrategy = new ObjectMapper().prepareStrategy(returnType);
         Optional<?> mappedAttributeOpt = mappingStrategy.mapAttribute(result);
         Preconditions.checkState(mappedAttributeOpt.isPresent(), "Unable to map return value %s as %s", result, returnType.getOpenType());
 
index 7f4f8fccb50740c9a9c990e0f942c11b80a5fa64..30873d9534c1b77c0a8b2445a50e6c45dff86758 100644 (file)
@@ -49,7 +49,7 @@ final class NetconfOperationProvider {
         ops.add(new EditConfig(yangStoreSnapshot, transactionProvider, configRegistryClient,
                 netconfSessionIdForReporting));
         ops.add(new Commit(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
-        ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting, transactionProvider));
+        ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
         ops.add(new DiscardChanges(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
         ops.add(new Validate(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
         ops.add(new RuntimeRpc(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
index 1102f342bd054f879c1ce06dc25071f629b506bd..5840c9dbd14d1aa3b3fe050d079e426d8ec21f20 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
 
+import java.lang.ref.SoftReference;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
 
 import javax.annotation.concurrent.GuardedBy;
@@ -15,7 +16,7 @@ import javax.annotation.concurrent.GuardedBy;
 public class YangStoreServiceImpl implements YangStoreService {
     private final SchemaContextProvider service;
     @GuardedBy("this")
-    private YangStoreSnapshotImpl cache = null;
+    private SoftReference<YangStoreSnapshotImpl> cache = new SoftReference<>(null);
 
     public YangStoreServiceImpl(SchemaContextProvider service) {
         this.service = service;
@@ -23,16 +24,18 @@ public class YangStoreServiceImpl implements YangStoreService {
 
     @Override
     public synchronized YangStoreSnapshotImpl getYangStoreSnapshot() throws YangStoreException {
-        if (cache == null) {
-            cache = new YangStoreSnapshotImpl(service.getSchemaContext());
+        YangStoreSnapshotImpl yangStoreSnapshot = cache.get();
+        if (yangStoreSnapshot == null) {
+            yangStoreSnapshot = new YangStoreSnapshotImpl(service.getSchemaContext());
+            cache = new SoftReference<>(yangStoreSnapshot);
         }
-        return cache;
+        return yangStoreSnapshot;
     }
 
     /**
      * Called when schema context changes, invalidates cache.
      */
     public synchronized void refresh() {
-        cache = null;
+        cache.clear();
     }
 }
index 250af688eac0db0a796b2e4dd668f84684949b99..beab62e997457055ce56ddbf646d40292905bf6a 100644 (file)
@@ -156,17 +156,16 @@ public class TransactionProvider implements AutoCloseable {
     }
 
     public void wipeTestTransaction(ObjectName taON) {
-        wipeInternal(taON, true, null);
+        wipeInternal(taON, true);
     }
 
     /**
      * Wiping means removing all module instances keeping the transaction open + service references.
      */
-    synchronized void wipeInternal(ObjectName taON, boolean isTest, String moduleName) {
+    synchronized void wipeInternal(ObjectName taON, boolean isTest) {
         ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON);
 
-        Set<ObjectName> lookupConfigBeans = moduleName == null ? transactionClient.lookupConfigBeans()
-                : transactionClient.lookupConfigBeans(moduleName);
+        Set<ObjectName> lookupConfigBeans = transactionClient.lookupConfigBeans();
         int i = lookupConfigBeans.size();
         for (ObjectName instance : lookupConfigBeans) {
             try {
@@ -190,7 +189,7 @@ public class TransactionProvider implements AutoCloseable {
     public void wipeTransaction() {
         Optional<ObjectName> taON = getTransaction();
         Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
-        wipeInternal(taON.get(), false, null);
+        wipeInternal(taON.get(), false);
     }
 
 }
index 2e8d1f64ab62cded6bde037c0d082e4604c8785a..41301543a33f54754f0ccfc7bda24f2a9b818f74 100644 (file)
@@ -8,11 +8,44 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector;
 
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
+import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
 import org.custommonkey.xmlunit.AbstractNodeTester;
 import org.custommonkey.xmlunit.NodeTest;
 import org.custommonkey.xmlunit.NodeTestException;
@@ -44,6 +77,7 @@ import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFacto
 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.Peers;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit;
@@ -62,7 +96,6 @@ import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 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;
@@ -83,38 +116,6 @@ import org.w3c.dom.Text;
 import org.w3c.dom.traversal.DocumentTraversal;
 import org.xml.sax.SAXException;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
-import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
-
 
 public class NetconfMappingTest extends AbstractConfigTest {
     private static final Logger logger = LoggerFactory.getLogger(NetconfMappingTest.class);
@@ -125,6 +126,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
     private NetconfTestImplModuleFactory factory;
     private DepTestImplModuleFactory factory2;
     private IdentityTestModuleFactory factory3;
+    private TestImplModuleFactory factory4;
 
     @Mock
     YangStoreSnapshot yangStoreSnapshot;
@@ -145,8 +147,9 @@ public class NetconfMappingTest extends AbstractConfigTest {
         this.factory = new NetconfTestImplModuleFactory();
         this.factory2 = new DepTestImplModuleFactory();
         this.factory3 = new IdentityTestModuleFactory();
+        factory4 = new TestImplModuleFactory();
         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, this.factory, this.factory2,
-                this.factory3));
+                this.factory3, factory4));
 
         transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID);
     }
@@ -195,33 +198,33 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         edit("netconfMessages/editConfig.xml");
         Document config = getConfigCandidate();
-        assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+        assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
                 "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
                 "ref_from_code_to_instance-from-code_1"));
 
 
         edit("netconfMessages/editConfig_addServiceName.xml");
         config = getConfigCandidate();
-        assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+        assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
                 "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
                 "ref_from_code_to_instance-from-code_1", "ref_dep_user_another"));
 
         edit("netconfMessages/editConfig_addServiceNameOnTest.xml");
         config = getConfigCandidate();
-        assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+        assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
                 "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
                 "ref_from_code_to_instance-from-code_1", "ref_dep_user_another"));
 
         commit();
         config = getConfigRunning();
         assertCorrectRefNamesForDependencies(config);
-        assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+        assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
                 "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
                 "ref_from_code_to_instance-from-code_1", "ref_dep_user_another"));
 
         edit("netconfMessages/editConfig_replace_default.xml");
         config = getConfigCandidate();
-        assertCorrectServiceNames(config, Sets.newHashSet("ref_dep", "ref_dep2"));
+        assertCorrectServiceNames(config, Collections.<String>emptySet());
 
         edit("netconfMessages/editConfig_remove.xml");
         config = getConfigCandidate();
@@ -260,8 +263,8 @@ public class NetconfMappingTest extends AbstractConfigTest {
         nt.performTest(tester, Node.TEXT_NODE);
     }
 
-    private void assertCorrectServiceNames(Document configCandidate, final Set<String> refNames) throws NodeTestException {
-
+    private void assertCorrectServiceNames(Document configCandidate, Set<String> refNames) throws NodeTestException {
+        final Set<String> refNames2 = new HashSet<>(refNames);
         NodeList servicesNodes = configCandidate.getElementsByTagName("services");
         assertEquals(1, servicesNodes.getLength());
 
@@ -273,9 +276,8 @@ public class NetconfMappingTest extends AbstractConfigTest {
                 if(element.getNodeName() != null) {
                     if(element.getNodeName().equals("name")) {
                         String elmText = element.getTextContent();
-                        if(refNames.contains(elmText)) {
-                            refNames.remove(elmText);
-                            return;
+                        if(refNames2.contains(elmText)) {
+                            refNames2.remove(elmText);
                         } else {
                             throw new NodeTestException("Unexpected services defined: " + elmText);
                         }
@@ -285,7 +287,8 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
             @Override
             public void noMoreNodes(NodeTest forTest) throws NodeTestException {
-                assertTrue(refNames.isEmpty());
+                assertEquals(Collections.<String>emptySet(), refNames2);
+                assertTrue(refNames2.toString(), refNames2.isEmpty());
             }
         };
         nt.performTest(tester, Node.ELEMENT_NODE);
@@ -424,42 +427,42 @@ public class NetconfMappingTest extends AbstractConfigTest {
         assertEquals(2, afterReplace);
     }
 
-    @Test(expected = NetconfDocumentedException.class)
+    @Test
     public void testSameAttrDifferentNamespaces() throws Exception {
         try {
             edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml");
+            fail();
         } catch (NetconfDocumentedException e) {
             String message = e.getMessage();
-            assertContainsString(message, "Element simple-long-2 present multiple times with different namespaces");
+            assertContainsString(message, "Element simpleInt present multiple times with different namespaces");
             assertContainsString(message, TEST_NAMESPACE);
             assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
-            throw e;
         }
     }
 
-    @Test(expected = NetconfDocumentedException.class)
+    @Test
     public void testDifferentNamespaceInTO() throws Exception {
         try {
             edit("netconfMessages/namespaces/editConfig_differentNamespaceTO.xml");
+            fail();
         } catch (NetconfDocumentedException e) {
             String message = e.getMessage();
             assertContainsString(message, "Unrecognised elements");
             assertContainsString(message, "simple-int2");
             assertContainsString(message, "dto_d");
-            throw e;
         }
     }
 
-    @Test(expected = NetconfDocumentedException.class)
+    @Test
     public void testSameAttrDifferentNamespacesList() throws Exception {
         try {
             edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml");
+            fail();
         } catch (NetconfDocumentedException e) {
             String message = e.getMessage();
-            assertContainsString(message, "Element binaryLeaf present multiple times with different namespaces");
+            assertContainsString(message, "Element allow-user present multiple times with different namespaces");
             assertContainsString(message, TEST_NAMESPACE);
             assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
-            throw e;
         }
     }
 
@@ -492,6 +495,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         for (int i = 0; i < TESTS_COUNT; i++) {
             String file = String.format(format, i + 1);
+            logger.info("Reading {}", file);
             try {
                 edit(file);
             } catch (NetconfDocumentedException e) {
@@ -565,23 +569,13 @@ public class NetconfMappingTest extends AbstractConfigTest {
         assertThat(string, JUnitMatchers.containsString(substring));
     }
 
-    private void checkEnum(final Document response) throws NetconfDocumentedException {
-        XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data")
-                .getOnlyChildElement("modules");
+    private void checkEnum(final Document response) throws Exception {
 
-        String enumName = "extended-enum";
-        String enumContent = "TWO";
+        String expectedEnumContent = "TWO";
 
-        for (XmlElement moduleElement : modulesElement.getChildElements("module")) {
-            String name = moduleElement.getOnlyChildElement("prefix:name").getTextContent();
-            if(name.equals(INSTANCE_NAME)) {
-                XmlElement enumAttr = moduleElement.getOnlyChildElement(enumName);
-                assertEquals(enumContent, enumAttr.getTextContent());
-                return;
-            }
-        }
-
-        fail("Enum attribute " + enumName + ":" + enumContent + " not present in " + XmlUtil.toString(response));
+        XMLAssert.assertXpathEvaluatesTo(expectedEnumContent,
+                getXpathForNetconfImplSubnode(INSTANCE_NAME,"extended-enum"),
+                response);
     }
 
     private void checkTestingDeps(Document response) {
@@ -589,24 +583,23 @@ public class NetconfMappingTest extends AbstractConfigTest {
         assertEquals(2, testingDepsSize);
     }
 
-    private void checkTypeConfigAttribute(Document response) throws NetconfDocumentedException {
-
-        XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data")
-                .getOnlyChildElement("modules");
-
-        List<String> expectedValues = Lists.newArrayList("default-string", "configAttributeType");
-        Set<String> configAttributeType = Sets.newHashSet();
+    private String getXpathForNetconfImplSubnode(String instanceName, String subnode) {
+        return "/urn:ietf:params:xml:ns:netconf:base:1.0:rpc-reply" +
+                "/urn:ietf:params:xml:ns:netconf:base:1.0:data" +
+                "/urn:opendaylight:params:xml:ns:yang:controller:config:modules" +
+                "/module[name='"+instanceName+"']" +
+                "/urn:opendaylight:params:xml:ns:yang:controller:test:impl:impl-netconf" +
+                "/urn:opendaylight:params:xml:ns:yang:controller:test:impl:"+subnode;
+    }
 
-        for (XmlElement moduleElement : modulesElement.getChildElements("module")) {
-            for (XmlElement type : moduleElement.getChildElements("type")) {
-                if (type.getNamespace() != null) {
-                    configAttributeType.add(type.getTextContent());
-                }
-            }
-        }
+    private void checkTypeConfigAttribute(Document response) throws Exception {
 
-        for (String expectedValue : expectedValues) {
-            assertTrue(configAttributeType.contains(expectedValue));
+        Map<String,String> namesToTypeValues = ImmutableMap.of("instance-from-code", "configAttributeType",
+                "test2", "default-string");
+        for (Entry<String, String> nameToExpectedValue : namesToTypeValues.entrySet()) {
+            XMLAssert.assertXpathEvaluatesTo(nameToExpectedValue.getValue(),
+                    getXpathForNetconfImplSubnode(nameToExpectedValue.getKey(),"type"),
+                    response);
         }
     }
 
@@ -689,7 +682,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
     }
 
     private Document get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
-        Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID, transactionProvider);
+        Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID);
         return executeOp(getOp, "netconfMessages/get.xml");
     }
 
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 57bd3dd6209d3248dc7c7b969ccaf6f5a33fbbf7..1ecbc55b2a02ac7af0757e777d960956cfddc0a0 100644 (file)
@@ -62,6 +62,14 @@ public class NetconfDocumentedException extends Exception {
     private final ErrorSeverity errorSeverity;
     private final Map<String, String> errorInfo;
 
+    public NetconfDocumentedException(String message) {
+        this(message,
+                NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.invalid_value,
+                NetconfDocumentedException.ErrorSeverity.error
+        );
+    }
+
     public NetconfDocumentedException(final String message, final ErrorType errorType, final ErrorTag errorTag,
             final ErrorSeverity errorSeverity) {
         this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
similarity index 86%
rename from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfExiSession.java
rename to opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfExiSession.java
index 2a20ba2f6168611adee52e7461fcb7ccd32c43ff..66510b42d15cee5b1ea9ca13a546de49323e6147 100644 (file)
@@ -5,9 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util;
-
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+package org.opendaylight.controller.netconf.api;
 
 /**
  * Session capable of exi communication according to http://tools.ietf.org/html/draft-varga-netconf-exi-capability-02
index ce77fdc08ed801219fb58f72b6d356c32ae77449..f46d14903323ff8f891da7ff025d5e50cc926c1b 100644 (file)
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-netty-util</artifactId>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-util</artifactId>
@@ -54,8 +58,8 @@
                             javax.xml.parsers,
                             javax.xml.xpath,
                             org.opendaylight.controller.netconf.api,
-                            org.opendaylight.controller.netconf.util,
                             org.opendaylight.controller.netconf.util.*,
+                            org.opendaylight.controller.netconf.nettyutil.*,
                             org.opendaylight.protocol.framework,
                             org.openexi.*,
                             org.slf4j,
index f4efb1fc7dc9bf56cd3176c769f72c312ee351d2..eaa3589e66d32c6e448c12ee6b04e60ca457dfdd 100644 (file)
@@ -8,19 +8,17 @@
 
 package org.opendaylight.controller.netconf.client;
 
+import io.netty.channel.Channel;
 import java.util.Collection;
-
-import org.opendaylight.controller.netconf.util.AbstractNetconfSession;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXIToMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToEXIEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSession;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.netty.channel.Channel;
-
 public final class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
index 4e2393171afd2090a103dbdb110ed4aea71f9dca..bb6ea61a25b5fa51e56af04af1b01f533205df18 100644 (file)
@@ -8,22 +8,24 @@
 
 package org.opendaylight.controller.netconf.client;
 
+import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
 import java.util.Collection;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpression;
-
 import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -33,10 +35,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
-
 public class NetconfClientSessionNegotiator extends
         AbstractNetconfSessionNegotiator<NetconfClientSessionPreferences, NetconfClientSession, NetconfClientSessionListener>
 {
index e65adc3fdf5b736522592a55e5c81d8fa8f37451..4c993acf58f3e8640d3aea09468ea0283134a903 100644 (file)
@@ -17,9 +17,9 @@ import io.netty.util.concurrent.Promise;
 import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.opendaylight.protocol.framework.SessionNegotiator;
index b86349ddea777fcea7f6533575dc259539d26fbe..799674487f4de5d936067b51b3f9ae392caee897 100644 (file)
@@ -9,13 +9,12 @@ package org.opendaylight.controller.netconf.client;
 
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.Promise;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
-import org.opendaylight.controller.netconf.util.handler.ssh.SshHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker;
-import org.opendaylight.protocol.framework.SessionListenerFactory;
-
 import java.io.IOException;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.Invoker;
+import org.opendaylight.protocol.framework.SessionListenerFactory;
 
 final class SshClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
 
index 967d3c6dfb94dfffac82bb1bceab390a6c2929b9..4a0a089fae97e1ff3d1c8b969f6da077e3584cb7 100644 (file)
@@ -9,7 +9,7 @@ package org.opendaylight.controller.netconf.client;
 
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.Promise;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 
 class TcpClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
index 5a3ec3a23e5c5f2bf2e2d149896f7cdf48a228de..37dae69f3556bbbd8c64936b127d0bce369d3023 100644 (file)
@@ -10,13 +10,12 @@ package org.opendaylight.controller.netconf.client.conf;
 import com.google.common.base.Objects;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
 import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 
-import java.net.InetSocketAddress;
-
 public class NetconfClientConfiguration {
 
     private final NetconfClientProtocol clientProtocol;
index a3e57bd9d30a02c5cfe88005762b3ee171ecc47e..b477beea66183d424e8b080f38c5a3b6e2d390e6 100644 (file)
@@ -7,13 +7,12 @@
  */
 package org.opendaylight.controller.netconf.client.conf;
 
+import java.net.InetSocketAddress;
 import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 
-import java.net.InetSocketAddress;
-
 public class NetconfClientConfigurationBuilder {
 
     public static final int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 5000;
index 64fcc48b251b29efcff9fb415cc73a86eee05d34..f618ea5ab9e309ab1e6795722705a55b3d7e61ee 100644 (file)
@@ -9,14 +9,13 @@ package org.opendaylight.controller.netconf.client.conf;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
 import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 
-import java.net.InetSocketAddress;
-
 public final class NetconfReconnectingClientConfiguration extends NetconfClientConfiguration {
 
     private final ReconnectStrategyFactory connectStrategyFactory;
index 411ac3c23dafd16870c649475b9bf03bcada4cf6..f0f972b945c837bdd2c1e5c8b86e50424770e5f3 100644 (file)
@@ -8,9 +8,8 @@
 package org.opendaylight.controller.netconf.client.conf;
 
 import java.net.InetSocketAddress;
-
 import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
index c62a85aae68d796030d27e954f901c029eb1b1e2..1d94517152f45215cc7481a963a290a2870640d2 100644 (file)
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-mapping-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-netty-util</artifactId>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-util</artifactId>
                             org.opendaylight.controller.netconf.api,
                             org.opendaylight.controller.netconf.api.jmx,
                             org.opendaylight.controller.netconf.mapping.api,
-                            org.opendaylight.controller.netconf.util,
-                            org.opendaylight.controller.netconf.util.mapping,
-                            org.opendaylight.controller.netconf.util.osgi,
-                            org.opendaylight.controller.netconf.util.xml,
-                            org.opendaylight.controller.netconf.util.exception,
-                            org.opendaylight.controller.netconf.util.handler,
+                            org.opendaylight.controller.netconf.util.*,
                             org.opendaylight.protocol.framework,
                             org.osgi.framework,
                             org.osgi.util.tracker,
                             org.slf4j,
                             org.w3c.dom,
                             org.xml.sax,
-                            org.opendaylight.controller.netconf.util.messages,
                             io.netty.util.internal,
                             org.opendaylight.controller.netconf.api.monitoring,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
                             org.opendaylight.yangtools.yang.binding,
-                            org.openexi.*,</Import-Package>
+                            org.openexi.*,
+                            org.opendaylight.controller.netconf.nettyutil.*</Import-Package>
           </instructions>
         </configuration>
       </plugin>
index 130818b12a7d6e040ff863b1026e9e9101d81385..de3dee14437b804fd18819bb20302a962fd213e2 100644 (file)
@@ -12,12 +12,11 @@ import io.netty.channel.ChannelFuture;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.Promise;
+import java.net.InetSocketAddress;
 import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
 import org.opendaylight.protocol.framework.AbstractDispatcher;
 
-import java.net.InetSocketAddress;
-
 public class NetconfServerDispatcher extends AbstractDispatcher<NetconfServerSession, NetconfServerSessionListener> {
 
     private final ServerChannelInitializer initializer;
index 280375d918fc487f98b29777a276fbdef9123cec..7d409092b9178bcd2816c96371108930f200fe3a 100644 (file)
@@ -8,18 +8,19 @@
 
 package org.opendaylight.controller.netconf.impl;
 
+import com.google.common.base.Preconditions;
+import io.netty.channel.Channel;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
 import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSession;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXIToMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToEXIEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSession;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
@@ -36,9 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-import io.netty.channel.Channel;
-
 public final class NetconfServerSession extends AbstractNetconfSession<NetconfServerSession, NetconfServerSessionListener> implements NetconfManagementSession {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfServerSession.class);
index 6528fe251775694e8ea47cf59b094d0efcc07ddf..a48cbbe24106411451cc4726d6e3ca153f3166cb 100644 (file)
@@ -8,22 +8,19 @@
 
 package org.opendaylight.controller.netconf.impl;
 
+import com.google.common.base.Optional;
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
 import java.net.InetSocketAddress;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSessionNegotiator;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
-
 public class NetconfServerSessionNegotiator extends
         AbstractNetconfSessionNegotiator<NetconfServerSessionPreferences, NetconfServerSession, NetconfServerSessionListener> {
 
index 303047df12b6fae6c77e964b702cb23a9ed52b59..7130dc350134578372348ce829bda08243a5303c 100644 (file)
@@ -7,8 +7,12 @@
  */
 package org.opendaylight.controller.netconf.impl.osgi;
 
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.TimeUnit;
+
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
@@ -22,11 +26,8 @@ import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.concurrent.TimeUnit;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
 
 public class NetconfImplActivator implements BundleActivator {
 
@@ -39,17 +40,16 @@ public class NetconfImplActivator implements BundleActivator {
     private ServiceRegistration<NetconfMonitoringService> regMonitoring;
 
     @Override
-    public void start(final BundleContext context)  {
-        InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
-                "TCP is not configured, netconf not available.", false);
-
-        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+    public void start(final BundleContext context) {
+        final InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfServerAddress(context,
+                NetconfConfigUtil.DEFAULT_NETCONF_TCP_ADDRESS);
+        final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
         startOperationServiceFactoryTracker(context, factoriesListener);
 
-        SessionIdProvider idProvider = new SessionIdProvider();
+        final SessionIdProvider idProvider = new SessionIdProvider();
         timer = new HashedWheelTimer();
-        long connectionTimeoutMillis = NetconfConfigUtil.extractTimeoutMillis(context);
 
+        long connectionTimeoutMillis = NetconfConfigUtil.extractTimeoutMillis(context);
 
         commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
 
@@ -62,23 +62,24 @@ public class NetconfImplActivator implements BundleActivator {
 
         NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
                 serverNegotiatorFactory);
-        NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup);
+
+        NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup,
+                eventLoopGroup);
 
         logger.info("Starting TCP netconf server at {}", address);
         dispatch.createServer(address);
 
         context.registerService(NetconfOperationProvider.class, factoriesListener, null);
-
     }
 
-    private void startOperationServiceFactoryTracker(BundleContext context, NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+    private void startOperationServiceFactoryTracker(final BundleContext context, final NetconfOperationServiceFactoryListenerImpl factoriesListener) {
         factoriesTracker = new NetconfOperationServiceFactoryTracker(context, factoriesListener);
         factoriesTracker.open();
     }
 
-    private NetconfMonitoringServiceImpl startMonitoringService(BundleContext context, NetconfOperationServiceFactoryListenerImpl factoriesListener) {
-        NetconfMonitoringServiceImpl netconfMonitoringServiceImpl = new NetconfMonitoringServiceImpl(factoriesListener);
-        Dictionary<String, ?> dic = new Hashtable<>();
+    private NetconfMonitoringServiceImpl startMonitoringService(final BundleContext context, final NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+        final NetconfMonitoringServiceImpl netconfMonitoringServiceImpl = new NetconfMonitoringServiceImpl(factoriesListener);
+        final Dictionary<String, ?> dic = new Hashtable<>();
         regMonitoring = context.registerService(NetconfMonitoringService.class, netconfMonitoringServiceImpl, dic);
 
         return netconfMonitoringServiceImpl;
index b8622d1e911c54e225fb02bc032c5a9f9fae702a..ea2bb9c34e4801f5c66b33ef108110602ba5c60b 100644 (file)
@@ -15,6 +15,14 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.GlobalEventExecutor;
 import java.io.DataOutputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -32,7 +40,6 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicLong;
-
 import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -57,9 +64,9 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -68,16 +75,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.concurrent.GlobalEventExecutor;
-
 @RunWith(Parameterized.class)
 public class ConcurrentClientsTest {
     private static final Logger logger = LoggerFactory.getLogger(ConcurrentClientsTest.class);
index e13415b64b71ad31aa6e2e846adbb360f3740183..abf2ad862f779cb5651f200fb484138482bbb5c0 100644 (file)
@@ -14,21 +14,20 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.embedded.EmbeddedChannel;
-
 import java.util.Queue;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.handler.ChunkedFramingMechanismEncoder;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.ChunkedFramingMechanismEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEOMAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
index 66106075d320b14269ebb0a05ffde05df42ce740..c40dfe7fc32208c73251c9a483d7f5feaed48eaf 100644 (file)
   </properties>
 
   <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-netty-util</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>commons.logback_settings</artifactId>
       <artifactId>netconf-monitoring</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-netty-util</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-ssh</artifactId>
index 29afa93d373cb5e7a7b86c57b0f93b6cceeeb48e..148b0446e309f4470f55ee0205e7be6cd429499d 100644 (file)
@@ -144,12 +144,12 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
 
         notificationVerifier.assertNotificationCount(2);
         notificationVerifier.assertNotificationContent(0, 0, 0, 9);
-        notificationVerifier.assertNotificationContent(1, 4, 4, 9);
+        notificationVerifier.assertNotificationContent(1, 4, 3, 9);
 
         mockedAggregator.assertSnapshotCount(2);
         // Capabilities are stripped for persister
         mockedAggregator.assertSnapshotContent(0, 0, 0, 1);
-        mockedAggregator.assertSnapshotContent(1, 4, 4, 3);
+        mockedAggregator.assertSnapshotContent(1, 4, 3, 3);
     }
 
     private VerifyingPersister mockAggregator() throws IOException {
index 4dc4b707d4708253579e8135ddd1b6c1e95af1c9..140284e4ee1946ab2cc579fba0cf08362440e580 100644 (file)
@@ -14,6 +14,9 @@ import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
+import ch.ethz.ssh2.Connection;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.GlobalEventExecutor;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -22,9 +25,7 @@ import java.net.InetSocketAddress;
 import java.nio.file.Files;
 import java.util.Collection;
 import java.util.List;
-
 import junit.framework.Assert;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -44,10 +45,10 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -55,10 +56,6 @@ import org.opendaylight.controller.sal.authorization.AuthResultEnum;
 import org.opendaylight.controller.usermanager.IUserManager;
 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
 
-import ch.ethz.ssh2.Connection;
-import io.netty.channel.ChannelFuture;
-import io.netty.util.concurrent.GlobalEventExecutor;
-
 public class NetconfITSecureTest extends AbstractNetconfConfigTest {
 
     private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
index cd53995bce8a54c2bf12e2419ceab87300204edb..fd43f67c056407c15dc0692d938b4fad7c30586b 100644 (file)
@@ -386,10 +386,10 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
 
             NetconfMessage response = netconfClient.sendMessage(getConfig);
 
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:afi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:afi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:safi>"));
-            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:safi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</afi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</afi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</safi>"));
+            assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</safi>"));
 
         } catch (Exception e) {
             fail(Throwables.getStackTraceAsString(e));
diff --git a/opendaylight/netconf/netconf-netty-util/pom.xml b/opendaylight/netconf/netconf-netty-util/pom.xml
new file mode 100644 (file)
index 0000000..1304159
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>netconf-subsystem</artifactId>
+    <version>0.2.5-SNAPSHOT</version>
+  </parent>
+  <artifactId>netconf-netty-util</artifactId>
+  <packaging>bundle</packaging>
+  <name>${project.artifactId}</name>
+
+  <dependencies>
+    <!-- compile dependencies -->
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-mapping-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-util</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-handler</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>protocol-framework</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>ganymed</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.openexi</groupId>
+      <artifactId>nagasena</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.openexi</groupId>
+      <artifactId>nagasena-rta</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>xmlunit</groupId>
+      <artifactId>xmlunit</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Import-Package>ch.ethz.ssh2, com.google.common.base, com.google.common.collect, io.netty.buffer,
+              io.netty.channel, io.netty.channel.socket, io.netty.handler.codec, io.netty.handler.ssl, io.netty.util,
+              io.netty.util.concurrent, javax.xml.transform, javax.xml.transform.dom, javax.xml.transform.sax,
+              javax.xml.transform.stream, org.opendaylight.controller.netconf.api,
+              org.opendaylight.controller.netconf.util.messages, org.opendaylight.controller.netconf.util.xml,
+              org.opendaylight.protocol.framework, org.openexi.proc, org.openexi.proc.common, org.openexi.proc.grammars,
+              org.openexi.sax, org.openexi.schema, org.slf4j, org.w3c.dom, org.xml.sax</Import-Package>
+            <Export-Package>org.opendaylight.controller.netconf.nettyutil,
+              org.opendaylight.controller.netconf.nettyutil.handler,
+              org.opendaylight.controller.netconf.nettyutil.handler.exi,
+              org.opendaylight.controller.netconf.nettyutil.handler.ssh,
+              org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication,
+              org.opendaylight.controller.netconf.nettyutil.handler.ssh.client</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.4</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+            <phase>package</phase>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
@@ -6,16 +6,15 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.netconf.util;
+package org.opendaylight.controller.netconf.nettyutil;
 
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.Promise;
-
 import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfHelloMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEOMAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfHelloMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
 
 public abstract class AbstractChannelInitializer<S extends NetconfSession> {
@@ -5,16 +5,19 @@
  * 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.util;
+package org.opendaylight.controller.netconf.nettyutil;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
 import java.io.IOException;
-
+import org.opendaylight.controller.netconf.api.NetconfExiSession;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfSessionListener;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.xml.EXIParameters;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.EXIParameters;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.AbstractProtocolSession;
@@ -22,10 +25,6 @@ import org.openexi.proc.common.EXIOptionsException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandler;
-
 public abstract class AbstractNetconfSession<S extends NetconfSession, L extends NetconfSessionListener<S>> extends AbstractProtocolSession<NetconfMessage> implements NetconfSession, NetconfExiSession {
     private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSession.class);
     private final L sessionListener;
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.netconf.util;
+package org.opendaylight.controller.netconf.nettyutil;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -21,15 +21,16 @@ import io.netty.util.TimerTask;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GenericFutureListener;
 import io.netty.util.concurrent.Promise;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfSessionListener;
 import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -39,8 +40,6 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
 
-import java.util.concurrent.TimeUnit;
-
 public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionPreferences, S extends AbstractNetconfSession<S, L>, L extends NetconfSessionListener<S>>
 extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
 
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import java.io.InputStream;
 import java.util.List;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import com.google.common.base.Preconditions;
 import io.netty.buffer.ByteBuf;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufOutputStream;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
@@ -5,9 +5,10 @@
  * 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.util.xml;
+package org.opendaylight.controller.netconf.nettyutil.handler.exi;
 
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.openexi.proc.common.AlignmentType;
 import org.openexi.proc.common.EXIOptions;
 import org.openexi.proc.common.EXIOptionsException;
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.netconf.util.handler.ssh;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelFuture;
@@ -18,15 +18,15 @@ import io.netty.channel.ChannelPromise;
 import java.io.IOException;
 import java.net.SocketAddress;
 
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClient;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClient;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.Invoker;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
 
 /**
  * Netty SSH handler class. Acts as interface between Netty and SSH library. All standard Netty message handling
- * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter};
+ * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter};
  */
 public class SshHandler extends ChannelOutboundHandlerAdapter {
     private static final String SOCKET = "socket";
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.netconf.util.handler.ssh.authentication;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
 
 import ch.ethz.ssh2.Connection;
 
@@ -14,7 +14,7 @@ import java.io.IOException;
 
 /**
  * Class Providing username/password authentication option to
- * {@link org.opendaylight.controller.netconf.util.handler.ssh.SshHandler}
+ * {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.SshHandler}
  */
 public class LoginPassword extends AuthenticationHandler {
     private final String username;
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
 
 import java.io.IOException;
 
@@ -6,13 +6,13 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
 
 import ch.ethz.ssh2.Connection;
 import ch.ethz.ssh2.Session;
 import ch.ethz.ssh2.channel.Channel;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
 
 import java.io.IOException;
 import java.util.HashMap;
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
@@ -19,7 +19,7 @@ import java.io.OutputStream;
 import java.util.LinkedList;
 import java.util.Queue;
 import java.util.concurrent.atomic.AtomicBoolean;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocketException;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocketException;
 
 
 /**
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import com.google.common.base.Charsets;
 import com.google.common.collect.Lists;
@@ -5,19 +5,16 @@
  * 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.util.messages;
+package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import static org.junit.Assert.assertEquals;
-import io.netty.buffer.Unpooled;
 
+import com.google.common.io.Files;
+import io.netty.buffer.Unpooled;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
-
 import org.junit.Test;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-
-import com.google.common.io.Files;
 
 public class NetconfMessageFactoryTest {
     @Test
index ff950e95e9700289bf9dda3bed79642f1fba096e..c6974d4982db051f1cb6a66d3f67394ee2d57817 100644 (file)
@@ -27,7 +27,7 @@ public final class NetconfSSHServer implements Runnable {
     private static final AtomicLong sesssionId = new AtomicLong();
     private final InetSocketAddress clientAddress;
     private final AuthProvider authProvider;
-    private boolean up = false;
+    private volatile boolean up = false;
 
     private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws IllegalStateException, IOException {
 
@@ -68,9 +68,17 @@ public final class NetconfSSHServer implements Runnable {
         while (up) {
             logger.trace("Starting new socket thread.");
             try {
-               SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(), authProvider);
-            } catch (IOException e) {
-                logger.error("Exception occurred during socket thread initialization {}", e);
+                SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(), authProvider);
+            }
+            catch (IOException e) {
+                if( up ) {
+                    logger.error("Exception occurred during socket thread initialization", e);
+                }
+                else {
+                    // We're shutting down so an exception is expected as the socket's been closed.
+                    // Log to debug.
+                    logger.debug("Shutting down - got expected exception: " + e);
+                }
             }
         }
     }
index 73886c4f461eb3ecd60710da40cf6fc3ff361e54..348fe006f3a7d4cfefcb8c502a9115da422a0a61 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.netconf.ssh.authentication;
 
+import java.security.NoSuchAlgorithmException;
 import org.apache.commons.io.FileUtils;
 import org.bouncycastle.openssl.PEMWriter;
 import org.slf4j.Logger;
@@ -25,7 +26,7 @@ public class PEMGenerator {
     private static final Logger logger = LoggerFactory.getLogger(PEMGenerator.class);
     private static final int KEY_SIZE = 4096;
 
-    public static String generateTo(File privateFile) throws Exception {
+    public static String generateTo(File privateFile) throws IOException, NoSuchAlgorithmException {
         KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
         SecureRandom sr = new SecureRandom();
         keyGen.initialize(KEY_SIZE, sr);
index ca0c9454d4a5c8934a96da245b41029198e464d6..d74308cfadbae8e658e58f9b189d93baaea83c2e 100644 (file)
@@ -7,22 +7,19 @@
  */
 package org.opendaylight.controller.netconf.ssh.osgi;
 
-import com.google.common.base.Optional;
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.List;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
-import org.opendaylight.controller.sal.authorization.UserLevel;
 import org.opendaylight.controller.usermanager.IUserManager;
-import org.opendaylight.controller.usermanager.UserConfig;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -30,7 +27,6 @@ import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Activator for netconf SSH bundle which creates SSH bridge between netconf client and netconf server. Activator
@@ -46,31 +42,28 @@ public class NetconfSSHActivator implements BundleActivator{
 
     private NetconfSSHServer server;
     private static final Logger logger =  LoggerFactory.getLogger(NetconfSSHActivator.class);
-    private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
     private IUserManager iUserManager;
     private BundleContext context = null;
-    private Optional<String> defaultPassword;
-    private Optional<String> defaultUser;
 
     private ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
         @Override
-        public IUserManager addingService(ServiceReference<IUserManager> reference) {
+        public IUserManager addingService(final ServiceReference<IUserManager> reference) {
             logger.trace("Service {} added, let there be SSH bridge.", reference);
             iUserManager =  context.getService(reference);
             try {
                 onUserManagerFound(iUserManager);
-            } catch (Exception e) {
+            } catch (final Exception e) {
                 logger.trace("Can't start SSH server due to {}",e);
             }
             return iUserManager;
         }
         @Override
-        public void modifiedService(ServiceReference<IUserManager> reference, IUserManager service) {
+        public void modifiedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
             logger.trace("Replacing modified service {} in netconf SSH.", reference);
             server.addUserManagerService(service);
         }
         @Override
-        public void removedService(ServiceReference<IUserManager> reference, IUserManager service) {
+        public void removedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
             logger.trace("Removing service {} from netconf SSH. " +
                     "SSH won't authenticate users until IUserManager service will be started.", reference);
             removeUserManagerService();
@@ -79,80 +72,61 @@ public class NetconfSSHActivator implements BundleActivator{
 
 
     @Override
-    public void start(BundleContext context)  {
+    public void start(final BundleContext context) {
         this.context = context;
         listenForManagerService();
     }
 
     @Override
     public void stop(BundleContext context) throws IOException {
-        if (this.defaultUser.isPresent()){
-            this.iUserManager.removeLocalUser(this.defaultUser.get());
-        }
         if (server != null){
             server.stop();
             logger.trace("Netconf SSH bridge is down ...");
         }
     }
-    private void startSSHServer() throws IllegalStateException, IOException {
+    private void startSSHServer() throws IOException {
         checkNotNull(this.iUserManager, "No user manager service available.");
         logger.trace("Starting netconf SSH  bridge.");
-        Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
-        InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
-                EXCEPTION_MESSAGE, true);
+        final InetSocketAddress sshSocketAddress = NetconfConfigUtil.extractSSHNetconfAddress(context,
+                NetconfConfigUtil.DEFAULT_NETCONF_SSH_ADDRESS);
+        final InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfClientAddress(context,
+               NetconfConfigUtil.DEFAULT_NETCONF_TCP_ADDRESS);
 
-        if (sshSocketAddressOptional.isPresent()){
-            String path =  FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(context));
-            if (path.equals("")){
-                throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
-            }
+        String path =  FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(context));
 
-            File privateKeyFile = new File(path);
-            String privateKeyPEMString = null;
-            if (privateKeyFile.exists() == false) {
-                try {
-                    privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
-                } catch (Exception e) {
-                    logger.error("Exception occurred while generating PEM string {}",e);
-                }
-            } else {
-                // read from file
-                try (FileInputStream fis = new FileInputStream(path)) {
-                    privateKeyPEMString = IOUtils.toString(fis);
-                } catch (IOException e) {
-                    logger.error("Error reading RSA key from file '{}'", path);
-                    throw new IllegalStateException("Error reading RSA key from file " + path);
-                }
-            }
-            AuthProvider authProvider = null;
+        if (path.isEmpty()) {
+            throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
+        }
+
+        final File privateKeyFile = new File(path);
+        final String privateKeyPEMString;
+        if (privateKeyFile.exists() == false) {
+            // generate & save to file
             try {
-                this.defaultPassword = NetconfConfigUtil.getSSHDefaultPassword(context);
-                this.defaultUser = NetconfConfigUtil.getSSHDefaultUser(context);
-                // Since there is no user data store yet (ldap, ...) this adds default user/password to UserManager
-                // if these parameters are set in netconf configuration file.
-                if (defaultUser.isPresent() &&
-                        defaultPassword.isPresent()){
-                    logger.trace(String.format("Default username and password for netconf ssh bridge found. Adding user %s to user manager.",defaultUser.get()));
-                    List<String> roles = new ArrayList<String>(1);
-                    roles.add(UserLevel.SYSTEMADMIN.toString());
-                    iUserManager.addLocalUser(new UserConfig(defaultUser.get(), defaultPassword.get(), roles));
-                }
-                authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+                privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
             } catch (Exception e) {
-                logger.error("Error instantiating AuthProvider {}",e);
+                logger.error("Exception occurred while generating PEM string {}", e);
+                throw new IllegalStateException("Error generating RSA key from file " + path);
             }
-            this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
-
-            Thread serverThread = new  Thread(server,"netconf SSH server thread");
-            serverThread.setDaemon(true);
-            serverThread.start();
-            logger.trace("Netconf SSH  bridge up and running.");
         } else {
-            logger.trace("No valid connection configuration for SSH bridge found.");
-            throw new IllegalStateException("No valid connection configuration for SSH bridge found.");
+            // read from file
+            try (FileInputStream fis = new FileInputStream(path)) {
+                privateKeyPEMString = IOUtils.toString(fis);
+            } catch (final IOException e) {
+                logger.error("Error reading RSA key from file '{}'", path);
+                throw new IOException("Error reading RSA key from file " + path, e);
+            }
         }
+        final AuthProvider authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+        this.server = NetconfSSHServer.start(sshSocketAddress.getPort(), tcpSocketAddress, authProvider);
+
+        final Thread serverThread = new Thread(server, "netconf SSH server thread");
+        serverThread.setDaemon(true);
+        serverThread.start();
+        logger.trace("Netconf SSH  bridge up and running.");
     }
-    private void onUserManagerFound(IUserManager userManager) throws IOException {
+
+    private void onUserManagerFound(final IUserManager userManager) throws Exception{
         if (server!=null && server.isUp()){
            server.addUserManagerService(userManager);
         } else {
@@ -163,7 +137,7 @@ public class NetconfSSHActivator implements BundleActivator{
         this.server.removeUserManagerService();
     }
     private void listenForManagerService(){
-        ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer);
+        final ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer);
         listenerTracker.open();
     }
 }
index 14a71fd9ba6a35c04eb0405df187cec8436be2e2..dcbdcabbba2683b260b003624c189561a134de2a 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-api</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>protocol-framework</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.thirdparty</groupId>
-      <artifactId>ganymed</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.openexi</groupId>
-      <artifactId>nagasena</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.openexi</groupId>
-      <artifactId>nagasena-rta</artifactId>
-    </dependency>
-
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
@@ -61,6 +44,7 @@
     <dependency>
       <groupId>xmlunit</groupId>
       <artifactId>xmlunit</artifactId>
+      <scope>test</scope>
     </dependency>
   </dependencies>
 
         <artifactId>maven-bundle-plugin</artifactId>
         <configuration>
           <instructions>
-            <Export-Package>org.opendaylight.controller.netconf.util,
-                            org.opendaylight.controller.netconf.util.xml,
-                            org.opendaylight.controller.netconf.util.osgi,
-                            org.opendaylight.controller.netconf.util.mapping,
-                            org.opendaylight.controller.netconf.util.messages,
-                            org.opendaylight.controller.netconf.util.handler,
-                            org.opendaylight.controller.netconf.util.handler.*,
-                            org.opendaylight.controller.netconf.util.exception,</Export-Package>
-            <Import-Package>com.google.common.base,
-                            com.google.common.collect,
-                            ch.ethz.ssh2,
-                            io.netty.buffer,
-                            io.netty.channel,
-                            io.netty.channel.socket,
-                            io.netty.handler.codec,
-                            io.netty.handler.ssl,
-                            io.netty.util,
-                            io.netty.util.concurrent,
-                            javax.annotation,
-                            javax.net.ssl,
-                            javax.xml.namespace,
-                            javax.xml.parsers,
-                            javax.xml.transform,
-                            javax.xml.transform.dom,
-                            javax.xml.transform.stream,
-                            javax.xml.validation,
-                            javax.xml.xpath,
-                            javax.xml.transform.sax,
-                            org.opendaylight.controller.netconf.api,
-                            org.opendaylight.controller.netconf.mapping.api,
-                            org.opendaylight.protocol.framework,
-                            org.osgi.framework,
-                            org.slf4j,
-                            org.w3c.dom,
-                            org.xml.sax,
-                            org.xml.sax.helpers,
-                            org.opendaylight.controller.config.api,
-                            org.openexi.*,</Import-Package>
+            <Import-Package>com.google.common.base, com.google.common.collect, io.netty.channel,
+              io.netty.util.concurrent, javax.annotation, javax.xml.namespace, javax.xml.parsers, javax.xml.transform,
+              javax.xml.transform.dom, javax.xml.transform.stream, javax.xml.validation, javax.xml.xpath,
+              org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.mapping.api,
+              org.osgi.framework, org.slf4j, org.w3c.dom, org.xml.sax</Import-Package>
+            <Export-Package>org.opendaylight.controller.netconf.util.*</Export-Package>
           </instructions>
         </configuration>
       </plugin>
index 9443f93f920f9720e13908c6319a139f4be0f6b0..640596d93078b86b356bc18c19d318bab89a62c6 100644 (file)
@@ -9,20 +9,12 @@ package org.opendaylight.controller.netconf.util;
 
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
 
 public final class NetconfUtil {
 
@@ -30,29 +22,6 @@ public final class NetconfUtil {
 
     private NetconfUtil() {}
 
-    public static NetconfMessage createMessage(final File f) {
-        Preconditions.checkNotNull(f, "File parameter was null");
-        try {
-            return createMessage(new FileInputStream(f));
-        } catch (final FileNotFoundException e) {
-            logger.warn("File {} not found.", f, e);
-        }
-        return null;
-    }
-
-    public static NetconfMessage createMessage(final InputStream is) {
-        Preconditions.checkNotNull(is, "InputStream parameter was null");
-        Document doc = null;
-        try {
-            doc = XmlUtil.readXmlToDocument(is);
-        } catch (final IOException e) {
-            logger.warn("Error ocurred while parsing stream.", e);
-        } catch (final SAXException e) {
-            logger.warn("Error ocurred while final parsing stream.", e);
-        }
-        return (doc == null) ? null : new NetconfMessage(doc);
-    }
-
     public static Document checkIsMessageOk(Document response) throws NetconfDocumentedException {
         XmlElement element = XmlElement.fromDomDocument(response);
         Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
index f89df2ac7cc331908f64ed8d05b2dc826f4d7757..0993b8ad0c7038e5b86b0fee0e5cb4d30fd701f8 100644 (file)
@@ -9,19 +9,24 @@
 package org.opendaylight.controller.netconf.util.osgi;
 
 import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import java.net.InetSocketAddress;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.InetSocketAddress;
 
 public final class NetconfConfigUtil {
     private static final Logger logger = LoggerFactory.getLogger(NetconfConfigUtil.class);
 
+    public static final InetSocketAddress DEFAULT_NETCONF_TCP_ADDRESS
+            = new InetSocketAddress("127.0.0.1", 8383);
+    public static final InetSocketAddress DEFAULT_NETCONF_SSH_ADDRESS
+            = new InetSocketAddress("0.0.0.0", 1830);
+
     private static final String PREFIX_PROP = "netconf.";
 
-    private NetconfConfigUtil() {}
+    private NetconfConfigUtil() {
+    }
 
     private enum InfixProp {
         tcp, ssh
@@ -31,109 +36,133 @@ public final class NetconfConfigUtil {
     private static final String ADDRESS_SUFFIX_PROP = ".address";
     private static final String CLIENT_PROP = ".client";
     private static final String PRIVATE_KEY_PATH_PROP = ".pk.path";
-    private static final String SSH_DEFAULT_USER = ".default.user";
-    private static final String SSH_DEFAULT_PASSWORD = ".default.password";
 
     private static final String CONNECTION_TIMEOUT_MILLIS_PROP = "connectionTimeoutMillis";
     private static final long DEFAULT_TIMEOUT_MILLIS = 5000;
 
-    public static long extractTimeoutMillis(BundleContext bundleContext) {
-        String key = PREFIX_PROP + CONNECTION_TIMEOUT_MILLIS_PROP;
-        String timeoutString = bundleContext.getProperty(key);
+    public static long extractTimeoutMillis(final BundleContext bundleContext) {
+        final String key = PREFIX_PROP + CONNECTION_TIMEOUT_MILLIS_PROP;
+        final String timeoutString = bundleContext.getProperty(key);
         if (timeoutString == null || timeoutString.length() == 0) {
             return DEFAULT_TIMEOUT_MILLIS;
         }
         try {
             return Long.parseLong(timeoutString);
-        }catch(NumberFormatException e) {
+        } catch (final NumberFormatException e) {
             logger.warn("Cannot parse {} property: {}, using defaults", key, timeoutString, e);
             return DEFAULT_TIMEOUT_MILLIS;
         }
     }
 
-    public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound, boolean forClient) {
-
-        Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient);
-
-        if (!inetSocketAddressOptional.isPresent()) {
-            throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
-        }
-        InetSocketAddress inetSocketAddress = inetSocketAddressOptional.get();
-        if (inetSocketAddress.getAddress().isAnyLocalAddress()) {
+    public static InetSocketAddress extractTCPNetconfServerAddress(final BundleContext context, final InetSocketAddress defaultAddress) {
+        final Optional<InetSocketAddress> extracted = extractNetconfServerAddress(context, InfixProp.tcp);
+        final InetSocketAddress netconfTcpAddress = getNetconfAddress(defaultAddress, extracted, InfixProp.tcp);
+        logger.debug("Using {} as netconf tcp address", netconfTcpAddress);
+        if (netconfTcpAddress.getAddress().isAnyLocalAddress()) {
             logger.warn("Unprotected netconf TCP address is configured to ANY local address. This is a security risk. " +
                     "Consider changing {} to 127.0.0.1", PREFIX_PROP + InfixProp.tcp + ADDRESS_SUFFIX_PROP);
         }
-        return inetSocketAddress;
+        return netconfTcpAddress;
     }
 
-    public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context, String exceptionMessage) {
-        return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage, false);
+    public static InetSocketAddress extractTCPNetconfClientAddress(final BundleContext context, final InetSocketAddress defaultAddress) {
+        final Optional<InetSocketAddress> extracted = extractNetconfClientAddress(context, InfixProp.tcp);
+        return getNetconfAddress(defaultAddress, extracted, InfixProp.tcp);
     }
 
-    public static String getPrivateKeyPath(BundleContext context){
-        return getPropertyValue(context,PREFIX_PROP + InfixProp.ssh +PRIVATE_KEY_PATH_PROP);
+    /**
+     * Get extracted address or default.
+     *
+     * @throws java.lang.IllegalStateException if neither address is present.
+     */
+    private static InetSocketAddress getNetconfAddress(final InetSocketAddress defaultAddress, Optional<InetSocketAddress> extractedAddress, InfixProp infix) {
+        InetSocketAddress inetSocketAddress;
+
+        if (extractedAddress.isPresent() == false) {
+            logger.debug("Netconf {} address not found, falling back to default {}", infix, defaultAddress);
+
+            if (defaultAddress == null) {
+                logger.warn("Netconf {} address not found, default address not provided", infix);
+                throw new IllegalStateException("Netconf " + infix + " address not found, default address not provided");
+            }
+            inetSocketAddress = defaultAddress;
+        } else {
+            inetSocketAddress = extractedAddress.get();
+        }
+
+        return inetSocketAddress;
     }
-    public static Optional<String> getSSHDefaultUser(BundleContext context){
-        return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_USER);
+
+    public static InetSocketAddress extractSSHNetconfAddress(final BundleContext context, final InetSocketAddress defaultAddress) {
+        Optional<InetSocketAddress> extractedAddress = extractNetconfServerAddress(context, InfixProp.ssh);
+        InetSocketAddress netconfSSHAddress = getNetconfAddress(defaultAddress, extractedAddress, InfixProp.ssh);
+        logger.debug("Using {} as netconf SSH address", netconfSSHAddress);
+        return netconfSSHAddress;
     }
-    public static Optional<String> getSSHDefaultPassword(BundleContext context){
-        return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_PASSWORD);
+
+    public static String getPrivateKeyPath(final BundleContext context) {
+        return getPropertyValue(context, PREFIX_PROP + InfixProp.ssh + PRIVATE_KEY_PATH_PROP);
     }
 
-    private static String getPropertyValue(BundleContext context, String propertyName){
-        String propertyValue = context.getProperty(propertyName);
-        if (propertyValue == null){
-            throw new IllegalStateException("Cannot find initial property with name '"+propertyName+"'");
+    private static String getPropertyValue(final BundleContext context, final String propertyName) {
+        final String propertyValue = context.getProperty(propertyName);
+        if (propertyValue == null) {
+            throw new IllegalStateException("Cannot find initial property with name '" + propertyName + "'");
         }
         return propertyValue;
     }
-    private static Optional<String> getOptionalPropertyValue(BundleContext context, String propertyName){
-        String propertyValue = context.getProperty(propertyName);
-        if (Strings.isNullOrEmpty(propertyValue)){
-            return Optional.absent();
-        }
-        return Optional.fromNullable(propertyValue);
-    }
+
     /**
-     * @param context
-     *            from which properties are being read.
-     * @param infixProp
-     *            either tcp or ssh
-     * @return value if address and port are valid.
-     * @throws IllegalStateException
-     *             if address or port are invalid, or configuration is missing
+     * @param context   from which properties are being read.
+     * @param infixProp either tcp or ssh
+     * @return value if address and port are present and valid, Optional.absent otherwise.
+     * @throws IllegalStateException if address or port are invalid, or configuration is missing
      */
-    private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
-                                                                         InfixProp infixProp,
-                                                                         String exceptionMessage,
-                                                                         boolean client) {
-        String address = "";
-        if (client) {
-            address = context.getProperty(PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP);
-        }
-        if (address == null || address.equals("")){
-            address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
-        }
-        if (address == null || address.equals("")) {
-            throw new IllegalStateException("Cannot find initial netconf configuration for parameter    "
-                    +PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP
-                    +" in config.ini. "+exceptionMessage);
-        }
-        String portKey = "";
-        if (client) {
-            portKey = PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP;
+    private static Optional<InetSocketAddress> extractNetconfServerAddress(final BundleContext context,
+                                                                           final InfixProp infixProp) {
+
+        final Optional<String> address = getProperty(context, PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
+        final Optional<String> port = getProperty(context, PREFIX_PROP + infixProp + PORT_SUFFIX_PROP);
+
+        if (address.isPresent() && port.isPresent()) {
+            try {
+                return Optional.of(parseAddress(address, port));
+            } catch (final RuntimeException e) {
+                logger.warn("Unable to parse {} netconf address from {}:{}, fallback to default",
+                        infixProp, address, port, e);
+            }
         }
-        if (portKey == null || portKey.equals("")){
-            portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
+        return Optional.absent();
+    }
+
+    private static InetSocketAddress parseAddress(final Optional<String> address, final Optional<String> port) {
+        final int portNumber = Integer.valueOf(port.get());
+        return new InetSocketAddress(address.get(), portNumber);
+    }
+
+    private static Optional<InetSocketAddress> extractNetconfClientAddress(final BundleContext context,
+                                                                           final InfixProp infixProp) {
+        final Optional<String> address = getProperty(context,
+                PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP);
+        final Optional<String> port = getProperty(context,
+                PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP);
+
+        if (address.isPresent() && port.isPresent()) {
+            try {
+                return Optional.of(parseAddress(address, port));
+            } catch (final RuntimeException e) {
+                logger.warn("Unable to parse client {} netconf address from {}:{}, fallback to server address",
+                        infixProp, address, port, e);
+            }
         }
-        String portString = context.getProperty(portKey);
-        checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
-        try {
-            int port = Integer.valueOf(portString);
-            return Optional.of(new InetSocketAddress(address, port));
-        } catch (RuntimeException e) {
-            throw new IllegalStateException("Cannot create " + infixProp + " netconf address from address:" + address
-                    + " and port:" + portString, e);
+        return extractNetconfServerAddress(context, infixProp);
+    }
+
+    private static Optional<String> getProperty(final BundleContext context, final String propKey) {
+        String value = context.getProperty(propKey);
+        if (value != null && value.isEmpty()) {
+            value = null;
         }
+        return Optional.fromNullable(value);
     }
 }
index 66603fb6c2d60b90cf2e17c277e65420d3c0b8b1..ac200a0aa668c1a406e044e11205ac90c20fc478 100644 (file)
@@ -10,9 +10,17 @@ package org.opendaylight.controller.netconf.util.xml;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
@@ -28,14 +36,6 @@ import org.w3c.dom.NodeList;
 import org.w3c.dom.Text;
 import org.xml.sax.SAXException;
 
-import javax.annotation.Nullable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 public final class XmlElement {
 
     private final Element element;
@@ -111,7 +111,7 @@ public final class XmlElement {
     public void checkNamespaceAttribute(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
         if (!getNamespaceAttribute().equals(expectedNamespace))
         {
-            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s",
                     getNamespaceAttribute(),
                     expectedNamespace),
                     NetconfDocumentedException.ErrorType.application,
@@ -123,7 +123,7 @@ public final class XmlElement {
     public void checkNamespace(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
         if (!getNamespace().equals(expectedNamespace))
        {
-            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+            throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s",
                     getNamespace(),
                     expectedNamespace),
                     NetconfDocumentedException.ErrorType.application,
@@ -320,23 +320,22 @@ public final class XmlElement {
     }
 
     public String getTextContent() throws NetconfDocumentedException {
-        Node textChild = element.getFirstChild();
-        if (null == textChild){
-            throw new NetconfDocumentedException(String.format( "Child node expected, got null for " + getName() + " : " + element),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.invalid_value,
-                    NetconfDocumentedException.ErrorSeverity.error);
+        NodeList childNodes = element.getChildNodes();
+        if (childNodes.getLength() == 0) {
+            return "";
         }
-        if (!(textChild instanceof Text)){
-            throw new NetconfDocumentedException(String.format(getName() + " should contain text." +
-                    Text.class.getName() + " expected, got " + textChild),
-                    NetconfDocumentedException.ErrorType.application,
-                    NetconfDocumentedException.ErrorTag.invalid_value,
-                    NetconfDocumentedException.ErrorSeverity.error);
+        for(int i = 0; i < childNodes.getLength(); i++) {
+            Node textChild = childNodes.item(i);
+            if (textChild instanceof Text) {
+                String content = textChild.getTextContent();
+                return content.trim();
+            }
         }
-        String content = textChild.getTextContent();
-        // Trim needed
-        return content.trim();
+        throw new NetconfDocumentedException(getName() + " should contain text.",
+                NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.invalid_value,
+                NetconfDocumentedException.ErrorSeverity.error
+        );
     }
 
     public String getNamespaceAttribute() throws MissingNameSpaceException {
@@ -351,15 +350,24 @@ public final class XmlElement {
         return attribute;
     }
 
-    public String getNamespace() throws MissingNameSpaceException {
+    public Optional<String> getNamespaceOptionally() {
         String namespaceURI = element.getNamespaceURI();
-        if (namespaceURI  == null || namespaceURI.equals("")){
+        if (Strings.isNullOrEmpty(namespaceURI)) {
+            return Optional.absent();
+        } else {
+            return Optional.of(namespaceURI);
+        }
+    }
+
+    public String getNamespace() throws MissingNameSpaceException {
+        Optional<String> namespaceURI = getNamespaceOptionally();
+        if (namespaceURI.isPresent() == false){
             throw new MissingNameSpaceException(String.format("No namespace defined for %s", this),
                     NetconfDocumentedException.ErrorType.application,
                     NetconfDocumentedException.ErrorTag.operation_failed,
                     NetconfDocumentedException.ErrorSeverity.error);
         }
-        return namespaceURI;
+        return namespaceURI.get();
     }
 
     @Override
index 1f81117ca383922ff246c9e10af36b708f84b26a..b2b202b69ef024569d032771ecd35e116812769e 100644 (file)
@@ -10,11 +10,12 @@ package org.opendaylight.controller.netconf.util.xml;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
-
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilder;
@@ -32,17 +33,15 @@ import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
 
 public final class XmlUtil {
 
     public static final String XMLNS_ATTRIBUTE_KEY = "xmlns";
-    private static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+    public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
     private static final DocumentBuilderFactory BUILDERFACTORY;
 
     static {
@@ -118,8 +117,14 @@ public final class XmlUtil {
         return typeElement;
     }
 
-    public static Element createPrefixedTextElement(Document document, String qName, String prefix, String content, Optional<String> namespace) {
-        return createTextElement(document, qName, createPrefixedValue(prefix, content), namespace);
+    public static Element createTextElementWithNamespacedContent(Document document, String qName, String prefix,
+                                                                 String namespace, String contentWithoutPrefix) {
+
+        String content = createPrefixedValue(XmlNetconfConstants.PREFIX, contentWithoutPrefix);
+        Element element = createTextElement(document, qName, content, Optional.<String>absent());
+        String prefixedNamespaceAttr = createPrefixedValue(XMLNS_ATTRIBUTE_KEY, prefix);
+        element.setAttributeNS(XMLNS_URI, prefixedNamespaceAttr, namespace);
+        return element;
     }
 
     public static String createPrefixedValue(String prefix, String value) {
index e8a453e5d3b9da48431f4886388d89457ff52804..e0d432f27cbb14c581a3bf9fc3453f76d2b2d984 100644 (file)
@@ -16,6 +16,7 @@ import org.custommonkey.xmlunit.AbstractNodeTester;
 import org.custommonkey.xmlunit.NodeTest;
 import org.custommonkey.xmlunit.NodeTestException;
 import org.custommonkey.xmlunit.NodeTester;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -88,7 +89,7 @@ public class XmlUnitUtil {
 
             @Override
             public void noMoreNodes(NodeTest forTest) throws NodeTestException {
-                assertTrue(elementFound);
+                assertTrue(XmlUtil.toString(doc), elementFound);
             }
         };
         assertNodeTestPasses(nt, tester, new short[]{Node.ELEMENT_NODE}, true);
index 35cf2c6a1423e090a3205376a0c2f953c0fd4b48..5dd5a90f7db9550cf4fbe677aea456cdcf821ecc 100644 (file)
                     </type>
 
                     <name>instance-from-code</name>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <sleep-factor>
+                            2.58
+                        </sleep-factor>
 
-                    <sleep-factor>
-                        2.58
-                    </sleep-factor>
+                        <extended>
+                                10
+                        </extended>
 
-                    <extended>
-                            10
-                    </extended>
+                        <extended-twice>
+                                20
+                        </extended-twice>
 
-                    <extended-twice>
-                            20
-                    </extended-twice>
+                        <extended-enum>
+                            TWO
+                        </extended-enum>
 
-                    <extended-enum>
-                        TWO
-                    </extended-enum>
+                        <simple-long-2>44</simple-long-2>
+                        <binaryLeaf>YmluYXJ5</binaryLeaf>
 
-                    <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>YmluYXJ5</binaryLeaf>
-
-                    <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
-                    <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        <simple-int1>444</simple-int1>
-                        <simple-int2>4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
+                        <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
+                        <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                            <simple-int1>444</simple-int1>
+                            <simple-int2>4444</simple-int2>
+                            <simple-int3>454</simple-int3>
+                            <complex-dto-bInner>
+                                <simple-int3>44</simple-int3>
+                                <deep>
+                                    <simple-int3>4</simple-int3>
+                                </deep>
+                                <simple-list>4</simple-list>
+                            </complex-dto-bInner>
                             <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep_user</name>
-                    </testing-dep>
+                        </dto_d>
+                        <simpleInt>44</simpleInt>
+                        <simple-test>545</simple-test>
+                        <simple-long>454545</simple-long>
+                        <simpleBoolean>false</simpleBoolean>
+                        <dto-c>
+                            <dto-a-inner>
+                                <dto-a-inner-inner>
+                                    <simple-arg>456</simple-arg>
+                                </dto-a-inner-inner>
+                                <simple-arg>44</simple-arg>
+                            </dto-a-inner>
+                        </dto-c>
+                        <simple-short>4</simple-short>
+                        <simple-BigInteger>999</simple-BigInteger>
+                        <simple-byte>4</simple-byte>
+                        <peers>
+                            <port>port1</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <peers>
+                            <port>port23</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep_user</name>
+                        </testing-dep>
 
-                    <testing-deps>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep_user</name>
-                    </testing-deps>
-                    <testing-deps>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep_user_two</name>
-                    </testing-deps>
+                        <testing-deps>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep_user</name>
+                        </testing-deps>
+                        <testing-deps>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep_user_two</name>
+                        </testing-deps>
+                    </impl-netconf>
                 </module>
 
                 <module>
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <simple-short>4</simple-short>
-
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep_user_two</name>
-                    </testing-dep>
+                    <impl-netconf  xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <simple-short>4</simple-short>
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep_user_two</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
             </modules>
 
index ade40f6a49c94f2a682b7e55e1ec1a3d79e03ecc..be3155222a2564be8a65d6d755672333841ce0dc 100644 (file)
                         test-impl:impl-netconf
                     </type>
                     <name>instance-from-code</name>
-                    <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8ad1</binaryLeaf>
-                    <dto_d>
-                        <simple-int1>444</simple-int1>
-                        <simple-int2>4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <simple-long-2>44</simple-long-2>
+                        <binaryLeaf>8ad1</binaryLeaf>
+                        <dto_d>
+                            <simple-int1>444</simple-int1>
+                            <simple-int2>4444</simple-int2>
+                            <simple-int3>454</simple-int3>
+                            <complex-dto-bInner>
+                                <simple-int3>44</simple-int3>
+                                <deep>
+                                    <simple-int3>4</simple-int3>
+                                </deep>
+                                <simple-list>4</simple-list>
+                            </complex-dto-bInner>
                             <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
+                        </dto_d>
+                        <simpleInt>44</simpleInt>
+                        <simple-test>545</simple-test>
+                        <simple-long>454545</simple-long>
+                        <simpleBoolean>false</simpleBoolean>
+                        <dto-c>
+                            <dto-a-inner>
+                                <dto-a-inner-inner>
+                                    <simple-arg>456</simple-arg>
+                                </dto-a-inner-inner>
+                                <simple-arg>44</simple-arg>
+                            </dto-a-inner>
+                        </dto-c>
+                        <simple-short>4</simple-short>
+                        <simple-BigInteger>999</simple-BigInteger>
+                        <simple-byte>4</simple-byte>
+                        <peers>
+                            <port>port1</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <peers>
+                            <port>port23</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                    </impl-netconf>
                 </module>
                 <module>
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
index 21db4b8e4244b7197f36c8a4761ca4313faf1ba3..3f088e48c9c63e201ff5725442a291f187dc33be 100644 (file)
                     </type>
 
                     <name>instance-from-code</name>
-
-                    <ip xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">127.1.2.3</ip>
-                    <union-test-attr xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">randomStringForUnion</union-test-attr>
-
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <ip xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">127.1.2.3</ip>
+                        <union-test-attr xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">randomStringForUnion</union-test-attr>
+                    </impl-netconf>
                 </module>
             </modules>
 
index df2a5e845257c6b8308ad03eac43a91feb687772..16947f9ec7a3fdcbfa1aff6f23bfd2b1acd1220e 100644 (file)
                     </type>
 
                     <name>test1</name>
-
-                    <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8545649856</binaryLeaf>
-                    <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
-                    <dto_d>
-                        <simple-int1>444</simple-int1>
-                        <simple-int2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <simple-long-2>44</simple-long-2>
+                        <binaryLeaf>8545649856</binaryLeaf>
+                        <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
+                        <dto_d>
+                            <simple-int1>444</simple-int1>
+                            <simple-int2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl2">4444</simple-int2>
+                            <simple-int3>454</simple-int3>
+                            <complex-dto-bInner>
+                                <simple-int3>44</simple-int3>
+                                <deep>
+                                    <simple-int3>4</simple-int3>
+                                </deep>
+                                <simple-list>4</simple-list>
+                            </complex-dto-bInner>
                             <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                        </dto_d>
+                        <simpleInt>44</simpleInt>
+                        <simple-test>545</simple-test>
+                        <simple-long>454545</simple-long>
+                        <simpleBoolean>false</simpleBoolean>
+                        <dto-c>
+                            <dto-a-inner>
+                                <dto-a-inner-inner>
+                                    <simple-arg>456</simple-arg>
+                                </dto-a-inner-inner>
+                                <simple-arg>44</simple-arg>
+                            </dto-a-inner>
+                        </dto-c>
+                        <simple-short>4</simple-short>
+                        <simple-BigInteger>999</simple-BigInteger>
+                        <simple-byte>4</simple-byte>
+                        <peers>
+                            <port>port1</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <peers>
+                            <port>port23</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
 
                 <module>
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
             </modules>
 
index c399c196d37174a9df5bba448f44d4b7fbdd441d..3dbaef4042a304cc0f03ec67de7cdb2b009442c1 100644 (file)
                     </type>
                 </module>
 
+              <module>
+                <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                  test-impl:impl
+                </type>
+
+                <name>testimpl</name>
+                <simpleInt>1</simpleInt>
+                <simpleInt xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">2</simpleInt>
+              </module>
+
                 <module>
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         test-impl:impl-netconf
                     </type>
 
                     <name>test1</name>
-
-                    <simple-long-2>44</simple-long-2>
-                    <simple-long-2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf>1</binaryLeaf>
-                    <binaryLeaf>0</binaryLeaf>
-                    <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
-                    <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        <simple-int1>444</simple-int1>
-                        <simple-int2>4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <simple-long-2>44</simple-long-2>
+                        <simple-long-2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">44</simple-long-2>
+                        <binaryLeaf></binaryLeaf>
+                        <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
+                        <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                            <simple-int1>444</simple-int1>
+                            <simple-int2>4444</simple-int2>
+                            <simple-int3>454</simple-int3>
+                            <complex-dto-bInner>
+                                <simple-int3>44</simple-int3>
+                                <deep>
+                                    <simple-int3>4</simple-int3>
+                                </deep>
+                                <simple-list>4</simple-list>
+                            </complex-dto-bInner>
                             <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                        </dto_d>
+                        <simpleInt>44</simpleInt>
+                        <simple-test>545</simple-test>
+                        <simple-long>454545</simple-long>
+                        <simpleBoolean>false</simpleBoolean>
+                        <dto-c>
+                            <dto-a-inner>
+                                <dto-a-inner-inner>
+                                    <simple-arg>456</simple-arg>
+                                </dto-a-inner-inner>
+                                <simple-arg>44</simple-arg>
+                            </dto-a-inner>
+                        </dto-c>
+                        <simple-short>4</simple-short>
+                        <simple-BigInteger>999</simple-BigInteger>
+                        <simple-byte>4</simple-byte>
+                        <peers>
+                            <port>port1</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <peers>
+                            <port>port23</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
 
                 <module>
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
             </modules>
 
index 47b82c6114f6048fa4a42fd4a8482ac8665162b0..6ee97ee09c624ad7d5dded223f212bc5706f58e2 100644 (file)
 
                 <module>
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        test-impl:impl-netconf
+                        test-impl:impl
                     </type>
 
                     <name>test1</name>
-
-                    <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">1</binaryLeaf>
-                    <binaryLeaf>0</binaryLeaf>
-                    <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
-                    <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        <simple-int1>444</simple-int1>
-                        <simple-int2>4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
-                            <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                    <allow-user>1</allow-user>
+                    <allow-user xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">2</allow-user>
                 </module>
 
                 <module>
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
             </modules>
 
             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                <service>
-                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                    <instance>
-                        <name>ref_dep</name>
-                        <provider>/modules/module[type='impl-dep'][name='dep']
-                        </provider>
-                    </instance>
-                    <instance>
-                        <name>ref_dep_2</name>
-                        <provider>/modules/module[type='impl-dep'][name='dep2']
-                        </provider>
-                    </instance>
-                    <instance>
-                        <name>ref_test1</name>
-                        <provider>
-                            /modules/module[type='impl-netconf'][name='test1']
-                        </provider>
-                    </instance>
-                </service>
+
             </services>
         </config>
     </edit-config>
index 02aca8d787863a2683db402b0c3a9a82ed6ff699..1e5c6da79c1263c3c7591c21dfe261132ab28764 100644 (file)
                     </type>
 
                     <name>test1</name>
-
-                    <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8545649856</binaryLeaf>
-                    <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-                        <simple-int1>444</simple-int1>
-                        <simple-int2>4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <simple-long-2>44</simple-long-2>
+                        <binaryLeaf>8545649856</binaryLeaf>
+                        <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                            <simple-int1>444</simple-int1>
+                            <simple-int2>4444</simple-int2>
+                            <simple-int3>454</simple-int3>
+                            <complex-dto-bInner>
+                                <simple-int3>44</simple-int3>
+                                <deep>
+                                    <simple-int3>4</simple-int3>
+                                </deep>
+                                <simple-list>4</simple-list>
+                            </complex-dto-bInner>
                             <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                        </dto_d>
+                        <simpleInt>44</simpleInt>
+                        <simple-test>545</simple-test>
+                        <simple-long>454545</simple-long>
+                        <simpleBoolean>false</simpleBoolean>
+                        <dto-c>
+                            <dto-a-inner>
+                                <dto-a-inner-inner>
+                                    <simple-arg>456</simple-arg>
+                                </dto-a-inner-inner>
+                                <simple-arg>44</simple-arg>
+                            </dto-a-inner>
+                        </dto-c>
+                        <simple-short>4</simple-short>
+                        <simple-BigInteger>999</simple-BigInteger>
+                        <simple-byte>4</simple-byte>
+                        <peers>
+                            <port>port1</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <peers>
+                            <port>port23</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
 
                 <module>
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                      <testing-dep>
+                          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                          <name>ref_dep</name>
+                      </testing-dep>
+                    </impl-netconf>
                 </module>
             </modules>
 
index 825be6d19fff18b2d8ccb0c078e6266e4e89c3f1..156c1114081c1c1ba1116beaa7f8b2b2fafa1b69 100644 (file)
                     </type>
 
                     <name>test1</name>
-
-                    <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8545649856</binaryLeaf>
-                    <dto_d>
-                        <unknownAttribute>error</unknownAttribute>
-                        <simple-int1>444</simple-int1>
-                        <simple-int2>4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <simple-long-2>44</simple-long-2>
+                        <binaryLeaf>8545649856</binaryLeaf>
+                        <dto_d>
+                            <unknownAttribute>error</unknownAttribute>
+                            <simple-int1>444</simple-int1>
+                            <simple-int2>4444</simple-int2>
+                            <simple-int3>454</simple-int3>
+                            <complex-dto-bInner>
+                                <simple-int3>44</simple-int3>
+                                <deep>
+                                    <simple-int3>4</simple-int3>
+                                </deep>
+                                <simple-list>4</simple-list>
+                            </complex-dto-bInner>
                             <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                        </dto_d>
+                        <simpleInt>44</simpleInt>
+                        <simple-test>545</simple-test>
+                        <simple-long>454545</simple-long>
+                        <simpleBoolean>false</simpleBoolean>
+                        <dto-c>
+                            <dto-a-inner>
+                                <dto-a-inner-inner>
+                                    <simple-arg>456</simple-arg>
+                                </dto-a-inner-inner>
+                                <simple-arg>44</simple-arg>
+                            </dto-a-inner>
+                        </dto-c>
+                        <simple-short>4</simple-short>
+                        <simple-BigInteger>999</simple-BigInteger>
+                        <simple-byte>4</simple-byte>
+                        <peers>
+                            <port>port1</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <peers>
+                            <port>port23</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
 
                 <module>
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
             </modules>
 
index 9ef2bed7d70dfb7654df642480cacc3df354baae..9b9157e65abb0217e7d8b60f78cfe8d670b227aa 100644 (file)
                     </type>
 
                     <name>test1</name>
-
-                    <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8545649856</binaryLeaf>
-                    <dto_d>
-                        <simple-int1>444</simple-int1>
-                        <simple-int2>4444</simple-int2>
-                        <simple-int3>454</simple-int3>
-                        <complex-dto-bInner>
-                            <simple-int3>44</simple-int3>
-                            <deep>
-                                <simple-int3>4</simple-int3>
-                            </deep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <simple-long-2>44</simple-long-2>
+                        <binaryLeaf>8545649856</binaryLeaf>
+                        <dto_d>
+                            <simple-int1>444</simple-int1>
+                            <simple-int2>4444</simple-int2>
+                            <simple-int3>454</simple-int3>
+                            <complex-dto-bInner>
+                                <simple-int3>44</simple-int3>
+                                <deep>
+                                    <simple-int3>4</simple-int3>
+                                </deep>
+                                <simple-list>4</simple-list>
+                            </complex-dto-bInner>
                             <simple-list>4</simple-list>
-                        </complex-dto-bInner>
-                        <simple-list>4</simple-list>
-                    </dto_d>
-                    <simpleInt>44</simpleInt>
-                    <simple-test>545</simple-test>
-                    <simple-long>454545</simple-long>
-                    <simpleBoolean>false</simpleBoolean>
-                    <dto-c>
-                        <dto-a-inner>
-                            <dto-a-inner-inner>
-                                <simple-arg>456</simple-arg>
-                            </dto-a-inner-inner>
-                            <simple-arg>44</simple-arg>
-                        </dto-a-inner>
-                    </dto-c>
-                    <simple-short>4</simple-short>
-                    <simple-BigInteger>999</simple-BigInteger>
-                    <simple-byte>4</simple-byte>
-                    <peers>
-                        <port>port1</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                    </peers>
-                    <peers>
-                        <port>port23</port>
-                        <simple-int3>456</simple-int3>
-                        <core-size>44</core-size>
-                        <unknownAttribute>error</unknownAttribute>
-                    </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                        </dto_d>
+                        <simpleInt>44</simpleInt>
+                        <simple-test>545</simple-test>
+                        <simple-long>454545</simple-long>
+                        <simpleBoolean>false</simpleBoolean>
+                        <dto-c>
+                            <dto-a-inner>
+                                <dto-a-inner-inner>
+                                    <simple-arg>456</simple-arg>
+                                </dto-a-inner-inner>
+                                <simple-arg>44</simple-arg>
+                            </dto-a-inner>
+                        </dto-c>
+                        <simple-short>4</simple-short>
+                        <simple-BigInteger>999</simple-BigInteger>
+                        <simple-byte>4</simple-byte>
+                        <peers>
+                            <port>port1</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                        </peers>
+                        <peers>
+                            <port>port23</port>
+                            <simple-int3>456</simple-int3>
+                            <core-size>44</core-size>
+                            <unknownAttribute>error</unknownAttribute>
+                        </peers>
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
 
                 <module>
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
+                    <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        <testing-dep>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                            <name>ref_dep</name>
+                        </testing-dep>
+                    </impl-netconf>
                 </module>
             </modules>
 
index 50e84463f5651948f408ef703ce6ee2d93590330..4f87fd8626b2d1cfd98925c0e3be5015808b41a3 100644 (file)
@@ -22,6 +22,7 @@
     <module>netconf-impl</module>
     <module>config-netconf-connector</module>
     <module>netconf-util</module>
+    <module>netconf-netty-util</module>
     <module>config-persister-impl</module>
     <module>netconf-mapping-api</module>
     <module>netconf-client</module>
index c30f65903204df027b582c1c5816d5b106c91239..1e2cd47c9c2d923ac09f3cbc50fc60b9c2a519f0 100644 (file)
@@ -22,6 +22,8 @@ import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
 
 public class Activator extends ComponentActivatorAbstractBase {
@@ -64,7 +66,9 @@ public class Activator extends ComponentActivatorAbstractBase {
                 NeutronRouterInterface.class,
                 NeutronPortInterface.class,
                 NeutronSubnetInterface.class,
-                NeutronNetworkInterface.class };
+                NeutronNetworkInterface.class,
+                NeutronSecurityGroupInterface.class,
+                NeutronSecurityRuleInterface.class};
         return res;
     }
 
@@ -163,5 +167,37 @@ public class Activator extends ComponentActivatorAbstractBase {
                     "setConfigurationContainerService",
                     "unsetConfigurationContainerService").setRequired(true));
         }
+        if (imp.equals(NeutronSecurityGroupInterface.class)) {
+            // export the service
+            c.setInterface(
+                new String[] { INeutronSecurityGroupCRUD.class.getName(),
+                    IConfigurationContainerAware.class.getName()}, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                .setService(IClusterContainerServices.class)
+                .setCallbacks("setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(
+                IConfigurationContainerService.class).setCallbacks(
+                "setConfigurationContainerService",
+                "unsetConfigurationContainerService").setRequired(true));
+        }
+        if (imp.equals(NeutronSecurityRuleInterface.class)) {
+            // export the service
+            c.setInterface(
+                new String[] { INeutronSecurityRuleCRUD.class.getName(),
+                    IConfigurationContainerAware.class.getName()}, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                .setService(IClusterContainerServices.class)
+                .setCallbacks("setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(
+                IConfigurationContainerService.class).setCallbacks(
+                "setConfigurationContainerService",
+                "unsetConfigurationContainerService").setRequired(true));
+        }
     }
 }
diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityGroupInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityGroupInterface.java
new file mode 100644 (file)
index 0000000..a991f61
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.implementation;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NeutronSecurityGroupInterface implements INeutronSecurityGroupCRUD, IConfigurationContainerAware, IObjectReader {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronSecurityGroupInterface.class);
+    private static final String FILE_NAME ="neutron.securitygroup.conf";
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private IConfigurationContainerService configurationService;
+    private ConcurrentMap<String, NeutronSecurityGroup> securityGroupDB;
+
+    // methods needed for creating caches
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            clusterContainerService = null;
+        }
+    }
+
+    public void setConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service set: {}", service);
+        configurationService = service;
+    }
+
+    public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service removed: {}", service);
+        configurationService = null;
+    }
+
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Security Groups");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronSecurityGroups",
+                EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Security Groups -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Security Groups already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Security Groups");
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    private void retrieveCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Security Groups");
+        securityGroupDB = (ConcurrentMap<String, NeutronSecurityGroup>) clusterContainerService
+            .getCache("neutronSecurityGroups");
+        if (securityGroupDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Security Groups");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Security Groups");
+    }
+
+    private void destroyCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for Neutron Security Groups");
+        clusterContainerService.destroyCache("neutronSecurityGroups");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+        loadConfiguration();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean neutronSecurityGroupExists(String uuid) {
+        return securityGroupDB.containsKey(uuid);
+    }
+
+    @Override
+    public NeutronSecurityGroup getNeutronSecurityGroup(String uuid) {
+        if (!neutronSecurityGroupExists(uuid)) {
+            logger.debug("No Security Groups Have Been Defined");
+            return null;
+        }
+        return securityGroupDB.get(uuid);
+    }
+
+    @Override
+    public List<NeutronSecurityGroup> getAllNeutronSecurityGroups() {
+        Set<NeutronSecurityGroup> allSecurityGroups = new HashSet<NeutronSecurityGroup>();
+        for (Entry<String, NeutronSecurityGroup> entry : securityGroupDB.entrySet()) {
+            NeutronSecurityGroup securityGroup = entry.getValue();
+            allSecurityGroups.add(securityGroup);
+        }
+        logger.debug("Exiting getSecurityGroups, Found {} OpenStackSecurityGroup", allSecurityGroups.size());
+        List<NeutronSecurityGroup> ans = new ArrayList<NeutronSecurityGroup>();
+        ans.addAll(allSecurityGroups);
+        return ans;
+    }
+
+    @Override
+    public boolean addNeutronSecurityGroup(NeutronSecurityGroup input) {
+        if (neutronSecurityGroupExists(input.getSecurityGroupUUID())) {
+            return false;
+        }
+        securityGroupDB.putIfAbsent(input.getSecurityGroupUUID(), input);
+        return true;
+    }
+
+    @Override
+    public boolean removeNeutronSecurityGroup(String uuid) {
+        if (!neutronSecurityGroupExists(uuid)) {
+            return false;
+        }
+        securityGroupDB.remove(uuid);
+        return true;
+    }
+
+    @Override
+    public boolean updateNeutronSecurityGroup(String uuid, NeutronSecurityGroup delta) {
+        if (!neutronSecurityGroupExists(uuid)) {
+            return false;
+        }
+        NeutronSecurityGroup target = securityGroupDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    @Override
+    public boolean neutronSecurityGroupInUse(String securityGroupUUID) {
+        return !neutronSecurityGroupExists(securityGroupUUID);
+    }
+
+    private void loadConfiguration() {
+        for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+            NeutronSecurityGroup nn = (NeutronSecurityGroup) conf;
+            securityGroupDB.put(nn.getSecurityGroupUUID(), nn);
+        }
+    }
+
+    @Override
+    public Status saveConfiguration() {
+        return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(securityGroupDB.values()),
+            FILE_NAME);
+    }
+
+    @Override
+    public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+        return ois.readObject();
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityRuleInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityRuleInterface.java
new file mode 100644 (file)
index 0000000..5ca907b
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.implementation;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NeutronSecurityRuleInterface implements INeutronSecurityRuleCRUD, IConfigurationContainerAware, IObjectReader {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronSecurityRuleInterface.class);
+    private static final String FILE_NAME = "neutron.securityrule.conf";
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private IConfigurationContainerService configurationService;
+    private ConcurrentMap<String, NeutronSecurityRule> securityRuleDB;
+
+    // methods needed for creating caches
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            clusterContainerService = null;
+        }
+    }
+
+    public void setConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service set: {}", service);
+        configurationService = service;
+    }
+
+    public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service removed: {}", service);
+        configurationService = null;
+    }
+
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Security Rules");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronSecurityRules",
+                EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Security Rules -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Security Rules already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Security Rules");
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private void retrieveCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Security Rules");
+        securityRuleDB = (ConcurrentMap<String, NeutronSecurityRule>) clusterContainerService
+            .getCache("neutronSecurityRules");
+        if (securityRuleDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Security Rules");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Security Rules");
+    }
+
+    private void destroyCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for Neutron Security Rules");
+        clusterContainerService.destroyCache("neutronSecurityRules");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+        loadConfiguration();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for (Method toMethod : methods) {
+            if (toMethod.getDeclaringClass().equals(target.getClass())
+                && toMethod.getName().startsWith("set")) {
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[]) null);
+                    if (value != null) {
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean neutronSecurityRuleExists(String uuid) {
+        return securityRuleDB.containsKey(uuid);
+    }
+
+    @Override
+    public NeutronSecurityRule getNeutronSecurityRule(String uuid) {
+        if (!neutronSecurityRuleExists(uuid)) {
+            logger.debug("No Security Rules Have Been Defined");
+            return null;
+        }
+        return securityRuleDB.get(uuid);
+    }
+
+    @Override
+    public List<NeutronSecurityRule> getAllNeutronSecurityRules() {
+        Set<NeutronSecurityRule> allSecurityRules = new HashSet<NeutronSecurityRule>();
+        for (Entry<String, NeutronSecurityRule> entry : securityRuleDB.entrySet()) {
+            NeutronSecurityRule securityRule = entry.getValue();
+            allSecurityRules.add(securityRule);
+        }
+        logger.debug("Exiting getSecurityRule, Found {} OpenStackSecurityRule", allSecurityRules.size());
+        List<NeutronSecurityRule> ans = new ArrayList<NeutronSecurityRule>();
+        ans.addAll(allSecurityRules);
+        return ans;
+    }
+
+    @Override
+    public boolean addNeutronSecurityRule(NeutronSecurityRule input) {
+        if (neutronSecurityRuleExists(input.getSecurityRuleUUID())) {
+            return false;
+        }
+        securityRuleDB.putIfAbsent(input.getSecurityRuleUUID(), input);
+        return true;
+    }
+
+    @Override
+    public boolean removeNeutronSecurityRule(String uuid) {
+        if (!neutronSecurityRuleExists(uuid)) {
+            return false;
+        }
+        securityRuleDB.remove(uuid);
+        return true;
+    }
+
+    @Override
+    public boolean updateNeutronSecurityRule(String uuid, NeutronSecurityRule delta) {
+        if (!neutronSecurityRuleExists(uuid)) {
+            return false;
+        }
+        NeutronSecurityRule target = securityRuleDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    @Override
+    public boolean neutronSecurityRuleInUse(String securityRuleUUID) {
+        return !neutronSecurityRuleExists(securityRuleUUID);
+    }
+
+    private void loadConfiguration() {
+        for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+            NeutronSecurityRule nn = (NeutronSecurityRule) conf;
+            securityRuleDB.put(nn.getSecurityRuleUUID(), nn);
+        }
+    }
+
+    @Override
+    public Status saveConfiguration() {
+        return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(securityRuleDB.values()),
+            FILE_NAME);
+    }
+
+    @Override
+    public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+        return ois.readObject();
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupAware.java
new file mode 100644 (file)
index 0000000..0fdf77f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Security Groups needs to implement
+ */
+
+public interface INeutronSecurityGroupAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified security group can be created
+     *
+     * @param securityGroup instance of proposed new Neutron Security Group object
+     * @return integer
+     * the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     * results in the create operation being interrupted and the returned status value reflected in the
+     * HTTP response.
+     */
+    public int canCreateNeutronSecurityGroup(NeutronSecurityGroup securityGroup);
+
+    /**
+     * Services provide this interface method for taking action after a security group has been created
+     *
+     * @param securityGroup instance of new Neutron Security Group object
+     * @return void
+     */
+    public void neutronSecurityGroupCreated(NeutronSecurityGroup securityGroup);
+
+    /**
+     * Services provide this interface method to indicate if the specified security group can be changed using the specified
+     * delta
+     *
+     * @param delta    updates to the security group object using patch semantics
+     * @param original instance of the Neutron Security Group object to be updated
+     * @return integer
+     * the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     * results in the update operation being interrupted and the returned status value reflected in the
+     * HTTP response.
+     */
+    public int canUpdateNeutronSecurityGroup(NeutronSecurityGroup delta, NeutronSecurityGroup original);
+
+    /**
+     * Services provide this interface method for taking action after a security group has been updated
+     *
+     * @param securityGroup instance of modified Neutron Security Group object
+     * @return void
+     */
+    public void neutronSecurityGroupUpdated(NeutronSecurityGroup securityGroup);
+
+    /**
+     * Services provide this interface method to indicate if the specified security group can be deleted
+     *
+     * @param securityGroup instance of the Neutron Security Group object to be deleted
+     * @return integer
+     * the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     * results in the delete operation being interrupted and the returned status value reflected in the
+     * HTTP response.
+     */
+    public int canDeleteNeutronSecurityGroup(NeutronSecurityGroup securityGroup);
+
+    /**
+     * Services provide this interface method for taking action after a security group has been deleted
+     *
+     * @param securityGroup instance of deleted Neutron Security Group object
+     * @return void
+     */
+    public void neutronSecurityGroupDeleted(NeutronSecurityGroup securityGroup);
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupCRUD.java
new file mode 100644 (file)
index 0000000..a408ef9
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB OpenStack Security Group objects
+ */
+
+public interface INeutronSecurityGroupCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     * Security Group object exists
+     *
+     * @param uuid UUID of the Security Group object
+     * @return boolean
+     */
+
+    public boolean neutronSecurityGroupExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * Security Group object exists
+     *
+     * @param uuid UUID of the Security Group object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup.OpenStackSecurity Groups}
+     * OpenStack Security Group class
+     */
+
+    public NeutronSecurityGroup getNeutronSecurityGroup(String uuid);
+
+    /**
+     * Applications call this interface method to return all Security Group objects
+     *
+     * @return List of OpenStackSecurity Groups objects
+     */
+
+    public List<NeutronSecurityGroup> getAllNeutronSecurityGroups();
+
+    /**
+     * Applications call this interface method to add a Security Group object to the
+     * concurrent map
+     *
+     * @param input OpenStackSecurity Group object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addNeutronSecurityGroup(NeutronSecurityGroup input);
+
+    /**
+     * Applications call this interface method to remove a Neutron Security Group object to the
+     * concurrent map
+     *
+     * @param uuid identifier for the security group object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeNeutronSecurityGroup(String uuid);
+
+    /**
+     * Applications call this interface method to edit a Security Group object
+     *
+     * @param uuid  identifier of the security group object
+     * @param delta OpenStackSecurity Group object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateNeutronSecurityGroup(String uuid, NeutronSecurityGroup delta);
+
+    /**
+     * Applications call this interface method to see if a MAC address is in use
+     *
+     * @param uuid identifier of the security group object
+     * @return boolean on whether the Security Groups is already in use
+     */
+
+    public boolean neutronSecurityGroupInUse(String uuid);
+
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleAware.java
new file mode 100644 (file)
index 0000000..ff2a1c4
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods required to be aware of Neutron Security Rules
+ */
+
+public interface INeutronSecurityRuleAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified security rule can be created
+     *
+     * @param securityRule instance of proposed new Neutron Security Rule object
+     * @return integer
+     * the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     * results in the create operation being interrupted and the returned status value reflected in the
+     * HTTP response.
+     */
+    public int canCreateNeutronSecurityRule(NeutronSecurityRule securityRule);
+
+    /**
+     * Services provide this interface method for taking action after a security rule has been created
+     *
+     * @param securityRule instance of new Neutron Security Rule object
+     * @return void
+     */
+    public void neutronSecurityRuleCreated(NeutronSecurityRule securityRule);
+
+    /**
+     * Services provide this interface method to indicate if the specified security rule can be changed using the specified
+     * delta
+     *
+     * @param delta    updates to the security rule object using patch semantics
+     * @param original instance of the Neutron Security Rule object to be updated
+     * @return integer
+     * the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     * results in the update operation being interrupted and the returned status value reflected in the
+     * HTTP response.
+     */
+    public int canUpdateNeutronSecurityRule(NeutronSecurityRule delta, NeutronSecurityRule original);
+
+    /**
+     * Services provide this interface method for taking action after a security rule has been updated
+     *
+     * @param securityRule instance of modified Neutron Security Rule object
+     * @return void
+     */
+    public void neutronSecurityRuleUpdated(NeutronSecurityRule securityRule);
+
+    /**
+     * Services provide this interface method to indicate if the specified security rule can be deleted
+     *
+     * @param securityRule instance of the Neutron Security Rule object to be deleted
+     * @return integer
+     * the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     * results in the delete operation being interrupted and the returned status value reflected in the
+     * HTTP response.
+     */
+    public int canDeleteNeutronSecurityRule(NeutronSecurityRule securityRule);
+
+    /**
+     * Services provide this interface method for taking action after a security rule has been deleted
+     *
+     * @param securityRule instance of deleted Neutron Security Rule object
+     * @return void
+     */
+    public void neutronSecurityRuleDeleted(NeutronSecurityRule securityRule);
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleCRUD.java
new file mode 100644 (file)
index 0000000..73b41c7
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB OpenStack Security Rule objects
+ */
+
+public interface INeutronSecurityRuleCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     * Security Rule object exists
+     *
+     * @param uuid UUID of theSecurity Rule object
+     * @return boolean
+     */
+
+    public boolean neutronSecurityRuleExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * Security Rule object exists
+     *
+     * @param uuid UUID of the security rule object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule.OpenStackNetworks}
+     * OpenStackSecurity Rule class
+     */
+
+    public NeutronSecurityRule getNeutronSecurityRule(String uuid);
+
+    /**
+     * Applications call this interface method to return all Security Rule objects
+     *
+     * @return List of OpenStack SecurityRules objects
+     */
+
+    public List<NeutronSecurityRule> getAllNeutronSecurityRules();
+
+    /**
+     * Applications call this interface method to add a Security Rule object to the
+     * concurrent map
+     *
+     * @param input OpenStack security rule object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addNeutronSecurityRule(NeutronSecurityRule input);
+
+    /**
+     * Applications call this interface method to remove a Neutron Security Rule object to the
+     * concurrent map
+     *
+     * @param uuid identifier for the security rule object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeNeutronSecurityRule(String uuid);
+
+    /**
+     * Applications call this interface method to edit aSecurity Rule object
+     *
+     * @param uuid  identifier of the security rule object
+     * @param delta OpenStackSecurity Rule object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateNeutronSecurityRule(String uuid, NeutronSecurityRule delta);
+
+    /**
+     * Applications call this interface method to see if a MAC address is in use
+     *
+     * @param uuid identifier of the security rule object
+     * @return boolean on whether the macAddress is already associated with a
+     * port or not
+     */
+
+    public boolean neutronSecurityRuleInUse(String uuid);
+
+}
index aebecfa93e18884d243cfb58227124a98de6d429..21cfdb1305060d1bfa24ff32866f1ce0aa8509b5 100644 (file)
@@ -36,4 +36,14 @@ public class NeutronCRUDInterfaces {
         INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o);
         return answer;
     }
-}
+
+    public static INeutronSecurityGroupCRUD getINeutronSecurityGroupCRUD(Object o) {
+        INeutronSecurityGroupCRUD answer = (INeutronSecurityGroupCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityGroupCRUD.class, o);
+        return answer;
+    }
+
+    public static INeutronSecurityRuleCRUD getINeutronSecurityRuleCRUD(Object o) {
+        INeutronSecurityRuleCRUD answer = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, o);
+        return answer;
+    }
+}
\ No newline at end of file
index c8ee4e8cccd3021b3a30deb4eb8ca56b16e17593..680a07453b94b3f56072804b2981006574837f5a 100644 (file)
@@ -61,9 +61,8 @@ public class NeutronPort extends ConfigurationObject implements Serializable {
     @XmlElement (name="tenant_id")
     String tenantID;
 
-    // TODO: add security groups
-    //        @XmlElement (name="security_groups")
-    //        List<String> securityGroups;
+    @XmlElement (name="security_groups")
+    List<NeutronSecurityGroup> securityGroups;
 
     /* this attribute stores the floating IP address assigned to
      * each fixed IP address
@@ -162,6 +161,14 @@ public class NeutronPort extends ConfigurationObject implements Serializable {
         this.tenantID = tenantID;
     }
 
+    public List<NeutronSecurityGroup> getSecurityGroups() {
+        return securityGroups;
+    }
+
+    public void setSecurityGroups(List<NeutronSecurityGroup> securityGroups) {
+        this.securityGroups = securityGroups;
+    }
+
     public NeutronFloatingIP getFloatingIP(String key) {
         if (!floatingIPMap.containsKey(key)) {
             return null;
@@ -259,6 +266,6 @@ public class NeutronPort extends ConfigurationObject implements Serializable {
         return "NeutronPort [portUUID=" + portUUID + ", networkUUID=" + networkUUID + ", name=" + name
                 + ", adminStateUp=" + adminStateUp + ", status=" + status + ", macAddress=" + macAddress
                 + ", fixedIPs=" + fixedIPs + ", deviceID=" + deviceID + ", deviceOwner=" + deviceOwner + ", tenantID="
-                + tenantID + ", floatingIPMap=" + floatingIPMap + "]";
+                + tenantID + ", floatingIPMap=" + floatingIPMap + ", securityGroups=" + securityGroups + "]";
     }
 }
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityGroup.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityGroup.java
new file mode 100644 (file)
index 0000000..0f0a14c
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
+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.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Security Group bindings.
+ * See OpenStack Network API v2.0 Reference for description of
+ * annotated attributes. The current fields are as follows:
+ * <p/>
+ * id                   uuid-str unique ID for the security group.
+ * name                 String name of the security group.
+ * description          String name of the security group.
+ * tenant_id            uuid-str Owner of security rule..
+ * security_group_rules List<NeutronSecurityRule> nested RO in the sec group.
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSecurityGroup extends ConfigurationObject implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(name = "id")
+    String securityGroupUUID;
+
+    @XmlElement(name = "name")
+    String securityGroupName;
+
+    @XmlElement(name = "description")
+    String securityGroupDescription;
+
+    @XmlElement(name = "tenant_id")
+    String securityGroupTenantID;
+
+    @XmlElement(name = "security_group_rules")
+    List<NeutronSecurityRule> neutronSecurityRule;
+
+    List<NeutronPort> neutronPorts;
+
+    public NeutronSecurityGroup() {
+        neutronPorts = new ArrayList<NeutronPort> ();
+        List<NeutronSecurityRule> securityRules;
+
+    }
+
+    public String getSecurityGroupUUID() {
+        return securityGroupUUID;
+    }
+
+    public void setSecurityGroupUUID(String securityGroupUUID) {
+        this.securityGroupUUID = securityGroupUUID;
+    }
+
+    public String getSecurityGroupName() {
+        return securityGroupName;
+    }
+
+    public void setSecurityGroupName(String securityGroupName) {
+        this.securityGroupName = securityGroupName;
+    }
+
+    public String getSecurityGroupDescription() {
+        return securityGroupDescription;
+    }
+
+    public void setSecurityGroupDescription(String securityGroupDescription) {
+        this.securityGroupDescription = securityGroupDescription;
+    }
+
+    public String getSecurityGroupTenantID() {
+        return securityGroupTenantID;
+    }
+
+    public void setSecurityGroupTenantID(String securityGroupTenantID) {
+        this.securityGroupTenantID = securityGroupTenantID;
+    }
+
+    // Rules In Group
+    public List<NeutronSecurityRule> getSecurityRules() {
+        return neutronSecurityRule;
+    }
+
+    public void setSecurityRules(NeutronSecurityRule neutronSecurityRule) {
+        this.neutronSecurityRule = (List<NeutronSecurityRule>) neutronSecurityRule;
+    }
+
+    public NeutronSecurityGroup extractFields(List<String> fields) {
+        NeutronSecurityGroup ans = new NeutronSecurityGroup ();
+        Iterator<String> i = fields.iterator ();
+        while (i.hasNext ()) {
+            String s = i.next ();
+            if (s.equals ("id")) {
+                ans.setSecurityGroupUUID (this.getSecurityGroupUUID ());
+            }
+            if (s.equals ("name")) {
+                ans.setSecurityGroupName (this.getSecurityGroupName ());
+            }
+            if (s.equals ("description")) {
+                ans.setSecurityGroupDescription (this.getSecurityGroupDescription ());
+            }
+            if (s.equals ("tenant_id")) {
+                ans.setSecurityGroupTenantID (this.getSecurityGroupTenantID ());
+            }
+            if (s.equals ("security_group_rules")) {
+                ans.setSecurityRules ((NeutronSecurityRule) this.getSecurityRules ());
+            }
+        }
+        return ans;
+    }
+
+    @Override
+    public String toString() {
+        return "NeutronSecurityGroup{" +
+                "securityGroupUUID='" + securityGroupUUID + '\'' +
+                ", securityGroupName='" + securityGroupName + '\'' +
+                ", securityGroupDescription='" + securityGroupDescription + '\'' +
+                ", securityGroupTenantID='" + securityGroupTenantID + '\'' +
+                ", securityRules=" + neutronSecurityRule + "]";
+    }
+
+    public void initDefaults() {
+        //TODO verify no defaults values are nessecary required.
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityRule.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityRule.java
new file mode 100644 (file)
index 0000000..3fad4fe
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
+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.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * See OpenStack Network API v2.0 Reference for description of
+ * annotated attributes. The current fields are as follows:
+ * <p/>
+ * id                uuid (String) UUID for the security group rule.
+ * security_rule_id  uuid (String) The security group to associate rule.
+ * direction         String Direction the VM traffic  (ingress/egress).
+ * security_group_id The security group to associate rule with.
+ * protocol          String IP Protocol (icmp, tcp, udp, etc).
+ * port_range_min    Integer Port at start of range
+ * port_range_max    Integer Port at end of range
+ * ethertype         String ethertype in L2 packet (IPv4, IPv6, etc)
+ * remote_ip_prefix  String (IP cidr) CIDR for address range.
+ * remote_group_id   uuid-str Source security group to apply to rule.
+ * tenant_id         uuid-str Owner of security rule. Admin only outside tenant.
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSecurityRule extends ConfigurationObject implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(name = "id")
+    String securityRuleUUID;
+
+    @XmlElement(name = "direction")
+    String securityRuleDirection;
+
+    @XmlElement(name = "protocol")
+    String securityRuleProtocol;
+
+    @XmlElement(name = "port_range_min")
+    Integer securityRulePortMin;
+
+    @XmlElement(name = " port_range_max")
+    Integer securityRulePortMax;
+
+    @XmlElement(name = "ethertype")
+    String securityRuleEthertype;
+
+    @XmlElement(name = "remote_ip_prefix")
+    String securityRuleRemoteIpPrefix;
+
+    @XmlElement(name = "remote_group_id")
+    String securityRemoteGroupID;
+
+    @XmlElement(name = "security_group_id")
+    String securityRuleGroupID;
+
+    @XmlElement(name = "tenant_id")
+    String securityRuleTenantID;
+
+    public NeutronSecurityRule() {
+        List<NeutronSecurityRule> securityRules;
+    }
+
+    public String getSecurityRuleUUID() {
+        return securityRuleUUID;
+    }
+
+    public void setSecurityRuleUUID(String securityRuleUUID) {
+        this.securityRuleUUID = securityRuleUUID;
+    }
+
+    public String getSecurityRuleDirection() {
+        return securityRuleDirection;
+    }
+
+    public void setSecurityRuleDirection(String securityRuleDirection) {
+        this.securityRuleDirection = securityRuleDirection;
+    }
+
+    public String getSecurityRuleProtocol() {
+        return securityRuleProtocol;
+    }
+
+    public void setSecurityRuleProtocol(String securityRuleProtocol) {
+        this.securityRuleProtocol = securityRuleProtocol;
+    }
+
+    public Integer getSecurityRulePortMin() {
+        return securityRulePortMin;
+    }
+
+    public void setSecurityRulePortMin(Integer securityRulePortMin) {
+        this.securityRulePortMin = securityRulePortMin;
+    }
+
+    public Integer getSecurityRulePortMax() {
+        return securityRulePortMax;
+    }
+
+    public void setSecurityRulePortMax(Integer securityRulePortMax) {
+        this.securityRulePortMax = securityRulePortMax;
+    }
+
+    public String getSecurityRuleEthertype() {
+        return securityRuleEthertype;
+    }
+
+    public void setSecurityRuleEthertype(String securityRuleEthertype) {
+        this.securityRuleEthertype = securityRuleEthertype;
+    }
+
+    public String getSecurityRuleRemoteIpPrefix() {
+        return securityRuleRemoteIpPrefix;
+    }
+
+    public void setSecurityRuleRemoteIpPrefix(String securityRuleRemoteIpPrefix) {
+        this.securityRuleRemoteIpPrefix = securityRuleRemoteIpPrefix;
+    }
+
+    public String getSecurityRemoteGroupID() {
+        return securityRemoteGroupID;
+    }
+
+    public void setSecurityRemoteGroupID(String securityRemoteGroupID) {
+        this.securityRemoteGroupID = securityRemoteGroupID;
+    }
+
+    public String getSecurityRuleGroupID() {
+        return securityRuleGroupID;
+    }
+
+    public void setSecurityRuleGroupID(String securityRuleGroupID) {
+        this.securityRuleGroupID = securityRuleGroupID;
+    }
+
+    public String getSecurityRuleTenantID() {
+        return securityRuleTenantID;
+    }
+
+    public void setSecurityRuleTenantID(String securityRuleTenantID) {
+        this.securityRuleTenantID = securityRuleTenantID;
+    }
+
+    public NeutronSecurityRule extractFields(List<String> fields) {
+        NeutronSecurityRule ans = new NeutronSecurityRule();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setSecurityRuleUUID(this.getSecurityRuleUUID());
+            }
+            if (s.equals("direction")) {
+                ans.setSecurityRuleDirection(this.getSecurityRuleDirection());
+            }
+            if (s.equals("protocol")) {
+                ans.setSecurityRuleProtocol(this.getSecurityRuleProtocol());
+            }
+            if (s.equals("port_range_min")) {
+                ans.setSecurityRulePortMin(this.getSecurityRulePortMin());
+            }
+            if (s.equals("port_range_max")) {
+                ans.setSecurityRulePortMax(this.getSecurityRulePortMax());
+            }
+            if (s.equals("ethertype")) {
+                ans.setSecurityRuleEthertype(this.getSecurityRuleEthertype());
+            }
+            if (s.equals("remote_ip_prefix")) {
+                ans.setSecurityRuleRemoteIpPrefix(this.getSecurityRuleRemoteIpPrefix());
+            }
+            if (s.equals("remote_group_id")) {
+                ans.setSecurityRemoteGroupID(this.getSecurityRemoteGroupID());
+            }
+            if (s.equals("security_group_id")) {
+                ans.setSecurityRuleGroupID(this.getSecurityRuleGroupID());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setSecurityRuleTenantID(this.getSecurityRuleTenantID());
+            }
+        }
+        return ans;
+    }
+
+    @Override
+    public String toString() {
+        return "NeutronSecurityRule{" +
+            "securityRuleUUID='" + securityRuleUUID + '\'' +
+            ", securityRuleDirection='" + securityRuleDirection + '\'' +
+            ", securityRuleProtocol='" + securityRuleProtocol + '\'' +
+            ", securityRulePortMin=" + securityRulePortMin +
+            ", securityRulePortMax=" + securityRulePortMax +
+            ", securityRuleEthertype='" + securityRuleEthertype + '\'' +
+            ", securityRuleRemoteIpPrefix='" + securityRuleRemoteIpPrefix + '\'' +
+            ", securityRemoteGroupID=" + securityRemoteGroupID +
+            ", securityRuleGroupID='" + securityRuleGroupID + '\'' +
+            ", securityRuleTenantID='" + securityRuleTenantID + '\'' +
+            '}';
+    }
+
+    public void initDefaults() {
+        //TODO verify no defaults values are nessecary required.
+    }
+}
\ No newline at end of file
index 76c39e4294dd05a0ada503edd05d1243c9b436f5..3fe03a2dac8de2f64d9ee2b9796befe72ab0e8b1 100644 (file)
@@ -32,6 +32,8 @@ public class NeutronNorthboundRSApplication extends Application {
         classes.add(NeutronPortsNorthbound.class);
         classes.add(NeutronRoutersNorthbound.class);
         classes.add(NeutronFloatingIPsNorthbound.class);
+        classes.add(NeutronSecurityGroupsNorthbound.class);
+        classes.add(NeutronSecurityRulesNorthbound.class);
         return classes;
     }
 
index 9f24e79ea02ab3fd6fbbd722fe8c86054a3b4470..1a2512fde3c3fd6c689a872f9ee148bba4a67521 100644 (file)
@@ -218,16 +218,6 @@ public class NeutronPortsNorthbound {
             if (portInterface.macInUse(singleton.getMacAddress())) {
                 throw new ResourceConflictException("MAC Address is in use.");
             }
-            Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
-            if (instances != null) {
-                for (Object instance : instances) {
-                    INeutronPortAware service = (INeutronPortAware) instance;
-                    int status = service.canCreatePort(singleton);
-                    if (status < 200 || status > 299) {
-                        return Response.status(status).build();
-                    }
-                }
-            }
             /*
              * if fixed IPs are specified, each one has to have an existing subnet ID
              * that is in the same scoping network as the port.  In addition, if an IP
@@ -260,6 +250,18 @@ public class NeutronPortsNorthbound {
                 }
             }
 
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronPortAware service = (INeutronPortAware) instance;
+                    int status = service.canCreatePort(singleton);
+                    if (status < 200 || status > 299) {
+                        return Response.status(status).build();
+                    }
+                }
+            }
+
+
             // add the port to the cache
             portInterface.addPort(singleton);
             if (instances != null) {
@@ -309,15 +311,7 @@ public class NeutronPortsNorthbound {
                 if (portInterface.macInUse(test.getMacAddress())) {
                     throw new ResourceConflictException("MAC address in use");
                 }
-                if (instances != null) {
-                    for (Object instance : instances) {
-                        INeutronPortAware service = (INeutronPortAware) instance;
-                        int status = service.canCreatePort(test);
-                        if (status < 200 || status > 299) {
-                            return Response.status(status).build();
-                        }
-                    }
-                }
+
                 /*
                  * if fixed IPs are specified, each one has to have an existing subnet ID
                  * that is in the same scoping network as the port.  In addition, if an IP
@@ -351,6 +345,15 @@ public class NeutronPortsNorthbound {
                         }
                     }
                 }
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronPortAware service = (INeutronPortAware) instance;
+                        int status = service.canCreatePort(test);
+                        if (status < 200 || status > 299) {
+                            return Response.status(status).build();
+                        }
+                    }
+                }
             }
 
             //once everything has passed, then we can add to the cache
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupRequest.java
new file mode 100644 (file)
index 0000000..6e779d6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+
+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 NeutronSecurityGroupRequest {
+    /**
+    * See OpenStack Network API v2.0 Reference for a
+    * description of annotated attributes and operations
+    */
+
+    @XmlElement (name = "security_group")
+    NeutronSecurityGroup singletonSecurityGroup;
+
+    @XmlElement (name = "security_groups")
+    List<NeutronSecurityGroup> bulkRequest;
+
+    NeutronSecurityGroupRequest() {
+    }
+
+    NeutronSecurityGroupRequest(List<NeutronSecurityGroup> bulk) {
+        bulkRequest = bulk;
+        singletonSecurityGroup = null;
+    }
+
+    NeutronSecurityGroupRequest(NeutronSecurityGroup group) {
+        singletonSecurityGroup = group;
+    }
+
+    public List<NeutronSecurityGroup> getBulk() {
+        return bulkRequest;
+    }
+
+    public NeutronSecurityGroup getSingleton() {
+        return singletonSecurityGroup;
+    }
+
+    public boolean isSingleton() {
+        return (singletonSecurityGroup != null);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java
new file mode 100644 (file)
index 0000000..5e9a331
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+
+import java.util.ArrayList;
+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.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+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.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Neutron Northbound REST APIs for Security Group.<br>
+ * This class provides REST APIs for managing neutron Security Group
+ * <p/>
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ */
+@Path ("/security-groups")
+public class NeutronSecurityGroupsNorthbound {
+    static final Logger logger = LoggerFactory.getLogger(NeutronSecurityGroupsNorthbound.class);
+
+    private NeutronSecurityGroup extractFields(NeutronSecurityGroup o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Security Groups
+     */
+    @GET
+    @Produces ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 200, condition = "Operation successful"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+
+    public Response listGroups(
+            // return fields
+            @QueryParam ("fields") List<String> fields,
+            // OpenStack security group attributes
+            @QueryParam ("id") String querySecurityGroupUUID,
+            @QueryParam ("name") String querySecurityGroupName,
+            @QueryParam ("description") String querySecurityDescription,
+            @QueryParam ("tenant_id") String querySecurityTenantID,
+            @QueryParam ("limit") String limit,
+            @QueryParam ("marker") String marker,
+            @QueryParam ("page_reverse") String pageReverse
+    ) {
+        INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+
+        if (securityGroupInterface == null) {
+            throw new ServiceUnavailableException("Security Group CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronSecurityGroup> allSecurityGroups = securityGroupInterface.getAllNeutronSecurityGroups();
+        List<NeutronSecurityGroup> ans = new ArrayList<NeutronSecurityGroup>();
+        Iterator<NeutronSecurityGroup> i = allSecurityGroups.iterator();
+        while (i.hasNext()) {
+            NeutronSecurityGroup nsg = i.next();
+            if ((querySecurityGroupUUID == null ||
+                    querySecurityGroupUUID.equals(nsg.getSecurityGroupUUID())) &&
+                    (querySecurityGroupName == null ||
+                            querySecurityGroupName.equals(nsg.getSecurityGroupName())) &&
+                    (querySecurityDescription == null ||
+                            querySecurityDescription.equals(nsg.getSecurityGroupDescription())) &&
+                    (querySecurityTenantID == null ||
+                            querySecurityTenantID.equals(nsg.getSecurityGroupTenantID()))) {
+                if (fields.size() > 0) {
+                    ans.add(extractFields(nsg, fields));
+                } else {
+                    ans.add(nsg);
+                }
+            }
+        }
+        return Response.status(200).entity(
+                new NeutronSecurityGroupRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Security Group
+     */
+
+    @Path ("{securityGroupUUID}")
+    @GET
+    @Produces ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 200, condition = "Operation successful"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response showSecurityGroup(@PathParam ("securityGroupUUID") String securityGroupUUID,
+                                      // return fields
+                                      @QueryParam ("fields") List<String> fields) {
+        INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+        if (securityGroupInterface == null) {
+            throw new ServiceUnavailableException("Security Group CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
+            throw new ResourceNotFoundException("Security Group UUID does not exist.");
+        }
+        if (!fields.isEmpty()) {
+            NeutronSecurityGroup ans = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+            return Response.status(200).entity(
+                    new NeutronSecurityGroupRequest(extractFields(ans, fields))).build();
+        } else {
+            return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build();
+        }
+    }
+
+    /**
+     * Creates new Security Group
+     */
+
+    @POST
+    @Produces ({MediaType.APPLICATION_JSON})
+    @Consumes ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 201, condition = "Created"),
+            @ResponseCode (code = 400, condition = "Bad Request"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 403, condition = "Forbidden"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 409, condition = "Conflict"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response createSecurityGroups(final NeutronSecurityGroupRequest input) {
+        INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+        if (securityGroupInterface == null) {
+            throw new ServiceUnavailableException("Security Group CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        if (input.isSingleton()) {
+            NeutronSecurityGroup singleton = input.getSingleton();
+
+            /*
+             *  Verify that the Security Group doesn't already exist.
+             */
+            if (securityGroupInterface.neutronSecurityGroupExists(singleton.getSecurityGroupUUID())) {
+                throw new BadRequestException("Security Group UUID already exists");
+            }
+
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                    int status = service.canCreateNeutronSecurityGroup(singleton);
+                    if (status < 200 || status > 299) {
+                        return Response.status(status).build();
+                    }
+                }
+            }
+            // Add to Neutron cache
+            securityGroupInterface.addNeutronSecurityGroup(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                    service.neutronSecurityGroupCreated(singleton);
+                }
+            }
+        } else {
+            List<NeutronSecurityGroup> bulk = input.getBulk();
+            Iterator<NeutronSecurityGroup> i = bulk.iterator();
+            HashMap<String, NeutronSecurityGroup> testMap = new HashMap<String, NeutronSecurityGroup>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronSecurityGroup test = i.next();
+
+                /*
+                 *  Verify that the security group doesn't already exist
+                 */
+
+                if (securityGroupInterface.neutronSecurityGroupExists(test.getSecurityGroupUUID())) {
+                    throw new BadRequestException("Security Group UUID already is already created");
+                }
+                if (instances != null) for (Object instance : instances) {
+                    INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                    int status = service.canCreateNeutronSecurityGroup(test);
+                    if ((status < 200) || (status > 299)) return Response.status(status).build();
+                }
+            }
+
+            /*
+             * now, each element of the bulk request can be added to the cache
+             */
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronSecurityGroup test = i.next();
+                securityGroupInterface.addNeutronSecurityGroup(test);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                        service.neutronSecurityGroupCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Security Group
+     */
+
+    @Path ("{securityGroupUUID}")
+    @PUT
+    @Produces ({MediaType.APPLICATION_JSON})
+    @Consumes ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 200, condition = "Operation successful"),
+            @ResponseCode (code = 400, condition = "Bad Request"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 403, condition = "Forbidden"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response updateSecurityGroup(
+            @PathParam ("securityGroupUUID") String securityGroupUUID, final NeutronSecurityGroupRequest input) {
+        INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+        if (securityGroupInterface == null) {
+            throw new ServiceUnavailableException("Security Group CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Security Group exists and there is only one delta provided
+         */
+        if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
+            throw new ResourceNotFoundException("Security Group UUID does not exist.");
+        }
+        if (!input.isSingleton()) {
+            throw new BadRequestException("Only singleton edit supported");
+        }
+        NeutronSecurityGroup delta = input.getSingleton();
+        NeutronSecurityGroup original = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+
+        if (delta.getSecurityGroupUUID() != null ||
+                delta.getSecurityGroupTenantID() != null ||
+                delta.getSecurityGroupName() != null ||
+                delta.getSecurityGroupDescription() != null) {
+            throw new BadRequestException("Attribute edit blocked by Neutron");
+        }
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                int status = service.canUpdateNeutronSecurityGroup(delta, original);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * update the object and return it
+         */
+        securityGroupInterface.updateNeutronSecurityGroup(securityGroupUUID, delta);
+        NeutronSecurityGroup updatedSecurityGroup = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                service.neutronSecurityGroupUpdated(updatedSecurityGroup);
+            }
+        }
+        return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build();
+    }
+
+    /**
+     * Deletes a Security Group
+     */
+
+    @Path ("{securityGroupUUID}")
+    @DELETE
+    @StatusCodes ({
+            @ResponseCode (code = 204, condition = "No Content"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 409, condition = "Conflict"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response deleteSecurityGroup(
+            @PathParam ("securityGroupUUID") String securityGroupUUID) {
+        INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+        if (securityGroupInterface == null) {
+            throw new ServiceUnavailableException("Security Group CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Security Group exists and it isn't currently in use
+         */
+        if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
+            throw new ResourceNotFoundException("Security Group UUID does not exist.");
+        }
+        if (securityGroupInterface.neutronSecurityGroupInUse(securityGroupUUID)) {
+            return Response.status(409).build();
+        }
+        NeutronSecurityGroup singleton = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                int status = service.canDeleteNeutronSecurityGroup(singleton);
+                if ((status < 200) || (status > 299)) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * remove it and return 204 status
+         */
+        securityGroupInterface.removeNeutronSecurityGroup(securityGroupUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+                service.neutronSecurityGroupDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRuleRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRuleRequest.java
new file mode 100644 (file)
index 0000000..b805bd6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+
+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 NeutronSecurityRuleRequest {
+    /**
+     * See OpenStack Network API v2.0 Reference for a
+     * description of annotated attributes and operations
+     */
+
+    @XmlElement(name="security_group_rule")
+    NeutronSecurityRule singletonSecurityRule;
+
+    @XmlElement(name="security_group_rules")
+    List<NeutronSecurityRule> bulkRequest;
+
+    NeutronSecurityRuleRequest() {
+    }
+
+    NeutronSecurityRuleRequest(List<NeutronSecurityRule> bulk) {
+        bulkRequest = bulk;
+        singletonSecurityRule = null;
+    }
+
+    NeutronSecurityRuleRequest(NeutronSecurityRule rule) {
+        singletonSecurityRule = rule;
+    }
+
+    public NeutronSecurityRule getSingleton() {
+        return singletonSecurityRule;
+    }
+
+    public boolean isSingleton() {
+        return (singletonSecurityRule != null);
+    }
+    public List<NeutronSecurityRule> getBulk() {
+        return bulkRequest;
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java
new file mode 100644 (file)
index 0000000..b2c05e0
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+
+import java.util.ArrayList;
+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.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+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.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Neutron Northbound REST APIs for Security Rule.<br>
+ * This class provides REST APIs for managing neutron Security Rule
+ * <p/>
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ */
+
+@Path ("/security-group-rules")
+public class NeutronSecurityRulesNorthbound {
+    static final Logger logger = LoggerFactory.getLogger(NeutronSecurityRulesNorthbound.class);
+
+    private NeutronSecurityRule extractFields(NeutronSecurityRule o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Security Rules
+     */
+    @GET
+    @Produces ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 200, condition = "Operation successful"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response listRules(
+            // return fields
+            @QueryParam ("fields") List<String> fields,
+            // OpenStack security rule attributes
+            @QueryParam ("id") String querySecurityRuleUUID,
+            @QueryParam ("direction") String querySecurityRuleDirection,
+            @QueryParam ("protocol") String querySecurityRuleProtocol,
+            @QueryParam ("port_range_min") Integer querySecurityRulePortMin,
+            @QueryParam ("port_range_max") Integer querySecurityRulePortMax,
+            @QueryParam ("ethertype") String querySecurityRuleEthertype,
+            @QueryParam ("remote_ip_prefix") String querySecurityRuleIpPrefix,
+            @QueryParam ("remote_group_id") String querySecurityRemoteGroupID,
+            @QueryParam ("security_group_id") String querySecurityRuleGroupID,
+            @QueryParam ("tenant_id") String querySecurityRuleTenantID,
+            @QueryParam ("limit") String limit,
+            @QueryParam ("marker") String marker,
+            @QueryParam ("page_reverse") String pageReverse
+    ) {
+        INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+        if (securityRuleInterface == null) {
+            throw new ServiceUnavailableException("Security Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronSecurityRule> allSecurityRules = securityRuleInterface.getAllNeutronSecurityRules();
+        List<NeutronSecurityRule> ans = new ArrayList<NeutronSecurityRule>();
+        Iterator<NeutronSecurityRule> i = allSecurityRules.iterator();
+        while (i.hasNext()) {
+            NeutronSecurityRule nsr = i.next();
+            if ((querySecurityRuleUUID == null ||
+                    querySecurityRuleUUID.equals(nsr.getSecurityRuleUUID())) &&
+                    (querySecurityRuleDirection == null ||
+                            querySecurityRuleDirection.equals(nsr.getSecurityRuleDirection())) &&
+                    (querySecurityRuleProtocol == null ||
+                            querySecurityRuleProtocol.equals(nsr.getSecurityRuleProtocol())) &&
+                    (querySecurityRulePortMin == null ||
+                            querySecurityRulePortMin.equals(nsr.getSecurityRulePortMin())) &&
+                    (querySecurityRulePortMax == null ||
+                            querySecurityRulePortMax.equals(nsr.getSecurityRulePortMax())) &&
+                    (querySecurityRuleEthertype == null ||
+                            querySecurityRuleEthertype.equals(nsr.getSecurityRuleEthertype())) &&
+                    (querySecurityRuleIpPrefix == null ||
+                            querySecurityRuleIpPrefix.equals(nsr.getSecurityRuleRemoteIpPrefix())) &&
+                    (querySecurityRuleGroupID == null ||
+                            querySecurityRuleGroupID.equals(nsr.getSecurityRuleGroupID())) &&
+                    (querySecurityRemoteGroupID == null ||
+                            querySecurityRemoteGroupID.equals(nsr.getSecurityRemoteGroupID())) &&
+                    (querySecurityRuleTenantID == null ||
+                            querySecurityRuleTenantID.equals(nsr.getSecurityRuleTenantID()))) {
+                if (fields.size() > 0) {
+                    ans.add(extractFields(nsr, fields));
+                } else {
+                    ans.add(nsr);
+                }
+            }
+        }
+        return Response.status(200).entity(
+                new NeutronSecurityRuleRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Security Rule
+     */
+
+    @Path ("{securityRuleUUID}")
+    @GET
+    @Produces ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 200, condition = "Operation successful"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response showSecurityRule(@PathParam ("securityRuleUUID") String securityRuleUUID,
+                                     // return fields
+                                     @QueryParam ("fields") List<String> fields) {
+        INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+        if (securityRuleInterface == null) {
+            throw new ServiceUnavailableException("Security Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
+            throw new ResourceNotFoundException("Security Rule UUID does not exist.");
+        }
+        if (!fields.isEmpty()) {
+            NeutronSecurityRule ans = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+            return Response.status(200).entity(
+                    new NeutronSecurityRuleRequest(extractFields(ans, fields))).build();
+        } else {
+            return Response.status(200).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build();
+        }
+    }
+
+    /**
+     * Creates new Security Rule
+     */
+
+    @POST
+    @Produces ({MediaType.APPLICATION_JSON})
+    @Consumes ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 201, condition = "Created"),
+            @ResponseCode (code = 400, condition = "Bad Request"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 403, condition = "Forbidden"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 409, condition = "Conflict"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response createSecurityRules(final NeutronSecurityRuleRequest input) {
+        INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+        if (securityRuleInterface == null) {
+            throw new ServiceUnavailableException("Security Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+        if (securityGroupInterface == null) {
+            throw new ServiceUnavailableException("Security Group CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * Existing entry checks
+        */
+
+        if (input.isSingleton()) {
+            NeutronSecurityRule singleton = input.getSingleton();
+
+            if (securityRuleInterface.neutronSecurityRuleExists(singleton.getSecurityRuleUUID())) {
+                throw new BadRequestException("Security Rule UUID already exists");
+            }
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                    int status = service.canCreateNeutronSecurityRule(singleton);
+                    if ((status < 200) || (status > 299)) {
+                        return Response.status(status).build();
+                    }
+                }
+            }
+
+            // add rule to cache
+            singleton.initDefaults();
+            securityRuleInterface.addNeutronSecurityRule(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                    service.neutronSecurityRuleCreated(singleton);
+                }
+            }
+
+            securityRuleInterface.addNeutronSecurityRule(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                    service.neutronSecurityRuleCreated(singleton);
+                }
+            }
+        } else {
+            List<NeutronSecurityRule> bulk = input.getBulk();
+            Iterator<NeutronSecurityRule> i = bulk.iterator();
+            HashMap<String, NeutronSecurityRule> testMap = new HashMap<String, NeutronSecurityRule>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronSecurityRule test = i.next();
+
+                /*
+                 *  Verify that the security rule doesn't already exist
+                 */
+
+                if (securityRuleInterface.neutronSecurityRuleExists(test.getSecurityRuleUUID())) {
+                    throw new BadRequestException("Security Rule UUID already exists");
+                }
+                if (testMap.containsKey(test.getSecurityRuleUUID())) {
+                    throw new BadRequestException("Security Rule UUID already exists");
+                }
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                        int status = service.canCreateNeutronSecurityRule(test);
+                        if ((status < 200) || (status > 299)) {
+                            return Response.status(status).build();
+                        }
+                    }
+                }
+            }
+
+            /*
+             * now, each element of the bulk request can be added to the cache
+             */
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronSecurityRule test = i.next();
+                securityRuleInterface.addNeutronSecurityRule(test);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                        service.neutronSecurityRuleCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Security Rule
+     */
+
+    @Path ("{securityRuleUUID}")
+    @PUT
+    @Produces ({MediaType.APPLICATION_JSON})
+    @Consumes ({MediaType.APPLICATION_JSON})
+    @StatusCodes ({
+            @ResponseCode (code = 200, condition = "Operation successful"),
+            @ResponseCode (code = 400, condition = "Bad Request"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 403, condition = "Forbidden"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response updateSecurityRule(
+            @PathParam ("securityRuleUUID") String securityRuleUUID, final NeutronSecurityRuleRequest input) {
+        INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+        if (securityRuleInterface == null) {
+            throw new ServiceUnavailableException("Security Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Security Rule exists and there is only one delta provided
+         */
+        if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
+            throw new ResourceNotFoundException("Security Rule UUID does not exist.");
+        }
+        if (!input.isSingleton()) {
+            throw new BadRequestException("Only singleton edit supported");
+        }
+        NeutronSecurityRule delta = input.getSingleton();
+        NeutronSecurityRule original = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+
+        /*
+         * updates restricted by Neutron
+         *
+         */
+        if (delta.getSecurityRuleUUID() != null ||
+                delta.getSecurityRuleDirection() != null ||
+                delta.getSecurityRuleProtocol() != null ||
+                delta.getSecurityRulePortMin() != null ||
+                delta.getSecurityRulePortMax() != null ||
+                delta.getSecurityRuleEthertype() != null ||
+                delta.getSecurityRuleRemoteIpPrefix() != null ||
+                delta.getSecurityRuleGroupID() != null ||
+                delta.getSecurityRemoteGroupID() != null ||
+                delta.getSecurityRuleTenantID() != null) {
+            throw new BadRequestException("Attribute edit blocked by Neutron");
+        }
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                int status = service.canUpdateNeutronSecurityRule(delta, original);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * update the object and return it
+         */
+        securityRuleInterface.updateNeutronSecurityRule(securityRuleUUID, delta);
+        NeutronSecurityRule updatedSecurityRule = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                service.neutronSecurityRuleUpdated(updatedSecurityRule);
+            }
+        }
+        return Response.status(200).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build();
+    }
+
+    /**
+     * Deletes a Security Rule
+     */
+
+    @Path ("{securityRuleUUID}")
+    @DELETE
+    @StatusCodes ({
+            @ResponseCode (code = 204, condition = "No Content"),
+            @ResponseCode (code = 401, condition = "Unauthorized"),
+            @ResponseCode (code = 404, condition = "Not Found"),
+            @ResponseCode (code = 409, condition = "Conflict"),
+            @ResponseCode (code = 501, condition = "Not Implemented")})
+    public Response deleteSecurityRule(
+            @PathParam ("securityRuleUUID") String securityRuleUUID) {
+        INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+        if (securityRuleInterface == null) {
+            throw new ServiceUnavailableException("Security Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Security Rule exists and it isn't currently in use
+         */
+        if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
+            throw new ResourceNotFoundException("Security Rule UUID does not exist.");
+        }
+        if (securityRuleInterface.neutronSecurityRuleInUse(securityRuleUUID)) {
+            return Response.status(409).build();
+        }
+        NeutronSecurityRule singleton = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                int status = service.canDeleteNeutronSecurityRule(singleton);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * remove it and return 204 status
+         */
+        securityRuleInterface.removeNeutronSecurityRule(securityRuleUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+                service.neutronSecurityRuleDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
\ No newline at end of file
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>