Merge "BUG-1200 changed help for agentpath && added comment describing functions.sh"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 4 Jul 2014 14:43:12 +0000 (14:43 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 4 Jul 2014 14:43:12 +0000 (14:43 +0000)
691 files changed:
features/base/pom.xml
features/base/src/main/resources/features.xml
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPReply.java
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ServiceReferenceMXBean.java [moved from opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java with 87% similarity]
opendaylight/config/config-manager/pom.xml
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java
opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/ConfigSnapshotHolder.java
opendaylight/config/config-persister-file-xml-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/xml/model/ConfigSnapshot.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java
opendaylight/config/netconf-config-dispatcher/pom.xml
opendaylight/config/pom.xml
opendaylight/config/threadpool-config-impl/pom.xml
opendaylight/config/yang-jmx-generator-plugin/pom.xml
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ConfigConstants.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/ModuleUtil.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ServiceInterfaceEntryTest.java
opendaylight/config/yang-test-plugin/pom.xml
opendaylight/config/yang-test/pom.xml
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/custom.properties
opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/startup.properties
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml [new file with mode: 0644]
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/02-clustering.xml [deleted file]
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/03-toaster-sample.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/99-netconf-connector.xml
opendaylight/distribution/opendaylight/src/main/resources/run.bat
opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.java
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/ToSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyMapping.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/MDFlowMappingTest.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/topology/test/TopologyMappingTest.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryOperation.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeFactory.java with 53% similarity]
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-match-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-port-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-table-types.yang
opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang [deleted file]
opendaylight/md-sal/pom.xml
opendaylight/md-sal/remoterpc-routingtable/implementation/pom.xml [deleted file]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/pom.xml [deleted file]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/pom.xml [deleted file]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/RouteIdentifierImpl.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/Router.java [deleted file]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml [deleted file]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingDataBroker.java [deleted file]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataChangeListener.java [moved from opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingDataChangeListener.java with 87% similarity]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ReadOnlyTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ReadTransaction.java [moved from opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingDataReadTransaction.java with 88% similarity]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ReadWriteTransaction.java [moved from opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingDataReadWriteTransaction.java with 64% similarity]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/WriteTransaction.java [moved from opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingDataWriteTransaction.java with 74% similarity]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcConsumerRegistry.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataBrokerService.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataChangeListener.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataModificationTransaction.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataProviderService.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/DataRefresher.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/RuntimeDataProvider.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/data/SynchronizedTransaction.java
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingAsyncDataBrokerImplModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingAsyncDataBrokerImplModuleFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingBrokerImplModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingBrokerImplModuleFactory.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/DataBrokerImplModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/DataBrokerImplModuleFactory.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/ForwardedCompatibleDataBrokerImplModuleFactory.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractWriteTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataReadTransactionImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataReadWriteTransactionImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataWriteTransactionImpl.java [new file with mode: 0644]
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/BindingTranslatedTransactionChain.java [new file with mode: 0644]
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/md/sal/binding/impl/ForwardedBindingDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RootBindingAwareBroker.java
opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-md-sal-binding.yang
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ListProcessingAndOrderingTest.java
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-binding-it/src/test/resources/controller.xml
opendaylight/md-sal/sal-binding-util/src/main/java/org/opendaylight/controller/md/sal/binding/util/AbstractBindingSalConsumerInstance.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataBroker.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeEvent.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeListener.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataTransactionFactory.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadOnlyTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadTransaction.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadWriteTransaction.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncTransaction.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeListener.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangePublisher.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandlerRegistration.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModification.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModificationTransactionFactory.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataProvider.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataProvisionService.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataReader.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChange.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutedRegistration.java
opendaylight/md-sal/sal-common-impl/pom.xml
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-impl/src/test/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-impl/src/test/resources/normalization-test.yang [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/pom.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStore.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ListenerRegistrationProxy.java [deleted file]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionChainProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/AbortTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/AbortTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CanCommitTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CanCommitTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseDataChangeListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseDataChangeListenerRegistrationReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChain.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChainReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CommitTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CommitTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java [moved from opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcServer.java with 57% similarity]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChain.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChainReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataChanged.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimary.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ForwardedCommitTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ModifyData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PreCommitTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PreCommitTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryFound.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryNotFound.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListenerReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/UpdateSchemaContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/AbstractModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/CompositeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/DeleteModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/ImmutableCompositeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/MergeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/Modification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/WriteModification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedDataStoreProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxyTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxyTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardManagerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimaryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/AbstractModificationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/DeleteModificationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MergeModificationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModificationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/WriteModificationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategyTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactoryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/DoNothingActor.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockActorContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/TestModel.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/application.conf [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/odl-datastore-test.yang [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataBroker.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadOnlyTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMTransactionChain.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataBrokerService.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataChangeListener.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataModificationTransaction.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataStore.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataValidator.java
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/DomBrokerImplModule.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModuleFactory.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModule.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModuleFactory.java
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/AbstractDOMForwardedCompositeTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/AbstractDOMForwardedTransactionFactory.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadOnlyTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedWriteTransaction.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/BackwardsCompatibleTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ConflictingModificationAppliedException.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTree.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidate.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeCandidateNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeModification.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataTreeSnapshot.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataValidationFailedException.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/IncorrectDataStructureException.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ModificationType.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreTreeNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreUtils.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AbstractDataTreeCandidate.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/Version.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.java
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/ProviderContextImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.java
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/AbstractBrokerServiceProxy.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DOMDataBrokerProxy.java
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
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangSchemaUtils.java
opendaylight/md-sal/sal-dom-broker/src/main/yang/opendaylight-dom-broker-impl.yang
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerPerformanceTest.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMTransactionChainTest.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DataNormalizerTest.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/TestModel.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java [deleted file]
opendaylight/md-sal/sal-dom-spi/pom.xml
opendaylight/md-sal/sal-dom-spi/src/main/yang/opendaylight-config-dom-datastore.yang [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/src/main/yang/opendaylight-operational-dom-datastore.yang [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/pom.xml [moved from opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml with 57% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModuleFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModuleFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDOMStoreTransaction.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDOMStoreTransaction.java with 100% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java with 100% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DOMImmutableDataChangeEvent.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DOMImmutableDataChangeEvent.java with 100% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeListenerRegistration.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeListenerRegistration.java with 100% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java with 95% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java with 97% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java with 96% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java with 96% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java with 92% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerTree.java [moved from opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerTree.java with 96% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/TestModel.java [new file with mode: 0644]
opendaylight/md-sal/sal-inmemory-datastore/src/test/resources/odl-datastore-test.yang [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/pom.xml
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/listener/NetconfDeviceCommunicator.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceCommitHandler.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceDataReader.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceTwoPhaseCommitTransaction.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/README-FIRST [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/run.sh [new file with mode: 0755]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/registration/ListenerRegistrationMessages.java [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/shard/ShardManagerMessages.java [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/transaction/ShardTransactionChainMessages.java [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/transaction/ShardTransactionMessages.java [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ListenerRegistration.proto [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardManager.proto [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransaction.proto [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransactionChain.proto [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/messages/ShardManagerMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModule.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModuleFactory.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/CapturedMessageHandler.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImpl.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandler.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandler.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketPair.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/MessageWrapper.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/util/XmlUtils.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/yang/odl-sal-dom-rpc-remote-cfg.yang [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImplTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/MockRoutingTable.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProviderTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SerilizationTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImplTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandlerTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/MessagingUtil.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/RemoteServerTestClient.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/AddFlow.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/FourSimpleChildren.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/logback-test.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/FourSimpleChildren.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidCompositeChild.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidSimpleChild.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleChild.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleOneCompositeChild.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoCompositeChildren.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoSimpleChildren.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/pom.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/RouterTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/controller.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/logback.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqrouter/rest/Router.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml [deleted file]
opendaylight/md-sal/sal-rest-connector/pom.xml
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/JsonReader.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/RestUtil.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfDocumentedExceptionMapper.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/XmlReader.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/EmptyNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java
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/impl/SimpleNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServerHandler.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonBasicDataTypesTest.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/xml/test/CnSnToXmlTest.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/DummyFuture.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestDeleteOperationTest.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/RestPutOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.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/test/structures/LstItem.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/simple-data-types.yang
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/xml/data.xml
opendaylight/md-sal/sal-rest-docgen/pom.xml
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ModelGenerator.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/mountpoints/MountPointSwagger.java
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/index.html
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java
opendaylight/md-sal/samples/l2switch/implementation/pom.xml
opendaylight/md-sal/samples/toaster-it/pom.xml
opendaylight/md-sal/samples/toaster-it/src/test/resources/controller.xml
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/sample/toaster/provider/OpendaylightToaster.java
opendaylight/md-sal/samples/toaster-provider/src/main/yang/toaster-provider-impl.yang
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java
opendaylight/md-sal/topology-lldp-discovery/pom.xml
opendaylight/md-sal/topology-manager/pom.xml
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/toxml/ObjectNameAttributeWritingStrategy.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/ModuleConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java
opendaylight/netconf/config-netconf-connector/src/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/Commit.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.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/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/operations/runtimerpc/RuntimeRpcElementResolved.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshotImpl.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/TestingExceptionHandler.java
opendaylight/netconf/netconf-api/pom.xml
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/xml/XmlNetconfConstants.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java with 86% similarity]
opendaylight/netconf/netconf-api/src/test/java/org/opendaylight/controller/netconf/api/NetconfDocumentedExceptionTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/README [new file with mode: 0644]
opendaylight/netconf/netconf-cli/README_ODL [new file with mode: 0644]
opendaylight/netconf/netconf-cli/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/Cli.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/CommandArgHandlerRegistry.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/Main.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/NetconfDeviceConnectionHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/NetconfDeviceConnectionManager.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/SchemaContextRegistry.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/AbstractCommand.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/Command.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandConstants.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandDispatcher.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandInvocationException.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/input/Input.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/input/InputDefinition.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Close.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Connect.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Disconnect.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Help.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/output/Output.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/output/OutputDefinition.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/remote/RemoteCommand.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/BaseConsoleContext.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleContext.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleIO.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleIOImpl.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/IOUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/AbstractReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/GenericListEntryReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/Reader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/ReadingException.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/ConfigReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/EditContentReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/FilterReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/PasswordReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/AnyXmlReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/BasicDataHolderReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ChoiceReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ContainerReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/DecisionReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/GenericListReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/GenericReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/LeafListEntryReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/LeafReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ListEntryReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/SeparatedNodes.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/UnionTypeReader.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/OutFormatter.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/WriteException.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/Writer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/custom/DataWriter.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/AbstractWriter.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/AugmentationNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/ChoiceNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/CliOutputFromNormalizedNodeSerializerFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/CompositeNodeWriter.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/ContainerNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafSetEntryNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafSetNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/MapEntryNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/MapNodeCliSerializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NodeCliSerializerDispatcher.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NormalizedNodeWriter.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/resources/logback.xml [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/resources/schema/common/ietf-inet-types.yang [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/resources/schema/common/netconf-cli-ext.yang [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/resources/schema/local/netconf-cli.yang [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/main/resources/schema/remote/ietf-netconf.yang [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/ConsoleIOTestImpl.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/NetconfCliTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/ValueForMessages.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/io/IOUtilTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/resources/schema-context/ietf-inet-types.yang [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/resources/schema-context/ietf-netconf.yang [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/resources/schema-context/model1.yang [new file with mode: 0644]
opendaylight/netconf/netconf-cli/src/test/resources/schema-context/model2.yang [new file with mode: 0644]
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-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/AbstractNetconfSessionNegotiator.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/exi/NetconfStartExiMessage.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelInputStream.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/VirtualSocketException.java
opendaylight/netconf/netconf-ssh/pom.xml
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/Handshaker.java
opendaylight/netconf/netconf-tcp/pom.xml
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/mapping/AbstractNetconfOperation.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/pom.xml
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronObject.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronNetwork.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/NeutronRouter.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java
opendaylight/northbound/commons/pom.xml
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/NorthboundApplication.java
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Accessor.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/CompareExpression.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Expression.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/ExpressionBuilder.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/IteratableTypeInfo.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/LogicalExpression.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Query.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContext.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContextImpl.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContextProvider.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryImpl.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/TypeInfo.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Visitor.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/WrapperTypeInfo.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/javacc/fiql.jj [new file with mode: 0644]
opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/BookBean.java [new file with mode: 0644]
opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/ExpresssionTest.java [new file with mode: 0644]
opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/Library.java [new file with mode: 0644]
opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/PersonBean.java [new file with mode: 0644]
opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/QueryContextTest.java [new file with mode: 0644]
opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/ReviewBean.java [new file with mode: 0644]
opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/XMLAccessorTypeTest.java [new file with mode: 0644]
opendaylight/northbound/commons/src/test/resources/logback.xml [moved from opendaylight/md-sal/remoterpc-routingtable/integrationtest/src/test/resources/logback.xml with 61% similarity]
opendaylight/northbound/connectionmanager/pom.xml
opendaylight/northbound/connectionmanager/src/main/java/org/opendaylight/controller/connectionmanager/northbound/ConnectionManagerNorthbound.java
opendaylight/northbound/containermanager/pom.xml
opendaylight/northbound/containermanager/src/main/java/org/opendaylight/controller/containermanager/northbound/ContainerManagerNorthbound.java
opendaylight/northbound/containermanager/src/main/java/org/opendaylight/controller/containermanager/northbound/ContainerManagerNorthboundRSApplication.java
opendaylight/northbound/controllermanager/pom.xml
opendaylight/northbound/controllermanager/src/main/java/org/opendaylight/controller/controllermanager/northbound/ControllerManagerNorthbound.java
opendaylight/northbound/flowprogrammer/pom.xml
opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java
opendaylight/northbound/hosttracker/pom.xml
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/INeutronRequest.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworkRequest.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortRequest.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/NeutronSubnetRequest.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java [deleted file]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedRequestFactory.java [new file with mode: 0644]
opendaylight/northbound/staticrouting/pom.xml
opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java
opendaylight/northbound/statistics/pom.xml
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java
opendaylight/northbound/subnets/pom.xml
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthbound.java
opendaylight/northbound/swagger-ui/pom.xml [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/index.html [new file with mode: 0644]
opendaylight/northbound/switchmanager/pom.xml
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java
opendaylight/northbound/topology/pom.xml
opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketMuxDemux.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6Match.java
opendaylight/protocol_plugins/openflow/src/test/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6MatchTest.java [new file with mode: 0644]
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IEEE8021Q.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IEEE8021QTest.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java
pom.xml

index 922b2d6bdfbd7652df204f2e70597a11fc0a76ac..d925f51b948cfe444a77a5875546e6986ec5ca26 100644 (file)
       </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>
index 5677ab66d0bf971e43541583ce6b5955a57906e0..60286175c18e0a6455dedcc19f23018216b406dd 100644 (file)
@@ -73,7 +73,7 @@
       <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:org.apache.commons/commons-lang3/${commons.lang3.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: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>
index a6ee60f65d14b5f47b6f7a6cc2db9331f6847d51..1a446b83db92fe1a690e8ac94f181b6bf75705ac 100644 (file)
@@ -23,14 +23,17 @@ public class ARPReply extends ARPEvent {
     private final byte[] tMac;
     private final byte[] sMac;
     private final InetAddress sIP;
+    private final short vlan;
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = super.hashCode();
+        result = prime * result + ((port == null) ? 0 : port.hashCode());
         result = prime * result + ((sIP == null) ? 0 : sIP.hashCode());
         result = prime * result + Arrays.hashCode(sMac);
         result = prime * result + Arrays.hashCode(tMac);
+        result = prime * result + vlan;
         return result;
     }
 
@@ -39,13 +42,20 @@ public class ARPReply extends ARPEvent {
         if (this == obj) {
             return true;
         }
-        if (obj == null) {
+        if (!super.equals(obj)) {
             return false;
         }
         if (!(obj instanceof ARPReply)) {
             return false;
         }
         ARPReply other = (ARPReply) obj;
+        if (port == null) {
+            if (other.port != null) {
+                return false;
+            }
+        } else if (!port.equals(other.port)) {
+            return false;
+        }
         if (sIP == null) {
             if (other.sIP != null) {
                 return false;
@@ -59,23 +69,28 @@ public class ARPReply extends ARPEvent {
         if (!Arrays.equals(tMac, other.tMac)) {
             return false;
         }
+        if (vlan != other.vlan) {
+            return false;
+        }
         return true;
     }
 
-    public ARPReply(NodeConnector port, InetAddress sIP, byte[] sMAC, InetAddress tIP, byte[] tMAC) {
+    public ARPReply(NodeConnector port, InetAddress sIP, byte[] sMAC, InetAddress tIP, byte[] tMAC, short vlan) {
         super(tIP);
         this.tMac = tMAC;
         this.sIP = sIP;
         this.sMac = sMAC;
         this.port = port;
+        this.vlan = vlan;
     }
 
-    public ARPReply(InetAddress tIP, byte[] tMAC) {
+    public ARPReply(InetAddress tIP, byte[] tMAC, short vlan) {
         super(tIP);
         this.tMac = tMAC;
         this.sIP = null;
         this.sMac = null;
         this.port = null;
+        this.vlan = vlan;
     }
 
     public byte[] getTargetMac() {
@@ -94,6 +109,10 @@ public class ARPReply extends ARPEvent {
         return port;
     }
 
+    public short getVlan() {
+        return vlan;
+    }
+
     /*
      * (non-Javadoc)
      *
@@ -122,6 +141,10 @@ public class ARPReply extends ARPEvent {
             builder.append("sIP=")
                     .append(sIP);
         }
+        if (vlan != 0) {
+            builder.append(", vlan=")
+            .append(vlan);
+        }
         builder.append("]");
         return builder.toString();
     }
index e5491824397c1678b26b819b4e2691d0295f95a6..fe456f3f8ebe6f6237352cb09f5b6a7dc8056398 100644 (file)
@@ -49,12 +49,12 @@ import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.packet.ARP;
 import org.opendaylight.controller.sal.packet.Ethernet;
 import org.opendaylight.controller.sal.packet.IDataPacketService;
+import org.opendaylight.controller.sal.packet.IEEE8021Q;
 import org.opendaylight.controller.sal.packet.IListenDataPacket;
 import org.opendaylight.controller.sal.packet.IPv4;
 import org.opendaylight.controller.sal.packet.Packet;
 import org.opendaylight.controller.sal.packet.PacketResult;
 import org.opendaylight.controller.sal.packet.RawPacket;
-import org.opendaylight.controller.sal.routing.IRouting;
 import org.opendaylight.controller.sal.utils.EtherTypes;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.NetUtils;
@@ -96,7 +96,6 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     private ISwitchManager switchManager;
     private ITopologyManager topologyManager;
     private IDataPacketService dataPacketService;
-    private IRouting routing;
     private IClusterContainerServices clusterContainerService;
     private IConnectionManager connectionManager;
     private Set<IfHostListener> hostListeners = new CopyOnWriteArraySet<IfHostListener>();
@@ -182,7 +181,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
     }
 
-    protected void sendARPReply(NodeConnector p, byte[] sMAC, InetAddress sIP, byte[] tMAC, InetAddress tIP) {
+    protected void sendARPReply(NodeConnector p, byte[] sMAC, InetAddress sIP, byte[] tMAC, InetAddress tIP, short vlan) {
         byte[] senderIP = sIP.getAddress();
         byte[] targetIP = tIP.getAddress();
         ARP arp = createARP(ARP.REPLY, sMAC, senderIP, tMAC, targetIP);
@@ -193,7 +192,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                     sIP, HexEncode.bytesToHexString(tMAC), tIP, p);
         }
 
-        Ethernet ethernet = createEthernet(sMAC, tMAC, arp);
+        Ethernet ethernet = createEthernet(sMAC, tMAC, arp, vlan);
 
         RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet);
         destPkt.setOutgoingNodeConnector(p);
@@ -201,26 +200,24 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         this.dataPacketService.transmitDataPacket(destPkt);
     }
 
-    private void logArpPacket(ARP pkt, NodeConnector p) {
+    private void logArpPacket(ARP pkt, NodeConnector p, short vlan) {
         try {
-            if (pkt.getOpCode() == ARP.REQUEST) {
-                log.trace("Received Arp Request with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {}", HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()),
-                        InetAddress.getByAddress(pkt.getSenderProtocolAddress()), HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()),
-                        InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p);
-            } else if(pkt.getOpCode() == ARP.REPLY) {
-                log.trace("Received Arp Reply with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {}", HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()),
-                        InetAddress.getByAddress(pkt.getSenderProtocolAddress()), HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()),
-                        InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p);
-            }
-        } catch(UnknownHostException e) {
+            log.trace("Received Arp {} with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {} {}",
+                    ((pkt.getOpCode() == ARP.REQUEST) ? "Request" : "Reply"),
+                    HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()),
+                    InetAddress.getByAddress(pkt.getSenderProtocolAddress()),
+                    HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()),
+                    InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p, (vlan != 0 ? "on vlan " + vlan : ""));
+
+        } catch (UnknownHostException e) {
             log.warn("Illegal Ip Address in the ARP packet", e);
         }
     }
 
-    protected void handleARPPacket(Ethernet eHeader, ARP pkt, NodeConnector p) {
+    protected void handleARPPacket(Ethernet eHeader, ARP pkt, NodeConnector p, short vlan) {
 
         if(log.isTraceEnabled()) {
-            logArpPacket(pkt, p);
+            logArpPacket(pkt, p, vlan);
         }
 
         byte[] sourceMAC = eHeader.getSourceMACAddress();
@@ -264,7 +261,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         HostNodeConnector requestor = null;
         if (NetUtils.isUnicastMACAddr(sourceMAC) && p.getNode() != null) {
             try {
-                requestor = new HostNodeConnector(sourceMAC, sourceIP, p, subnet.getVlan());
+                requestor = new HostNodeConnector(sourceMAC, sourceIP, p, vlan);
             } catch (ConstructionException e) {
                 log.debug("Received ARP packet with invalid MAC: {}", HexEncode.bytesToHexString(sourceMAC));
                 return;
@@ -294,7 +291,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
             // the true value indicates we should generate replies to requestors
             // across the cluster
             log.trace("Received ARP reply packet from {}, reply to all requestors.", sourceIP);
-            arpRequestReplyEvent.put(new ARPReply(sourceIP, sourceMAC), true);
+            arpRequestReplyEvent.put(new ARPReply(sourceIP, sourceMAC, vlan), true);
             return;
         }
 
@@ -315,11 +312,11 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                     log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}",
                             HexEncode.bytesToHexString(getControllerMAC()));
                 }
-                sendARPReply(p, getControllerMAC(), targetIP, pkt.getSenderHardwareAddress(), sourceIP);
+                sendARPReply(p, getControllerMAC(), targetIP, pkt.getSenderHardwareAddress(), sourceIP, vlan);
             } else {
                 log.trace("Received non-local ARP req. for default gateway. Raising reply event");
                 arpRequestReplyEvent.put(
-                        new ARPReply(p, targetIP, getControllerMAC(), sourceIP, pkt.getSenderHardwareAddress()), false);
+                        new ARPReply(p, targetIP, getControllerMAC(), sourceIP, pkt.getSenderHardwareAddress(), vlan), false);
             }
             return;
         }
@@ -353,10 +350,10 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                 log.trace("Received ARP req. for known host {}, sending reply...", targetIP);
                 if (connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL) {
                     sendARPReply(p, host.getDataLayerAddressBytes(), host.getNetworkAddress(),
-                            pkt.getSenderHardwareAddress(), sourceIP);
+                            pkt.getSenderHardwareAddress(), sourceIP, vlan);
                 } else {
                     arpRequestReplyEvent.put(new ARPReply(p, host.getNetworkAddress(), host.getDataLayerAddressBytes(),
-                            sourceIP, pkt.getSenderHardwareAddress()), false);
+                            sourceIP, pkt.getSenderHardwareAddress(), vlan), false);
                 }
             } else {
                 /*
@@ -404,7 +401,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
             }
 
             byte[] destMACAddress = NetUtils.getBroadcastMACAddr();
-            Ethernet ethernet = createEthernet(getControllerMAC(), destMACAddress, arp);
+            Ethernet ethernet = createEthernet(getControllerMAC(), destMACAddress, arp, (short)0);
 
             // TODO For now send port-by-port, see how to optimize to
             // send to multiple ports at once
@@ -416,9 +413,9 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     }
 
     /**
-     * Send a unicast ARP Request to the known host on a specific switch/port as
-     * defined in the host. The sender IP is the networkAddress of the subnet
-     * The sender MAC is the controller's MAC
+     * Send a unicast ARP Request to the known host on specific (switch/port,
+     * vlan) as defined in the host. The sender IP is the networkAddress of the
+     * subnet The sender MAC is the controller's MAC
      */
     protected void sendUcastARPRequest(HostNodeConnector host, Subnet subnet) {
         log.trace("sendUcastARPRequest host:{} subnet:{}", host, subnet);
@@ -440,7 +437,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                     outPort);
         }
 
-        Ethernet ethernet = createEthernet(getControllerMAC(), targetMAC, arp);
+        Ethernet ethernet = createEthernet(getControllerMAC(), targetMAC, arp, host.getVlan());
 
         RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet);
         destPkt.setOutgoingNodeConnector(outPort);
@@ -498,7 +495,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
      * @param pkt
      * @param p
      */
-    protected void handlePuntedIPPacket(IPv4 pkt, NodeConnector p) {
+    protected void handlePuntedIPPacket(IPv4 pkt, NodeConnector p, short vlan) {
 
         InetAddress dIP = NetUtils.getInetAddress(pkt.getDestinationAddress());
         if (dIP == null) {
@@ -653,13 +650,19 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         log.trace("Received a frame of size: {}", inPkt.getPacketData().length);
         Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
         if (formattedPak instanceof Ethernet) {
-            Object nextPak = formattedPak.getPayload();
+            Packet nextPak = formattedPak.getPayload();
+            short vlan = 0;
+            if (nextPak instanceof IEEE8021Q) {
+                vlan = ((IEEE8021Q) nextPak).getVid();
+                log.trace("Moved after the dot1Q header");
+                nextPak = ((IEEE8021Q) nextPak).getPayload();
+            }
             if (nextPak instanceof IPv4) {
                 log.trace("Handle IP packet: {}", formattedPak);
-                handlePuntedIPPacket((IPv4) nextPak, inPkt.getIncomingNodeConnector());
+                handlePuntedIPPacket((IPv4) nextPak, inPkt.getIncomingNodeConnector(), vlan);
             } else if (nextPak instanceof ARP) {
                 log.trace("Handle ARP packet: {}", formattedPak);
-                handleARPPacket((Ethernet) formattedPak, (ARP) nextPak, inPkt.getIncomingNodeConnector());
+                handleARPPacket((Ethernet) formattedPak, (ARP) nextPak, inPkt.getIncomingNodeConnector(), vlan);
             }
         }
         return PacketResult.IGNORED;
@@ -680,12 +683,21 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         return arp;
     }
 
-    private Ethernet createEthernet(byte[] sourceMAC, byte[] targetMAC, ARP arp) {
+    private Ethernet createEthernet(byte[] sourceMAC, byte[] targetMAC, ARP arp, short vlan) {
         Ethernet ethernet = new Ethernet();
         ethernet.setSourceMACAddress(sourceMAC);
         ethernet.setDestinationMACAddress(targetMAC);
-        ethernet.setEtherType(EtherTypes.ARP.shortValue());
-        ethernet.setPayload(arp);
+        if (vlan == 0) {
+            ethernet.setEtherType(EtherTypes.ARP.shortValue());
+            ethernet.setPayload(arp);
+        } else {
+            IEEE8021Q dot1q = new IEEE8021Q();
+            dot1q.setVid(vlan);
+            dot1q.setEtherType(EtherTypes.ARP.shortValue());
+            dot1q.setPayload(arp);
+            ethernet.setEtherType(EtherTypes.VLANTAGGED.shortValue());
+            ethernet.setPayload(dot1q);
+        }
         return ethernet;
     }
 
@@ -731,7 +743,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
     }
 
-    private void generateAndSendReply(InetAddress sourceIP, byte[] sourceMAC) {
+    private void generateAndSendReply(InetAddress sourceIP, byte[] sourceMAC, short vlan) {
         if (log.isTraceEnabled()) {
             log.trace("generateAndSendReply called with params sourceIP:{} sourceMAC:{}", sourceIP,
                     HexEncode.bytesToHexString(sourceMAC));
@@ -745,13 +757,14 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         for (HostNodeConnector host : hosts) {
             if (log.isTraceEnabled()) {
                 log.trace(
-                        "Sending ARP Reply with src {}/{}, target {}/{}",
+                        "Sending ARP Reply with src {}/{}, target {}/{} {}",
                         new Object[] { HexEncode.bytesToHexString(sourceMAC), sourceIP,
-                                HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host.getNetworkAddress() });
+                                HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host.getNetworkAddress(),
+                                (vlan != 0 ? "on vlan " + vlan : "") });
             }
             if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL) {
                 sendARPReply(host.getnodeConnector(), sourceMAC, sourceIP, host.getDataLayerAddressBytes(),
-                        host.getNetworkAddress());
+                        host.getNetworkAddress(), vlan);
             } else {
                 /*
                  * In the remote event a requestor moved to another controller
@@ -760,7 +773,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                  */
                 arpRequestReplyEvent.put(
                         new ARPReply(host.getnodeConnector(), sourceIP, sourceMAC, host.getNetworkAddress(), host
-                                .getDataLayerAddressBytes()), false);
+                                .getDataLayerAddressBytes(), vlan), false);
             }
         }
     }
@@ -822,12 +835,12 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                         // requestors across the cluster
                         if (ev.isNewReply()) {
                             log.trace("Trigger a generateAndSendReply in response to {}", rep);
-                            generateAndSendReply(rep.getTargetIP(), rep.getTargetMac());
+                            generateAndSendReply(rep.getTargetIP(), rep.getTargetMac(), rep.getVlan());
                             // Otherwise, a specific reply. If local, send out.
                         } else if (connectionManager.getLocalityStatus(rep.getPort().getNode()) == ConnectionLocality.LOCAL) {
                             log.trace("ARPCacheEventHandler - sendUcatARPReply locally in response to {}", rep);
                             sendARPReply(rep.getPort(), rep.getSourceMac(), rep.getSourceIP(), rep.getTargetMac(),
-                                    rep.getTargetIP());
+                                    rep.getTargetIP(), rep.getVlan());
                         }
                     }
                 } catch (InterruptedException e) {
index 3f1fa38ebd8631d4e0c4b1917088a91edb637c7c..3aeb2ccba72ebcb372eb33b265daf9c33ad1b006 100644 (file)
@@ -2,11 +2,13 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
-    <groupId>org.opendaylight.controller</groupId>
-    <artifactId>commons.parent</artifactId>
-    <version>1.0.2-SNAPSHOT</version>
-    <relativePath>../parent</relativePath>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>odlparent</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath></relativePath>
   </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
   <artifactId>commons.opendaylight</artifactId>
   <version>1.4.2-SNAPSHOT</version>
   <packaging>pom</packaging>
@@ -15,6 +17,7 @@
   </prerequisites>
 
   <properties>
+
     <akka.version>2.3.2</akka.version>
     <aopalliance.version>1.0.0</aopalliance.version>
     <appauth.version>0.4.2-SNAPSHOT</appauth.version>
@@ -22,7 +25,6 @@
     <aries.util.version>1.1.0</aries.util.version>
     <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
     <!-- Controller Modules Versions -->
-    <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
     <asm.version>4.1</asm.version>
     <!-- Plugin Versions -->
     <bouncycastle.version>1.50</bouncycastle.version>
@@ -30,7 +32,7 @@
     <bundlescanner.api.version>0.4.2-SNAPSHOT</bundlescanner.api.version>
     <bundlescanner.implementation.version>0.4.2-SNAPSHOT</bundlescanner.implementation.version>
     <bundlescanner.version>0.4.2-SNAPSHOT</bundlescanner.version>
-    <checkstyle.version>2.10</checkstyle.version>
+    <checkstyle.version>2.12</checkstyle.version>
     <clustering.services.version>0.5.1-SNAPSHOT</clustering.services.version>
     <clustering.services_implementation.version>0.4.3-SNAPSHOT</clustering.services_implementation.version>
     <clustering.stub.version>0.4.2-SNAPSHOT</clustering.stub.version>
@@ -41,7 +43,6 @@
     <commons.catalina.ha>7.0.32.v201211201952</commons.catalina.ha>
     <commons.catalina.tribes>7.0.32.v201211201952</commons.catalina.tribes>
     <commons.checkstyle.version>0.0.3-SNAPSHOT</commons.checkstyle.version>
-    <commons.codec.version>1.7</commons.codec.version>
     <commons.coyote>7.0.32.v201211201952</commons.coyote>
     <commons.el>7.0.32.v201211081135</commons.el>
     <commons.fileupload.version>1.2.2</commons.fileupload.version>
@@ -49,7 +50,7 @@
     <commons.io.version>2.4</commons.io.version>
     <commons.jasper>7.0.32.v201211201952</commons.jasper>
     <commons.juli.version>7.0.32.v201211081135</commons.juli.version>
-    <commons.lang.version>3.1</commons.lang.version>
+    <commons.lang3.version>3.1</commons.lang3.version>
     <commons.logback_settings.version>0.0.2-SNAPSHOT</commons.logback_settings.version>
     <commons.net.version>3.0.1</commons.net.version>
     <commons.opendaylight.commons.httpclient>0.1.2-SNAPSHOT</commons.opendaylight.commons.httpclient>
@@ -59,6 +60,7 @@
     <commons.tomcat.api>7.0.32.v201211081135</commons.tomcat.api>
     <commons.tomcat.util>7.0.32.v201211201952</commons.tomcat.util>
     <compiler.version>2.3.2</compiler.version>
+    <commons.httpclient.version>0.1.2-SNAPSHOT</commons.httpclient.version>
     <concepts.version>0.5.2-SNAPSHOT</concepts.version>
     <config.version>0.2.5-SNAPSHOT</config.version>
     <configuration.implementation.version>0.4.3-SNAPSHOT</configuration.implementation.version>
@@ -69,8 +71,6 @@
     <containermanager.shell.version>0.5.2-SNAPSHOT</containermanager.shell.version>
     <containermanager.version>0.5.2-SNAPSHOT</containermanager.version>
     <controllermanager.northbound.version>0.0.2-SNAPSHOT</controllermanager.northbound.version>
-    <corsfilter.version>7.0.42</corsfilter.version>
-    <ctrie.version>0.2.0</ctrie.version>
     <devices.web.version>0.4.2-SNAPSHOT</devices.web.version>
     <dummy-console.version>1.1.0-SNAPSHOT</dummy-console.version>
     <eclipse.persistence.version>2.5.0</eclipse.persistence.version>
     <exam.version>3.0.0</exam.version>
 
     <!-- OpenEXI third party lib for netconf-->
+
     <exi.nagasena.version>0000.0002.0038.0</exi.nagasena.version>
-    <failsafe.version>2.15</failsafe.version>
-    <feature.transaction.version>1.0.1</feature.transaction.version>
-    <felix.dependencymanager.shell.version>3.0.1</felix.dependencymanager.shell.version>
-    <felix.dependencymanager.version>3.1.0</felix.dependencymanager.version>
-    <felix.fileinstall.version>3.1.6</felix.fileinstall.version>
-    <felix.webconsole.version>4.2.0</felix.webconsole.version>
     <filtervalve.version>1.4.2-SNAPSHOT</filtervalve.version>
+    <findbugs.maven.plugin.version>2.4.0</findbugs.maven.plugin.version>
     <flowprogrammer.northbound.version>0.4.2-SNAPSHOT</flowprogrammer.northbound.version>
     <flows.web.version>0.4.2-SNAPSHOT</flows.web.version>
     <forwarding.staticrouting>0.5.2-SNAPSHOT</forwarding.staticrouting>
     <forwarding.staticrouting.northbound.version>0.4.2-SNAPSHOT</forwarding.staticrouting.northbound.version>
     <forwardingrulesmanager.implementation.version>0.4.2-SNAPSHOT</forwardingrulesmanager.implementation.version>
     <forwardingrulesmanager.version>0.6.0-SNAPSHOT</forwardingrulesmanager.version>
-    <geminiweb.version>2.2.0.RELEASE</geminiweb.version>
-    <gson.version>2.2.4</gson.version>
-    <guava.version>14.0.1</guava.version>
     <hosttracker.api.version>0.5.2-SNAPSHOT</hosttracker.api.version>
     <hosttracker.implementation.version>0.5.2-SNAPSHOT</hosttracker.implementation.version>
     <hosttracker.northbound.version>0.4.2-SNAPSHOT</hosttracker.northbound.version>
     <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>
-    <jacoco.version>0.6.2.201302030002</jacoco.version>
-    <jar.plugin.version>2.4</jar.plugin.version>
-    <java.version.source>1.7</java.version.source>
-    <java.version.target>1.7</java.version.target>
-    <javassist.version>3.17.1-GA</javassist.version>
-    <javax.annotation.version>1.2</javax.annotation.version>
-    <!-- Third party version -->
-    <jersey-servlet.version>1.17</jersey-servlet.version>
-    <jersey.version>1.17</jersey.version>
-    <jersey2.publisher.version>4.0</jersey2.publisher.version>
-    <jersey2.version>2.8</jersey2.version>
-    <jettison.version>1.3.3</jettison.version>
+    <jdepend.maven.plugin.version>2.0-beta-2</jdepend.maven.plugin.version>
     <jmxGeneratorPath>src/main/yang-gen-config</jmxGeneratorPath>
     <jolokia-bridge.version>0.0.2-SNAPSHOT</jolokia-bridge.version>
     <jolokia.version>1.1.4</jolokia.version>
     <karaf.branding.version>1.0.0-SNAPSHOT</karaf.branding.version>
     <karaf.shell.version>3.0.0</karaf.shell.version>
     <karaf.version>3.0.1</karaf.version>
+    <lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
     <logback.version>1.0.9</logback.version>
     <logging.bridge.version>0.4.2-SNAPSHOT</logging.bridge.version>
-    <maven.compile.plugin.version>2.5.1</maven.compile.plugin.version>
-    <!-- Java Versions -->
-    <maven.compiler.source>1.7</maven.compiler.source>
-    <maven.compiler.target>1.7</maven.compiler.target>
+    <maven.plugin.api.version>3.0.5</maven.plugin.api.version>
     <mdsal.version>1.1-SNAPSHOT</mdsal.version>
-    <mockito.version>1.9.5</mockito.version>
     <netconf.version>0.2.5-SNAPSHOT</netconf.version>
-    <netty.version>4.0.19.Final</netty.version>
     <networkconfig.bridgedomain.northbound.version>0.0.3-SNAPSHOT</networkconfig.bridgedomain.northbound.version>
     <networkconfig.neutron.implementation.version>0.4.2-SNAPSHOT</networkconfig.neutron.implementation.version>
     <networkconfig.neutron.northbound.version>0.4.2-SNAPSHOT</networkconfig.neutron.northbound.version>
     <northbound.hosttracker.version>1.4.2-SNAPSHOT</northbound.hosttracker.version>
     <northbound.jolokia.version>1.4.2-SNAPSHOT</northbound.jolokia.version>
     <opendaylight-l2-types.version>2013.08.27.4-SNAPSHOT</opendaylight-l2-types.version>
-    <org.json.version>20080701</org.json.version>
     <osgi-brandfragment.web.version>0.0.2-SNAPSHOT</osgi-brandfragment.web.version>
-    <osgi.compendium.version>5.0.0</osgi.compendium.version>
-    <osgi.core.version>5.0.0</osgi.core.version>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-    <projectinfo>2.6</projectinfo>
     <propertymavenplugin.version>1.0-alpha-2</propertymavenplugin.version>
     <protocol-framework.version>0.5.0-SNAPSHOT</protocol-framework.version>
     <protocol_plugins.openflow.version>0.4.2-SNAPSHOT</protocol_plugins.openflow.version>
     <protocol_plugins.stub.version>0.4.2-SNAPSHOT</protocol_plugins.stub.version>
-    <releaseplugin.version>2.3.2</releaseplugin.version>
     <routing.dijkstra_implementation.version>0.4.2-SNAPSHOT</routing.dijkstra_implementation.version>
     <sal.connection.version>0.1.2-SNAPSHOT</sal.connection.version>
     <sal.implementation.version>0.4.2-SNAPSHOT</sal.implementation.version>
     <scala.version>2.11</scala.version>
     <security.version>0.4.2-SNAPSHOT</security.version>
     <sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
-    <siteplugin>3.2</siteplugin>
-    <slf4j.version>1.7.2</slf4j.version>
     <sonar.branch>${user.name}-private-view</sonar.branch>
     <sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
     <!-- Sonar properties using jacoco to retrieve integration test results -->
     <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
     <sonar.language>java</sonar.language>
     <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2</sonar.skippedModules>
-    <spifly.version>1.0.0</spifly.version>
-    <spring-osgi.version>1.2.1</spring-osgi.version>
-    <spring-security-karaf.version>3.1.4.RELEASE</spring-security-karaf.version>
-    <spring-security.version>3.1.3.RELEASE</spring-security.version>
-    <spring.version>3.1.3.RELEASE</spring.version>
     <statistics.northbound.version>0.4.2-SNAPSHOT</statistics.northbound.version>
     <statisticsmanager.implementation.version>0.4.2-SNAPSHOT</statisticsmanager.implementation.version>
     <statisticsmanager.version>0.5.1-SNAPSHOT</statisticsmanager.version>
     <topology.web.version>0.4.2-SNAPSHOT</topology.web.version>
     <topologymanager.version>0.4.2-SNAPSHOT</topologymanager.version>
     <troubleshoot.web.version>0.4.2-SNAPSHOT</troubleshoot.web.version>
-    <url.version>1.5.0</url.version>
     <usermanager.implementation.version>0.4.2-SNAPSHOT</usermanager.implementation.version>
     <usermanager.northbound.version>0.0.2-SNAPSHOT</usermanager.northbound.version>
     <usermanager.version>0.4.2-SNAPSHOT</usermanager.version>
-    <virgo.version>3.6.0.RELEASE</virgo.version>
     <web.version>0.4.2-SNAPSHOT</web.version>
     <xtend.dstdir>src/main/xtend-gen</xtend.dstdir>
-    <xtend.version>2.4.3</xtend.version>
     <yang-ext.version>2013.09.07.4-SNAPSHOT</yang-ext.version>
     <yang-jmx-generator.version>1.0.0-SNAPSHOT</yang-jmx-generator.version>
     <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
 
   <dependencyManagement>
     <dependencies>
-
+       <!-- project specific dependencies -->
       <dependency>
         <groupId>${project.groupId}</groupId>
         <artifactId>ietf-netconf-monitoring</artifactId>
         <artifactId>guava</artifactId>
         <version>${guava.version}</version>
       </dependency>
+      <!-- 3rd party dependencies needed by config-->
+      <dependency>
+        <groupId>com.jcabi</groupId>
+        <artifactId>jcabi-maven-slf4j</artifactId>
+        <version>0.8</version>
+      </dependency>
 
       <dependency>
         <groupId>com.sun.jersey</groupId>
         <artifactId>akka-remote_${scala.version}</artifactId>
         <version>${akka.version}</version>
       </dependency>
+      <dependency>
+        <groupId>com.typesafe.akka</groupId>
+        <artifactId>akka-testkit_${scala.version}</artifactId>
+        <version>${akka.version}</version>
+      </dependency>
       <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</artifactId>
         <artifactId>commons-io</artifactId>
         <version>${commons.io.version}</version>
       </dependency>
+      <dependency>
+        <groupId>commons-lang</groupId>
+        <artifactId>commons-lang</artifactId>
+        <version>${commons.lang.version}</version>
+      </dependency>
       <dependency>
         <groupId>commons-net</groupId>
         <artifactId>commons-net</artifactId>
         <artifactId>jsr311-api</artifactId>
         <version>${jsr311.api.version}</version>
       </dependency>
+      <dependency>
+        <groupId>net.sourceforge.pmd</groupId>
+        <artifactId>pmd</artifactId>
+        <version>5.1.0</version>
+      </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>javax.activation</artifactId>
       <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-lang3</artifactId>
-        <version>${commons.lang.version}</version>
+        <version>${commons.lang3.version}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.felix</groupId>
         <artifactId>enunciate-core-annotations</artifactId>
         <version>${enunciate.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.codehaus.gmaven.runtime</groupId>
+        <artifactId>gmaven-runtime-2.0</artifactId>
+        <version>1.5</version>
+      </dependency>
       <dependency>
         <groupId>org.codehaus.jettison</groupId>
         <artifactId>jettison</artifactId>
         <version>${jettison.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.eclipse</groupId>
+        <artifactId>jdt</artifactId>
+        <version>3.3.0-v20070607-1300</version>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.equinox</groupId>
+        <artifactId>app</artifactId>
+        <version>1.0.0-v20070606</version>
+      </dependency>
 
       <!-- equinox http service bridge -->
       <dependency>
         <artifactId>servlet</artifactId>
         <version>1.0.0-v20070606</version>
       </dependency>
+      <dependency>
+        <groupId>org.eclipse.jdt</groupId>
+        <artifactId>core</artifactId>
+        <version>3.3.0-v_771</version>
+      </dependency>
       <dependency>
         <groupId>org.eclipse.persistence</groupId>
         <artifactId>org.eclipse.persistence.antlr</artifactId>
         <artifactId>org.eclipse.xtend.lib</artifactId>
         <version>${xtend.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+        <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+        <version>2.4</version>
+      </dependency>
       <dependency>
         <groupId>org.javassist</groupId>
         <artifactId>javassist</artifactId>
         <version>${javassist.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.jboss.resteasy</groupId>
+        <artifactId>jaxrs-api</artifactId>
+        <version>3.0.4.Final</version>
+      </dependency>
       <dependency>
         <groupId>org.jboss.spec.javax.transaction</groupId>
         <artifactId>jboss-transaction-api_1.1_spec</artifactId>
         <artifactId>filter-valve</artifactId>
         <version>${filtervalve.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>flow-management-compatibility</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>flowprogrammer.northbound</artifactId>
         <artifactId>netconf-client</artifactId>
         <version>${netconf.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-client</artifactId>
+        <version>${netconf.version}</version>
+        <type>test-jar</type>
+      </dependency>
 
       <!--Netconf config-->
       <dependency>
         <artifactId>sal-remote</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-remoterpc-connector</artifactId>
-        <version>${mdsal.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>sal-rest-connector</artifactId>
         <artifactId>model-inventory</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.model</groupId>
+        <artifactId>model-topology</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.samples</groupId>
+        <artifactId>sample-toaster</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.samples</groupId>
+        <artifactId>sample-toaster-consumer</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.opendaylight.controller.samples</groupId>
+        <artifactId>sample-toaster-provider</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>com.sun.jersey.jersey-servlet</artifactId>
         <artifactId>yang-ext</artifactId>
         <version>${yang-ext.version}</version>
       </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>${xtend.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.openexi</groupId>
         <artifactId>nagasena</artifactId>
         <artifactId>org.osgi.core</artifactId>
         <version>${osgi.core.version}</version>
       </dependency>
-
-      <dependency>
-        <groupId>org.ow2.asm</groupId>
-        <artifactId>asm-all</artifactId>
-        <version>4.1</version>
-      </dependency>
-      <!-- Visual VM hook -->
       <dependency>
-        <groupId>org.ow2.chameleon.management</groupId>
-        <artifactId>chameleon-mbeans</artifactId>
-        <version>1.0.0</version>
+        <groupId>org.reflections</groupId>
+        <artifactId>reflections</artifactId>
+        <version>0.9.9-RC1</version>
       </dependency>
       <dependency>
         <groupId>org.scala-lang</groupId>
         <scope>compile</scope>
       </dependency>
       <dependency>
-        <groupId>org.springframework</groupId>
-        <artifactId>org.springframework.aop</artifactId>
-        <version>${spring.version}</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.beans</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.expression</artifactId>
-        <version>${spring.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.springframework</groupId>
-        <artifactId>org.springframework.transaction</artifactId>
-        <version>${spring-security.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.springframework</groupId>
-        <artifactId>org.springframework.web</artifactId>
-        <version>${spring.version}</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-taglibs</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>virgomirror</groupId>
-        <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId>
-        <version>3.8.0.I20120518-2145</version>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-simple</artifactId>
+        <version>${slf4j.version}</version>
       </dependency>
       <dependency>
         <groupId>junit</groupId>
         <version>${junit.version}</version>
         <scope>test</scope>
       </dependency>
-      <dependency>
-        <groupId>org.mockito</groupId>
-        <artifactId>mockito-all</artifactId>
-        <version>${mockito.version}</version>
-        <scope>test</scope>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>commons.logback_settings</artifactId>
         <version>${yangtools.version}</version>
         <scope>test</scope>
       </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.springframework.osgi</groupId>
-        <artifactId>spring-osgi-mock</artifactId>
-        <version>${spring-osgi.version}</version>
-        <scope>test</scope>
-      </dependency>
-      <dependency>
-        <groupId>xmlunit</groupId>
-        <artifactId>xmlunit</artifactId>
-        <version>1.5</version>
-        <scope>test</scope>
-      </dependency>
     </dependencies>
   </dependencyManagement>
 
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
                     <ignore></ignore>
                   </action>
                 </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>javacc-maven-plugin</artifactId>
+                    <versionRange>[0.0,)</versionRange>
+                    <goals>
+                      <goal>javacc</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <execute>
+                      <runOnIncremental>false</runOnIncremental>
+                    </execute>
+                  </action>
+                </pluginExecution>
               </pluginExecutions>
             </lifecycleMappingMetadata>
           </configuration>
       </snapshots>
       <id>opendaylight-mirror</id>
       <name>opendaylight-mirror</name>
-      <url>${nexusproxy}/groups/public/</url>
+      <url>http://nexus.opendaylight.org/content/groups/public/</url>
     </repository>
     <!-- OpenDayLight Snapshot artifact -->
     <repository>
       </snapshots>
       <id>opendaylight-snapshot</id>
       <name>opendaylight-snapshot</name>
-      <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
     </repository>
   </repositories>
 
       </snapshots>
       <id>opendaylight-mirror</id>
       <name>opendaylight-mirror</name>
-      <url>${nexusproxy}/groups/public/</url>
+      <url>http://nexus.opendaylight.org/content/groups/public/</url>
     </pluginRepository>
     <!-- OpenDayLight Snapshot artifact -->
     <pluginRepository>
       </snapshots>
       <id>opendaylight-snapshot</id>
       <name>opendaylight-snapshot</name>
-      <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
     </pluginRepository>
   </pluginRepositories>
   <distributionManagement>
     <!-- OpenDayLight Released artifact -->
     <repository>
       <id>opendaylight-release</id>
-      <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.release/</url>
     </repository>
     <!-- OpenDayLight Snapshot artifact -->
     <snapshotRepository>
       <id>opendaylight-snapshot</id>
-      <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
     </snapshotRepository>
     <!-- Site deployment -->
     <site>
index fef2c7196948c007705b4444a5c9445065618648..a62bd7da06501b355c41f36230dbf30a982d61fa 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.protocol.framework;
 
 import com.google.common.base.Preconditions;
+
 import io.netty.bootstrap.Bootstrap;
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.Channel;
+import io.netty.buffer.PooledByteBufAllocator;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelInitializer;
 import io.netty.channel.ChannelOption;
@@ -25,9 +27,11 @@ import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
 import io.netty.util.concurrent.Promise;
+
 import java.io.Closeable;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -94,8 +98,8 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
      *
      * @return ChannelFuture representing the binding process
      */
-    protected <CH extends Channel> ChannelFuture createServer(SocketAddress address, Class<? extends ServerChannel> channelClass,
-                                                              final ChannelPipelineInitializer<CH, S> initializer) {
+    protected <CH extends Channel> ChannelFuture createServer(final SocketAddress address, final Class<? extends ServerChannel> channelClass,
+            final ChannelPipelineInitializer<CH, S> initializer) {
         final ServerBootstrap b = new ServerBootstrap();
         b.childHandler(new ChannelInitializer<CH>() {
 
@@ -110,6 +114,7 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
             // makes no sense for LocalServer and produces warning
             b.childOption(ChannelOption.SO_KEEPALIVE, true);
         }
+        b.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
         customizeBootstrap(b);
 
         if (b.group() == null) {
@@ -151,9 +156,8 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
     protected Future<S> createClient(final InetSocketAddress address, final ReconnectStrategy strategy, final PipelineInitializer<S> initializer) {
         final Bootstrap b = new Bootstrap();
         final ProtocolSessionPromise<S> p = new ProtocolSessionPromise<S>(executor, address, strategy, b);
-        b.group(this.workerGroup).channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE, true).handler(
+        b.option(ChannelOption.SO_KEEPALIVE, true).handler(
                 new ChannelInitializer<SocketChannel>() {
-
                     @Override
                     protected void initChannel(final SocketChannel ch) {
                         initializer.initializeChannel(ch, p);
@@ -162,6 +166,18 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
 
         customizeBootstrap(b);
 
+        if (b.group() == null) {
+            b.group(workerGroup);
+        }
+
+        // There is no way to detect if this was already set by
+        // customizeBootstrap()
+        try {
+            b.channel(NioSocketChannel.class);
+        } catch (IllegalStateException e) {
+            LOG.trace("Not overriding channelFactory on bootstrap {}", b, e);
+        }
+
         p.connect();
         LOG.debug("Client created.");
         return p;
@@ -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.config.manager.impl.jmx;
+package org.opendaylight.controller.config.api.jmx;
 
 import javax.management.ObjectName;
 
index 79fd5268e674c6ee7d6cc53a30b112b8fc5c90b6..fc2c0fd85b86f79a60c30fb34bc8199b1459c1c9 100644 (file)
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>
-    <!--
-        <dependency>
-            <groupId>com.googlecode.json-simple</groupId>
-            <artifactId>json-simple</artifactId>
-            <version>1.1</version>
-        </dependency>
-        -->
+
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
index dedeeed789f5e8b9ec030f2c349beec19f1c2872..ba6676b927bb554d296b2ebaa9efd3205bdebc4c 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.config.manager.impl.jmx;
 
 import javax.management.ObjectName;
+import org.opendaylight.controller.config.api.jmx.ServiceReferenceMXBean;
 
 public class ServiceReferenceMXBeanImpl implements ServiceReferenceMXBean {
     private ObjectName currentImplementation;
index 3e7b65e1bdcf8f25cfe6c255e43072edc2382f6a..8c132c93b298dee714f3efa063f329efc70a7878 100644 (file)
@@ -13,7 +13,7 @@ import org.junit.Test;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest.RecordingBundleContextServiceRegistrationHandler.RegistrationHolder;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
-import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBean;
+import org.opendaylight.controller.config.api.jmx.ServiceReferenceMXBean;
 import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
 import org.opendaylight.controller.config.manager.testingservices.parallelapsp.test.AbstractParallelAPSPTest;
 import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory;
index c00b26d9ced898dc0dd4f4239d68b9d933332ad3..ba13ebb8f051e65d31c5a663daee15b1034d0134 100644 (file)
@@ -12,13 +12,14 @@ import java.util.SortedSet;
 public interface ConfigSnapshotHolder {
 
     /**
-     * Get part of get-config document that contains just
+     * Get XML node that should be pushed to netconf's edit-config
      */
     String getConfigSnapshot();
 
 
     /**
      * Get only required capabilities referenced by the snapshot.
+     * If no value is specified, return empty set instead of null
      */
     SortedSet<String> getCapabilities();
 
index d13052a7e273a3aa5ffb45e22e8b421ed689afde..7c069dab6b0fb04bbd511fefffbfc5ebf3be6879 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.persist.storage.file.xml.model;
 
+import java.util.TreeSet;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 
 import javax.xml.bind.annotation.XmlAnyElement;
@@ -22,7 +23,7 @@ public class ConfigSnapshot {
     public static final String SNAPSHOT_ROOT_ELEMENT_NAME = "snapshot";
 
     private String configSnapshot;
-    private SortedSet<String> capabilities;
+    private SortedSet<String> capabilities = new TreeSet<>();
 
     ConfigSnapshot(String configXml, SortedSet<String> capabilities) {
         this.configSnapshot = configXml;
index 549ff9ffcfdb9254a4115349d1cbd65520875809..559993f2648ec013791bdcf7167e412fe9a69102 100644 (file)
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import org.opendaylight.controller.config.api.jmx.ServiceReferenceMXBean;
 
 public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     private final ConfigRegistryMXBean configRegistryMXBeanProxy;
@@ -65,10 +66,27 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
                 configMBeanServer);
     }
 
+    /**
+     * Usage of this method indicates error as config JMX uses solely MXBeans.
+     * Use {@link #newMXBeanProxy(javax.management.ObjectName, Class)}
+     * or {@link JMX#newMBeanProxy(javax.management.MBeanServerConnection, javax.management.ObjectName, Class)}
+     * This method will be removed soon.
+     */
+    @Deprecated
     public <T> T newMBeanProxy(ObjectName on, Class<T> clazz) {
+        on = translateServiceRefIfPossible(on, clazz, configMBeanServer);
         return JMX.newMBeanProxy(configMBeanServer, on, clazz);
     }
 
+    static  ObjectName translateServiceRefIfPossible(ObjectName on, Class<?> clazz, MBeanServer configMBeanServer) {
+        if (ObjectNameUtil.isServiceReference(on) && clazz.equals(ServiceReferenceMXBean.class) == false) {
+            ServiceReferenceMXBean proxy = JMX.newMXBeanProxy(configMBeanServer, on, ServiceReferenceMXBean.class);
+            on = proxy.getCurrentImplementation();
+        }
+        return on;
+    }
+
+
     public <T> T newMXBeanProxy(ObjectName on, Class<T> clazz) {
         return JMX.newMXBeanProxy(configMBeanServer, on, clazz);
     }
@@ -211,5 +229,4 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
         configRegistryMXBeanProxy.checkServiceReferenceExists(objectName);
     }
-
 }
index 4adc0d9364e3392969c0c771edc4fd5ae41cdaf1..4cf766a8120ef4c559eb45a9883c7583c1983f8b 100644 (file)
@@ -7,13 +7,8 @@
  */
 package org.opendaylight.controller.config.util;
 
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.api.jmx.CommitStatus;
-import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
-import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-
+import java.util.Map;
+import java.util.Set;
 import javax.management.Attribute;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
@@ -22,8 +17,12 @@ import javax.management.JMX;
 import javax.management.MBeanException;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
-import java.util.Map;
-import java.util.Set;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
+import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 
 public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     private final ConfigRegistryMXBean configRegistryMXBeanProxy;
@@ -44,9 +43,21 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     public <T> T newMXBeanProxy(ObjectName on, Class<T> clazz) {
+        // if on is without transaction, add it. Reason is that when using getters on MXBeans the transaction name is stripped
+        on = ObjectNameUtil.withTransactionName(on, getTransactionName());
+        // if this is service reference and user requests for implementation, look it up
+        on = ConfigRegistryJMXClient.translateServiceRefIfPossible(on, clazz, configMBeanServer);
+        on = ObjectNameUtil.withTransactionName(on, getTransactionName());
         return JMX.newMXBeanProxy(configMBeanServer, on, clazz);
     }
 
+    /**
+     * Usage of this method indicates error as config JMX uses solely MXBeans.
+     * Use {@link #newMXBeanProxy(javax.management.ObjectName, Class)}
+     * or {@link JMX#newMBeanProxy(javax.management.MBeanServerConnection, javax.management.ObjectName, Class)}
+     * This method will be removed soon.
+     */
+    @Deprecated
     public <T> T newMBeanProxy(ObjectName on, Class<T> clazz) {
         return JMX.newMBeanProxy(configMBeanServer, on, clazz);
     }
index 65ebdaf938bd5092bd433f3f8b72dfe6d66a2d14..b9d218ead1ea0fe39efd15c051037ebc2807e8be 100644 (file)
@@ -26,7 +26,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-client</artifactId>
-      <version>${netconf.version}</version>
     </dependency>
   </dependencies>
 
index 5f34a9aa82d0ab35780b04862882710b7ae47fe8..76fbd7f6e55c057e6248fed354da9c8f801da2bb 100644 (file)
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-antrun-plugin</artifactId>
-          <version>1.3</version>
+          <version>${maven.antrun.plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
-          <version>2.4</version>
           <executions>
             <execution>
               <goals>
@@ -99,7 +98,6 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
-          <version>2.14.1</version>
           <configuration>
             <redirectTestOutputToFile>true</redirectTestOutputToFile>
             <parallel>classes</parallel>
         <plugin>
           <groupId>org.codehaus.groovy.maven</groupId>
           <artifactId>gmaven-plugin</artifactId>
-          <version>1.0</version>
+          <version>${gmaven.plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.opendaylight.yangtools</groupId>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
-        <version>2.12</version>
         <configuration>
           <failsOnError>false</failsOnError>
           <failOnViolation>false</failOnViolation>
index 4bc080bbff91f0cf0f2478432edcf83681e2b3f3..4fd0d681a11e49f5cf5038afaa6bd6c7a3c8c4de 100644 (file)
@@ -23,7 +23,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>threadpool-config-api</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>
index b8831f6979ec3205e496c13ee1df15217d3d9feb..5f51980b94b530e3dbdb7e6e87059088c425b61b 100644 (file)
@@ -24,7 +24,6 @@
     <dependency>
       <groupId>com.jcabi</groupId>
       <artifactId>jcabi-maven-slf4j</artifactId>
-      <version>0.8</version>
     </dependency>
 
     <dependency>
@@ -40,7 +39,6 @@
     <dependency>
       <groupId>org.codehaus.gmaven.runtime</groupId>
       <artifactId>gmaven-runtime-2.0</artifactId>
-      <version>1.5</version>
       <exclusions>
         <exclusion>
           <groupId>org.sonatype.gossip</groupId>
     <dependency>
       <groupId>net.sourceforge.pmd</groupId>
       <artifactId>pmd</artifactId>
-      <version>5.1.0</version>
       <scope>test</scope>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse</groupId>
       <artifactId>jdt</artifactId>
-      <version>3.3.0-v20070607-1300</version>
       <scope>test</scope>
 
       <exclusions>
     <dependency>
       <groupId>org.eclipse.equinox</groupId>
       <artifactId>app</artifactId>
-      <version>1.0.0-v20070606</version>
       <scope>test</scope>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse.jdt</groupId>
       <artifactId>core</artifactId>
-      <version>3.3.0-v_771</version>
       <scope>test</scope>
 
       <exclusions>
index aa06cb97d74eafcc35eeea7f16128e7f94743cfb..33546b1e2ae6a4d6ede0dfaddfc307495f13a325 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory;
 
+import static com.google.common.base.Preconditions.checkState;
 import static java.lang.String.format;
 
 import com.google.common.base.Joiner;
@@ -212,7 +213,7 @@ public class AbsModuleGeneratedObjectFactory {
                         "}\n", moduleField.getName(), osgi);
                 } else {
                     str = format(
-                        "%1$sDependency = dependencyResolver.resolveInstance(%2$s.class, %1$s, %1$sJmxAttribute);",
+                        "%1$sDependency = dependencyResolver.resolveInstance(%2$s.class, %1$s, %1$sJmxAttribute);\n",
                         moduleField.getName(), osgi);
                 }
                 resolveDependenciesMap.put(moduleField, str);
@@ -222,7 +223,8 @@ public class AbsModuleGeneratedObjectFactory {
         // wrap each field resolvation statement with if !=null when dependency is not mandatory
         for (Map.Entry<ModuleField, String> entry : resolveDependenciesMap.entrySet()) {
             if (entry.getKey().getDependency().isMandatory() == false) {
-                result += format("if (%s!=null) {\n%s;\n}", entry.getKey().getName(), entry.getValue());
+                checkState(entry.getValue().endsWith(";\n"));
+                result += format("if (%s!=null) {\n%s}\n", entry.getKey().getName(), entry.getValue());
             } else {
                 result += entry.getValue();
             }
@@ -284,7 +286,7 @@ public class AbsModuleGeneratedObjectFactory {
             format("private final %s oldModule;\n", abstractFQN.getTypeName())+
             format("private final %s oldInstance;\n", AutoCloseable.class.getCanonicalName())+
             format("private %s instance;\n", AutoCloseable.class.getCanonicalName())+
-            format("private final %s dependencyResolver;\n", DependencyResolver.class.getCanonicalName())+
+            format("protected final %s dependencyResolver;\n", DependencyResolver.class.getCanonicalName())+
             format("private final %s identifier;\n", ModuleIdentifier.class.getCanonicalName())+
             "@Override\n"+
             format("public %s getIdentifier() {\n", ModuleIdentifier.class.getCanonicalName())+
@@ -401,7 +403,7 @@ public class AbsModuleGeneratedObjectFactory {
         parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier");
         parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
 
-        String setToNulls = "this.oldInstance=null;\n;" +
+        String setToNulls = "this.oldInstance=null;\n" +
                 "this.oldModule=null;\n";
         return getConstructorStart(abstractFQN, parameters, setToNulls);
     }
index ae064001956b9217fcfc1e950309ff514d17ddf6..775fa9fc20d97b10a48859703a4572f03b65d2ca 100644 (file)
@@ -7,11 +7,6 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
-import java.net.URI;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
 import org.opendaylight.yangtools.yang.common.QName;
 
 public class ConfigConstants {
@@ -33,33 +28,14 @@ public class ConfigConstants {
     public static final QName RPC_CONTEXT_REF_GROUPING_LEAF = createRpcXQName("context-instance");
     public static final QName RPC_CONTEXT_INSTANCE_EXTENSION_QNAME = createRpcXQName("rpc-context-instance");
 
-    public static QName createConfigQName(String localName) {
-        return createQName(CONFIG_NAMESPACE, "2013-04-05", localName);
+    public static QName createConfigQName(final String localName) {
+        // FIXME: pre-construct QNameModule
+        return QName.create(CONFIG_NAMESPACE, "2013-04-05", localName);
     }
 
-    public static QName createRpcXQName(String localName) {
-        return createQName("urn:ietf:params:xml:ns:yang:rpc-context",
+    public static QName createRpcXQName(final String localName) {
+        // FIXME: pre-construct QNameModule
+        return QName.create("urn:ietf:params:xml:ns:yang:rpc-context",
                 "2013-06-17", localName);
     }
-
-    /**
-     *
-     * @param uri
-     * @param revisionDate
-     *            in format yyyy-MM-dd
-     * @param localName
-     * @return
-     */
-    private static QName createQName(String uri, String revisionDate,
-            String localName) {
-        SimpleDateFormat revisionFormat = new SimpleDateFormat("yyyy-MM-dd");
-        Date revision;
-        try {
-            revision = revisionFormat.parse(revisionDate);
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
-        return new QName(URI.create(uri), revision, localName);
-    }
-
 }
index 89f3a4a51923a3f126f09b50af7e0d14b7af62a3..d8c5a56fb7a7561de457894180ad1a1b418b7f57 100644 (file)
@@ -18,6 +18,7 @@ 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.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -26,7 +27,9 @@ 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;
@@ -64,27 +67,27 @@ final class ModuleMXBeanEntryBuilder {
     private TypeProviderWrapper typeProviderWrapper;
     private String packageName;
 
-    public ModuleMXBeanEntryBuilder setModule(Module module) {
+    public ModuleMXBeanEntryBuilder setModule(final Module module) {
         this.currentModule = module;
         return this;
     }
 
-    public ModuleMXBeanEntryBuilder setqNamesToSIEs(Map<QName, ServiceInterfaceEntry> qNamesToSIEs) {
+    public ModuleMXBeanEntryBuilder setqNamesToSIEs(final Map<QName, ServiceInterfaceEntry> qNamesToSIEs) {
         this.qNamesToSIEs = qNamesToSIEs;
         return this;
     }
 
-    public ModuleMXBeanEntryBuilder setSchemaContext(SchemaContext schemaContext) {
+    public ModuleMXBeanEntryBuilder setSchemaContext(final SchemaContext schemaContext) {
         this.schemaContext = schemaContext;
         return this;
     }
 
-    public ModuleMXBeanEntryBuilder setTypeProviderWrapper(TypeProviderWrapper typeProviderWrapper) {
+    public ModuleMXBeanEntryBuilder setTypeProviderWrapper(final TypeProviderWrapper typeProviderWrapper) {
         this.typeProviderWrapper = typeProviderWrapper;
         return this;
     }
 
-    public ModuleMXBeanEntryBuilder setPackageName(String packageName) {
+    public ModuleMXBeanEntryBuilder setPackageName(final String packageName) {
         this.packageName = packageName;
         return this;
     }
@@ -147,7 +150,7 @@ final class ModuleMXBeanEntryBuilder {
         return result;
     }
 
-    private static void cleanUpNulls(Map<String, ModuleMXBeanEntry> result) {
+    private static void cleanUpNulls(final Map<String, ModuleMXBeanEntry> result) {
         for (Map.Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
             ModuleMXBeanEntry module = entry.getValue();
             if (module.getAttributes() == null) {
@@ -160,14 +163,14 @@ final class ModuleMXBeanEntryBuilder {
         }
     }
 
-    private static void checkUnaugumentedIdentities(Map<String, IdentitySchemaNode> unaugmentedModuleIdentities) {
+    private static void checkUnaugumentedIdentities(final Map<String, IdentitySchemaNode> unaugmentedModuleIdentities) {
         if (unaugmentedModuleIdentities.size() > 0) {
             logger.warn("Augmentation not found for all currentModule identities: {}",
                     unaugmentedModuleIdentities.keySet());
         }
     }
 
-    private static void checkAttributeNamesUniqueness(Map<String, QName> uniqueGeneratedClassesNames, Map<String, ModuleMXBeanEntry> result) {
+    private static void checkAttributeNamesUniqueness(final Map<String, QName> uniqueGeneratedClassesNames, final Map<String, ModuleMXBeanEntry> result) {
         for (Map.Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
             checkUniqueRuntimeBeanAttributesName(entry.getValue(),
                     uniqueGeneratedClassesNames);
@@ -212,29 +215,30 @@ final class ModuleMXBeanEntryBuilder {
         return moduleIdentities;
     }
 
-    private Collection<ChoiceCaseNode> castChildNodesToChoiceCases(Set<DataSchemaNode> childNodes) {
+    private Collection<ChoiceCaseNode> castChildNodesToChoiceCases(final Set<DataSchemaNode> childNodes) {
         return Collections2.transform(childNodes, new Function<DataSchemaNode, ChoiceCaseNode>() {
             @Nullable
             @Override
-            public ChoiceCaseNode apply(@Nullable DataSchemaNode input) {
+            public ChoiceCaseNode apply(@Nullable final DataSchemaNode input) {
                 return (ChoiceCaseNode) input;
             }
         });
     }
 
-    private boolean areAllChildrenChoiceCaseNodes(Set<DataSchemaNode> childNodes) {
+    private boolean areAllChildrenChoiceCaseNodes(final Set<DataSchemaNode> childNodes) {
         for (DataSchemaNode childNode : childNodes) {
-            if (childNode instanceof ChoiceCaseNode == false)
+            if (childNode instanceof ChoiceCaseNode == false) {
                 return false;
+            }
         }
         return true;
     }
 
-    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,
-            DataSchemaNode when) {
+    private <HAS_CHILDREN_AND_QNAME extends DataNodeContainer & SchemaNode> void processChoiceCaseNode(final Map<String, ModuleMXBeanEntry> result,
+            final Map<String, QName> uniqueGeneratedClassesNames, final String configModulePrefix,
+            final Map<String, IdentitySchemaNode> moduleIdentities,
+            final Map<String, IdentitySchemaNode> unaugmentedModuleIdentities, final AugmentationSchema augmentation,
+            final DataSchemaNode when) {
 
         ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) when;
         if (choiceCaseNode.getConstraints() == null || choiceCaseNode.getConstraints().getWhenCondition() == null) {
@@ -301,12 +305,12 @@ final class ModuleMXBeanEntryBuilder {
             }
             checkState(Objects.equals(nullableDummyContainerName, moduleMXBeanEntry.getNullableDummyContainerName()),
                     "Mismatch in module " + moduleMXBeanEntry.toString() + " - dummy container must be present/missing in" +
-                            " both state and configuration");
+                    " both state and configuration");
         } else {
             ModuleMXBeanEntry.ModuleMXBeanEntryInitial initial = new ModuleMXBeanEntry.ModuleMXBeanEntryInitialBuilder()
-                    .setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix)
-                    .setNamespace(currentModule.getNamespace().toString()).setqName(ModuleUtil.getQName(currentModule))
-                    .build();
+            .setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix)
+            .setNamespace(currentModule.getNamespace().toString()).setqName(ModuleUtil.getQName(currentModule))
+            .build();
 
             // construct ModuleMXBeanEntry
             ModuleMXBeanEntry moduleMXBeanEntry = new ModuleMXBeanEntry(initial, yangToAttributes, providedServices,
@@ -319,8 +323,8 @@ final class ModuleMXBeanEntryBuilder {
         }
     }
 
-    private void checkUniqueRuntimeBeansGeneratedClasses(Map<String, QName> uniqueGeneratedClassesNames,
-            DataSchemaNode when, Collection<RuntimeBeanEntry> runtimeBeans) {
+    private void checkUniqueRuntimeBeansGeneratedClasses(final Map<String, QName> uniqueGeneratedClassesNames,
+            final DataSchemaNode when, final Collection<RuntimeBeanEntry> runtimeBeans) {
         for (RuntimeBeanEntry runtimeBean : runtimeBeans) {
             final String javaNameOfRuntimeMXBean = runtimeBean.getJavaNameOfRuntimeMXBean();
             if (uniqueGeneratedClassesNames.containsKey(javaNameOfRuntimeMXBean)) {
@@ -331,8 +335,8 @@ final class ModuleMXBeanEntryBuilder {
         }
     }
 
-    private static void checkUniqueRuntimeBeanAttributesName(ModuleMXBeanEntry mxBeanEntry,
-            Map<String, QName> uniqueGeneratedClassesNames) {
+    private static void checkUniqueRuntimeBeanAttributesName(final ModuleMXBeanEntry mxBeanEntry,
+            final Map<String, QName> uniqueGeneratedClassesNames) {
         for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) {
             for (String runtimeAttName : runtimeBeanEntry.getYangPropertiesToTypesMap().keySet()) {
                 if (mxBeanEntry.getAttributes().keySet().contains(runtimeAttName)) {
@@ -344,8 +348,8 @@ final class ModuleMXBeanEntryBuilder {
         }
     }
 
-    private void checkUniqueAttributesWithGeneratedClass(Map<String, QName> uniqueGeneratedClassNames,
-            QName parentQName, Map<String, AttributeIfc> yangToAttributes) {
+    private void checkUniqueAttributesWithGeneratedClass(final Map<String, QName> uniqueGeneratedClassNames,
+            final QName parentQName, final Map<String, AttributeIfc> yangToAttributes) {
         for (Map.Entry<String, AttributeIfc> attr : yangToAttributes.entrySet()) {
             if (attr.getValue() instanceof TOAttribute) {
                 checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName, (TOAttribute) attr.getValue());
@@ -357,7 +361,7 @@ final class ModuleMXBeanEntryBuilder {
         }
     }
 
-    private void checkUniqueTOAttr(Map<String, QName> uniqueGeneratedClassNames, QName parentQName, TOAttribute attr) {
+    private void checkUniqueTOAttr(final Map<String, QName> uniqueGeneratedClassNames, final QName parentQName, final TOAttribute attr) {
         final String upperCaseCamelCase = attr.getUpperCaseCammelCase();
         if (uniqueGeneratedClassNames.containsKey(upperCaseCamelCase)) {
             QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCamelCase);
@@ -367,9 +371,9 @@ final class ModuleMXBeanEntryBuilder {
         }
     }
 
-    private Collection<RuntimeBeanEntry> fillRuntimeBeans(DataNodeContainer dataNodeContainer, Module currentModule,
-            TypeProviderWrapper typeProviderWrapper, String packageName, String moduleLocalNameFromXPath,
-            String javaNamePrefix) {
+    private Collection<RuntimeBeanEntry> fillRuntimeBeans(final DataNodeContainer dataNodeContainer, final Module currentModule,
+            final TypeProviderWrapper typeProviderWrapper, final String packageName, final String moduleLocalNameFromXPath,
+            final String javaNamePrefix) {
 
         return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, dataNodeContainer, moduleLocalNameFromXPath,
                 typeProviderWrapper, javaNamePrefix, currentModule).values();
@@ -383,7 +387,7 @@ final class ModuleMXBeanEntryBuilder {
      * @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) {
+    private <HAS_CHILDREN_AND_QNAME extends DataNodeContainer & SchemaNode> HAS_CHILDREN_AND_QNAME getDataNodeContainer(final ChoiceCaseNode choiceCaseNode) {
         Set<DataSchemaNode> childNodes = choiceCaseNode.getChildNodes();
         if (childNodes.size() == 1) {
             DataSchemaNode onlyChild = childNodes.iterator().next();
@@ -398,9 +402,9 @@ final class ModuleMXBeanEntryBuilder {
         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) {
+    private Map<String, AttributeIfc> fillConfiguration(final DataNodeContainer dataNodeContainer, final Module currentModule,
+            final TypeProviderWrapper typeProviderWrapper, final Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+            final SchemaContext schemaContext, final String packageName) {
         Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
         Set<DataSchemaNode> childNodes = dataNodeContainer.getChildNodes();
         for (DataSchemaNode attrNode : childNodes) {
@@ -411,8 +415,8 @@ final class ModuleMXBeanEntryBuilder {
         return yangToAttributes;
     }
 
-    private Map<String, QName> findProvidedServices(IdentitySchemaNode moduleIdentity, Module currentModule,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs, SchemaContext schemaContext) {
+    private Map<String, QName> findProvidedServices(final IdentitySchemaNode moduleIdentity, final Module currentModule,
+            final Map<QName, ServiceInterfaceEntry> qNamesToSIEs, final SchemaContext schemaContext) {
         Map<String, QName> result = new HashMap<>();
         for (UnknownSchemaNode unknownNode : moduleIdentity.getUnknownSchemaNodes()) {
             if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
@@ -425,9 +429,9 @@ final class ModuleMXBeanEntryBuilder {
         return result;
     }
 
-    private AttributeIfc getAttributeValue(DataSchemaNode attrNode, Module currentModule,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs, TypeProviderWrapper typeProviderWrapper,
-            SchemaContext schemaContext, String packageName) {
+    private AttributeIfc getAttributeValue(final DataSchemaNode attrNode, final Module currentModule,
+            final Map<QName, ServiceInterfaceEntry> qNamesToSIEs, final TypeProviderWrapper typeProviderWrapper,
+            final SchemaContext schemaContext, final String packageName) {
 
         if (attrNode instanceof LeafSchemaNode) {
             // simple type
@@ -460,9 +464,9 @@ final class ModuleMXBeanEntryBuilder {
         }
     }
 
-    private Optional<? extends AbstractDependencyAttribute> extractDependency(DataNodeContainer dataNodeContainer,
-            DataSchemaNode attrNode, Module currentModule, Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            SchemaContext schemaContext) {
+    private Optional<? extends AbstractDependencyAttribute> extractDependency(final DataNodeContainer dataNodeContainer,
+            final DataSchemaNode attrNode, final Module currentModule, final Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+            final SchemaContext schemaContext) {
         if (dataNodeContainer.getUses().size() == 1 && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
             // reference
             UsesNode usesNode = dataNodeContainer.getUses().iterator().next();
@@ -490,7 +494,7 @@ final class ModuleMXBeanEntryBuilder {
         return Optional.absent();
     }
 
-    private int getChildNodeSizeWithoutUses(DataNodeContainer csn) {
+    private int getChildNodeSizeWithoutUses(final DataNodeContainer csn) {
         int result = 0;
         for (DataSchemaNode dsn : csn.getChildNodes()) {
             if (dsn.isAddedByUses() == false) {
@@ -500,8 +504,8 @@ final class ModuleMXBeanEntryBuilder {
         return result;
     }
 
-    private ServiceInterfaceEntry findSIE(String prefixAndIdentityLocalName, Module currentModule,
-            Map<QName, ServiceInterfaceEntry> qNamesToSIEs, SchemaContext schemaContext) {
+    private ServiceInterfaceEntry findSIE(final String prefixAndIdentityLocalName, final Module currentModule,
+            final Map<QName, ServiceInterfaceEntry> qNamesToSIEs, final SchemaContext schemaContext) {
 
         Matcher m = PREFIX_COLON_LOCAL_NAME.matcher(prefixAndIdentityLocalName);
         Module foundModule;
@@ -518,13 +522,13 @@ final class ModuleMXBeanEntryBuilder {
             foundModule = currentModule; // no prefix => SIE is in currentModule
             localSIName = prefixAndIdentityLocalName;
         }
-        QName siQName = new QName(foundModule.getNamespace(), foundModule.getRevision(), localSIName);
+        QName siQName = QName.create(foundModule.getNamespace(), foundModule.getRevision(), localSIName);
         ServiceInterfaceEntry sie = qNamesToSIEs.get(siQName);
         checkState(sie != null, "Cannot find referenced Service Interface by " + prefixAndIdentityLocalName);
         return sie;
     }
 
-    private ModuleImport findModuleImport(Module module, String prefix) {
+    private ModuleImport findModuleImport(final Module module, final String prefix) {
         for (ModuleImport moduleImport : module.getImports()) {
             if (moduleImport.getPrefix().equals(prefix)) {
                 return moduleImport;
@@ -534,13 +538,13 @@ final class ModuleMXBeanEntryBuilder {
     }
 
     @VisibleForTesting
-    static Matcher getWhenConditionMatcher(String prefix, RevisionAwareXPath whenConstraint) {
+    static Matcher getWhenConditionMatcher(final String prefix, final RevisionAwareXPath whenConstraint) {
         String xpathRegex = MODULE_CONDITION_XPATH_TEMPLATE.replace(MAGIC_STRING, prefix);
         Pattern pattern = Pattern.compile(xpathRegex);
         return pattern.matcher(whenConstraint.toString());
     }
 
-    String getConfigModulePrefixFromImport(Module currentModule) {
+    String getConfigModulePrefixFromImport(final Module currentModule) {
         for (ModuleImport currentImport : currentModule.getImports()) {
             if (currentImport.getModuleName().equals(ConfigConstants.CONFIG_MODULE)) {
                 return currentImport.getPrefix();
index 5fea8fd078dfbbd95ead79b2610eb16e7bf0a4fe..ccd701d1fb36a2bba58093999a21aa23c7ac5c08 100644 (file)
@@ -12,7 +12,7 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 
 public class ModuleUtil {
 
-    public static QName getQName(Module currentModule){
-        return new QName(currentModule.getNamespace(), currentModule.getRevision(), currentModule.getName());
+    public static QName getQName(final Module currentModule) {
+        return QName.create(currentModule.getNamespace(), currentModule.getRevision(), currentModule.getName());
     }
 }
index c941d1504ddae409a9fdfa0c14ec4da957d1038e..23b071c817022ac0103f7cc01c4cc5f5482ba995 100644 (file)
@@ -13,6 +13,7 @@ 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;
@@ -25,6 +26,7 @@ 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;
@@ -65,11 +67,11 @@ public class RuntimeBeanEntry {
     private final Set<Rpc> rpcs;
 
     @VisibleForTesting
-    RuntimeBeanEntry(String packageName,
-            DataNodeContainer nodeForReporting, String yangName,
-            String javaNamePrefix, boolean isRoot,
-            Optional<String> keyYangName, List<AttributeIfc> attributes,
-            List<RuntimeBeanEntry> children, Set<Rpc> rpcs) {
+    RuntimeBeanEntry(final String packageName,
+            final DataNodeContainer nodeForReporting, final String yangName,
+            final String javaNamePrefix, final boolean isRoot,
+            final Optional<String> keyYangName, final List<AttributeIfc> attributes,
+            final List<RuntimeBeanEntry> children, final Set<Rpc> rpcs) {
 
         checkArgument(isRoot == false || keyYangName.isPresent() == false,
                 "Root RuntimeBeanEntry must not have key " + "set");
@@ -86,7 +88,7 @@ public class RuntimeBeanEntry {
         for (AttributeIfc a : attributes) {
             checkState(map.containsKey(a.getAttributeYangName()) == false,
                     "Attribute already defined: " + a.getAttributeYangName()
-                            + " in " + nodeForReporting);
+                    + " in " + nodeForReporting);
             map.put(a.getAttributeYangName(), a);
         }
 
@@ -110,9 +112,9 @@ public class RuntimeBeanEntry {
      *         not contain special configuration for it.
      */
     public static Map<String, RuntimeBeanEntry> extractClassNameToRuntimeBeanMap(
-            String packageName, DataNodeContainer container,
-            String moduleYangName, TypeProviderWrapper typeProviderWrapper,
-            String javaNamePrefix, Module currentModule) {
+            final String packageName, final DataNodeContainer container,
+            final String moduleYangName, final TypeProviderWrapper typeProviderWrapper,
+            final String javaNamePrefix, final Module currentModule) {
 
         Map<QName, Set<RpcDefinition>> identitiesToRpcs = getIdentitiesToRpcs(currentModule);
 
@@ -151,7 +153,7 @@ public class RuntimeBeanEntry {
     }
 
     private static Map<QName/* of identity */, Set<RpcDefinition>> getIdentitiesToRpcs(
-            Module currentModule) {
+            final Module currentModule) {
         // currently only looks for local identities (found in currentModule)
         Map<QName, Set<RpcDefinition>> result = new HashMap<>();
         for (IdentitySchemaNode identity : currentModule.getIdentities()) {
@@ -164,14 +166,16 @@ public class RuntimeBeanEntry {
             if (input != null) {
                 for (UsesNode uses : input.getUses()) {
 
-                    if (uses.getGroupingPath().getPath().size() != 1)
+                    if (uses.getGroupingPath().getPath().size() != 1) {
                         continue;
+                    }
 
                     // check grouping path
                     QName qname = uses.getGroupingPath().getPath().get(0);
                     if (false == qname
-                            .equals(ConfigConstants.RPC_CONTEXT_REF_GROUPING_QNAME))
+                            .equals(ConfigConstants.RPC_CONTEXT_REF_GROUPING_QNAME)) {
                         continue;
+                    }
 
                     for (SchemaNode refinedNode : uses.getRefines().values()) {
 
@@ -181,7 +185,7 @@ public class RuntimeBeanEntry {
                                     .equals(unknownSchemaNode.getNodeType())) {
                                 String localIdentityName = unknownSchemaNode
                                         .getNodeParameter();
-                                QName identityQName = new QName(
+                                QName identityQName = QName.create(
                                         currentModule.getNamespace(),
                                         currentModule.getRevision(),
                                         localIdentityName);
@@ -208,9 +212,9 @@ public class RuntimeBeanEntry {
      * in subtree.
      */
     private static AttributesRpcsAndRuntimeBeans extractSubtree(
-            String packageName, DataNodeContainer subtree,
-            TypeProviderWrapper typeProviderWrapper, Module currentModule,
-            Map<QName, Set<RpcDefinition>> identitiesToRpcs) {
+            final String packageName, final DataNodeContainer subtree,
+            final TypeProviderWrapper typeProviderWrapper, final Module currentModule,
+            final Map<QName, Set<RpcDefinition>> identitiesToRpcs) {
 
         List<AttributeIfc> attributes = Lists.newArrayList();
         // List<JavaAttribute> javaAttributes = new ArrayList<>();
@@ -258,7 +262,7 @@ public class RuntimeBeanEntry {
             if (ConfigConstants.RPC_CONTEXT_INSTANCE_EXTENSION_QNAME
                     .equals(unknownSchemaNode.getNodeType())) {
                 String localIdentityName = unknownSchemaNode.getNodeParameter();
-                QName identityQName = new QName(currentModule.getNamespace(),
+                QName identityQName = QName.create(currentModule.getNamespace(),
                         currentModule.getRevision(), localIdentityName);
                 Set<RpcDefinition> rpcDefinitions = identitiesToRpcs
                         .get(identityQName);
@@ -290,8 +294,8 @@ public class RuntimeBeanEntry {
                     for (DataSchemaNode childNode : sortAttributes(rpcDefinition.getInput()
                             .getChildNodes())) {
                         if (childNode.isAddedByUses() == false) { // skip
-                                                                  // refined
-                                                                  // context-instance
+                            // refined
+                            // context-instance
                             checkArgument(childNode instanceof LeafSchemaNode, "Unexpected type of rpc input type. "
                                     + "Currently only leafs and empty output nodes are supported, got " + childNode);
                             JavaAttribute javaAttribute = new JavaAttribute(
@@ -310,8 +314,8 @@ public class RuntimeBeanEntry {
                 attributes, rpcs);
     }
 
-    private static AttributeIfc getReturnTypeAttribute(DataSchemaNode child, TypeProviderWrapper typeProviderWrapper,
-                                                       String packageName) {
+    private static AttributeIfc getReturnTypeAttribute(final DataSchemaNode child, final TypeProviderWrapper typeProviderWrapper,
+            final String packageName) {
         if (child instanceof LeafSchemaNode) {
             LeafSchemaNode leaf = (LeafSchemaNode) child;
             return new JavaAttribute(leaf, typeProviderWrapper);
@@ -328,10 +332,10 @@ public class RuntimeBeanEntry {
         }
     }
 
-    private static Collection<DataSchemaNode> sortAttributes(Set<DataSchemaNode> childNodes) {
+    private static Collection<DataSchemaNode> sortAttributes(final Set<DataSchemaNode> childNodes) {
         final TreeSet<DataSchemaNode> dataSchemaNodes = new TreeSet<>(new Comparator<DataSchemaNode>() {
             @Override
-            public int compare(DataSchemaNode o1, DataSchemaNode o2) {
+            public int compare(final DataSchemaNode o1, final DataSchemaNode o2) {
                 return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
             }
         });
@@ -339,20 +343,21 @@ public class RuntimeBeanEntry {
         return dataSchemaNodes;
     }
 
-    private static boolean isInnerStateBean(DataSchemaNode child) {
+    private static boolean isInnerStateBean(final DataSchemaNode child) {
         for (UnknownSchemaNode unknownSchemaNode : child
                 .getUnknownSchemaNodes()) {
             if (unknownSchemaNode.getNodeType().equals(
-                    ConfigConstants.INNER_STATE_BEAN_EXTENSION_QNAME))
+                    ConfigConstants.INNER_STATE_BEAN_EXTENSION_QNAME)) {
                 return true;
+            }
         }
         return false;
     }
 
-    private static RuntimeBeanEntry createHierarchical(String packageName,
-            ListSchemaNode listSchemaNode,
-            TypeProviderWrapper typeProviderWrapper, Module currentModule,
-            Map<QName, Set<RpcDefinition>> identitiesToRpcs) {
+    private static RuntimeBeanEntry createHierarchical(final String packageName,
+            final ListSchemaNode listSchemaNode,
+            final TypeProviderWrapper typeProviderWrapper, final Module currentModule,
+            final Map<QName, Set<RpcDefinition>> identitiesToRpcs) {
 
         // supported are numeric types, strings, enums
         // get all attributes
@@ -387,10 +392,10 @@ public class RuntimeBeanEntry {
         return rbFromAttributes;
     }
 
-    private static RuntimeBeanEntry createRoot(String packageName,
-            DataNodeContainer nodeForReporting, String attributeYangName,
-            List<AttributeIfc> attributes, String javaNamePrefix,
-            List<RuntimeBeanEntry> children, Set<Rpc> rpcs) {
+    private static RuntimeBeanEntry createRoot(final String packageName,
+            final DataNodeContainer nodeForReporting, final String attributeYangName,
+            final List<AttributeIfc> attributes, final String javaNamePrefix,
+            final List<RuntimeBeanEntry> children, final Set<Rpc> rpcs) {
         return new RuntimeBeanEntry(packageName, nodeForReporting,
                 attributeYangName, javaNamePrefix, true,
                 Optional.<String> absent(), attributes, children, rpcs);
@@ -442,8 +447,8 @@ public class RuntimeBeanEntry {
         private final Set<Rpc> rpcs;
 
         public AttributesRpcsAndRuntimeBeans(
-                List<RuntimeBeanEntry> runtimeBeanEntries,
-                List<AttributeIfc> attributes, Set<Rpc> rpcs) {
+                final List<RuntimeBeanEntry> runtimeBeanEntries,
+                final List<AttributeIfc> attributes, final Set<Rpc> rpcs) {
             this.runtimeBeanEntries = runtimeBeanEntries;
             this.attributes = attributes;
             this.rpcs = rpcs;
@@ -472,8 +477,8 @@ public class RuntimeBeanEntry {
         private final AttributeIfc returnType;
         private final String yangName;
 
-        Rpc(AttributeIfc returnType, String name, String yangName,
-                List<JavaAttribute> parameters) {
+        Rpc(final AttributeIfc returnType, final String name, final String yangName,
+                final List<JavaAttribute> parameters) {
             this.returnType = returnType;
             this.name = name;
             this.parameters = parameters;
@@ -503,12 +508,12 @@ public class RuntimeBeanEntry {
         return getJavaNameOfRuntimeMXBean(javaNamePrefix);
     }
 
-    public String getFullyQualifiedName(String typeName) {
+    public String getFullyQualifiedName(final String typeName) {
         return FullyQualifiedNameHelper.getFullyQualifiedName(packageName,
                 typeName);
     }
 
-    private static String getJavaNameOfRuntimeMXBean(String javaNamePrefix) {
+    private static String getJavaNameOfRuntimeMXBean(final String javaNamePrefix) {
         return javaNamePrefix + MXBEAN_SUFFIX;
     }
 
index 5b0196cdda78d4354ab01c8cae3c156f1cfbbd64..fac4d5743229501fd7827269a8c810ac6b6f54a1 100644 (file)
@@ -185,7 +185,9 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
             OpenType<?> innerCompositeType;
 
             if(isDerivedType(innerTypeBaseType, innerType)) {
-                innerCompositeType = getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
+                innerCompositeType = baseInnerTypeDefinition instanceof UnionTypeDefinition ?
+                        getCompositeTypeForUnion(baseInnerTypeDefinition) :
+                        getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
             } else {
                 innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
             }
index dd44246867abb9af1e51bfe1bc5dbd8ea8c63f91..fab273c60093b529931e5f0ce4f02f9198327ff7 100644 (file)
@@ -7,7 +7,35 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
 import com.google.common.collect.Sets;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.SimpleType;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
@@ -25,32 +53,6 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.SimpleType;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
 public class ModuleMXBeanEntryTest extends AbstractYangTest {
 
     public static final String PACKAGE_NAME = "pack2";
@@ -95,7 +97,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
                 PACKAGE_NAME,identitiesToSIs));
         Map<String /* identity local name */, ModuleMXBeanEntry> namesToMBEs = ModuleMXBeanEntry
                 .create(jmxImplModule, modulesToSIEs, context, new TypeProviderWrapper(new TypeProviderImpl(context))
-                        , PACKAGE_NAME);
+                , PACKAGE_NAME);
         Map<String, AttributeIfc> attributes = namesToMBEs.get("impl-netconf")
                 .getAttributes();
 
@@ -120,7 +122,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
         assertThat(threadFactoryAttribute.getType().getName(), is("ObjectName"));
     }
 
-    private void assertCorrectAttributesSize(Map<String, ModuleMXBeanEntry> namesToMBEs, Map<String, AttributeIfc> attributes) {
+    private void assertCorrectAttributesSize(final Map<String, ModuleMXBeanEntry> namesToMBEs, final Map<String, AttributeIfc> attributes) {
         assertEquals(14, attributes.size());
         assertEquals(1, namesToMBEs.get("impl-netconf").getRuntimeBeans().size());
         assertEquals(2, namesToMBEs.get("impl-netconf").getRuntimeBeans().iterator().next().getAttributes().size());
@@ -131,10 +133,11 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
     }
 
     protected RuntimeBeanEntry findFirstByYangName(
-            Collection<RuntimeBeanEntry> runtimeBeans, String yangName) {
+            final Collection<RuntimeBeanEntry> runtimeBeans, final String yangName) {
         for (RuntimeBeanEntry rb : runtimeBeans) {
-            if (yangName.equals(rb.getYangName()))
+            if (yangName.equals(rb.getYangName())) {
                 return rb;
+            }
         }
         throw new IllegalArgumentException("Yang name not found:" + yangName
                 + " in " + runtimeBeans);
@@ -150,7 +153,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
                 "/config:modules/config:module/config:type=\"threadpool-dynamic\"");
     }
 
-    private void assertMatches(String prefix, String input) {
+    private void assertMatches(final String prefix, final String input) {
         RevisionAwareXPath whenConstraint = mock(RevisionAwareXPath.class);
         doReturn(input).when(whenConstraint).toString();
         Matcher output = ModuleMXBeanEntryBuilder.getWhenConditionMatcher(prefix,
@@ -181,7 +184,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
                         is((Type) Types.typeForClass(Long.class)));
             }
             // check dependency on thread factory
-            QName threadfactoryQName = new QName(THREADS_NAMESPACE,
+            QName threadfactoryQName = QName.create(THREADS_NAMESPACE,
                     THREADS_REVISION_DATE, "threadfactory");
             ServiceInterfaceEntry threadFactorySIEntry = modulesToSIEs
                     .get(threadfactoryQName);
@@ -192,7 +195,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
 
             DataSchemaNode mockedDataSchemaNode = mock(DataSchemaNode.class);
             doReturn(Collections.emptyList()).when(mockedDataSchemaNode)
-                    .getUnknownSchemaNodes();
+            .getUnknownSchemaNodes();
             doReturn(threadfactoryQName).when(mockedDataSchemaNode).getQName();
             AttributeIfc expectedDependencyAttribute = new DependencyAttribute(
                     mockedDataSchemaNode, threadFactorySIEntry,
@@ -200,7 +203,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest {
             assertThat(actualThreadFactory, is(expectedDependencyAttribute));
             assertThat(
                     dynamicThreadPool
-                            .getFullyQualifiedName("DynamicThreadPoolModuleMXBean"),
+                    .getFullyQualifiedName("DynamicThreadPoolModuleMXBean"),
                     is(PACKAGE_NAME + ".DynamicThreadPoolModuleMXBean"));
             assertThat(dynamicThreadPool.getNullableDescription(),
                     is("threadpool-dynamic description"));
index eed86951033bc5ec2aa5251e4f187ea0f0f3c1a9..f22edbf948f0ba93b77346cc0b55786fcc032ab5 100644 (file)
@@ -7,7 +7,12 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
 import com.google.common.collect.Sets;
+
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.text.ParseException;
@@ -20,13 +25,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+
 import org.hamcrest.CoreMatchers;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
 
 public class ServiceInterfaceEntryTest extends AbstractYangTest {
     public static final String PACKAGE_NAME = "packages.sis";
@@ -53,15 +56,15 @@ public class ServiceInterfaceEntryTest extends AbstractYangTest {
         }
     }
 
-    public static final QName EVENTBUS_QNAME = new QName(THREADS_NAMESPACE,
+    public static final QName EVENTBUS_QNAME = QName.create(THREADS_NAMESPACE,
             THREADS_REVISION_DATE, "eventbus");
-    public static final QName THREADFACTORY_QNAME = new QName(
+    public static final QName THREADFACTORY_QNAME = QName.create(
             THREADS_NAMESPACE, THREADS_REVISION_DATE, "threadfactory");
-    public static final QName THREADPOOL_QNAME = new QName(THREADS_NAMESPACE,
+    public static final QName THREADPOOL_QNAME = QName.create(THREADS_NAMESPACE,
             THREADS_REVISION_DATE, "threadpool");
-    public static final QName SCHEDULED_THREADPOOL_QNAME = new QName(
+    public static final QName SCHEDULED_THREADPOOL_QNAME = QName.create(
             THREADS_NAMESPACE, THREADS_REVISION_DATE, "scheduled-threadpool");
-    public static final QName SCHEDULED_EXECUTOR_SERVICE_QNAME = new QName(
+    public static final QName SCHEDULED_EXECUTOR_SERVICE_QNAME = QName.create(
             THREADS_NAMESPACE, THREADS_REVISION_DATE,
             "scheduled-executor-service");
     public static final String SCHEDULED_THREADPOOL_INTERFACE_NAME = "ScheduledThreadPoolServiceInterface";
@@ -133,9 +136,10 @@ public class ServiceInterfaceEntryTest extends AbstractYangTest {
                 + SCHEDULED_THREADPOOL_INTERFACE_NAME));
     }
 
-    static String trimInnerSpacesOrNull(String input) {
-        if (input == null)
+    static String trimInnerSpacesOrNull(final String input) {
+        if (input == null) {
             return null;
+        }
         return input.replaceAll("\\s{2,}", " ");
     }
 }
index 173227f0bc53ddf781534a36eb9df522cae6e636..c7fb73f3854cf5316c0efc7d3b39972f6978e767 100644 (file)
@@ -24,7 +24,7 @@
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-plugin-api</artifactId>
-      <version>3.0.5</version>
+      <version>${maven.plugin.api.version}</version>
     </dependency>
   </dependencies>
 </project>
index 8c8065dd673a05f772ed2e3b2405c835db188f56..247b3c07459ef67531d3085242e38f22c21b770a 100644 (file)
@@ -64,7 +64,7 @@
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
index 6a6a12d1de2499cb1956f02f456b158fd79f470e..8a23a6b5e60e64a6baaf20fd9d7d9712894f57dd 100644 (file)
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
-    <!-- scope is compile so all features (there is only one) are installed
-            into startup.properties and the feature repo itself is not installed -->
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>base-features</artifactId>
       <version>${project.version}</version>
-      <type>pom</type>
+      <type>kar</type>
       <scope>runtime</scope>
     </dependency>
     <dependency>
@@ -82,7 +80,7 @@
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>features-file</artifactId>
+      <artifactId>features-yangtools</artifactId>
       <version>${yangtools.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
index 502e1a261c713b1ea030ec014e663dcb82f4b51b..6c1ca421c257ab81807c20f4a939d556cb5338c6 100644 (file)
@@ -1,11 +1,17 @@
 # Extra packages to import from the boot class loader
 org.osgi.framework.system.packages.extra=org.apache.karaf.branding,sun.reflect,sun.reflect.misc,sun.misc,sun.nio.ch
 
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=325578
+# Extend the framework to avoid the resources to be presented with
+# a URL of type bundleresource: but to be presented as file:
+osgi.hook.configurators.include=org.eclipse.virgo.kernel.equinox.extensions.hooks.ExtensionsHookConfigurator
 
 # Embedded Tomcat configuration File
 org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml
 org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
 
+# Use Equinox as default OSGi Framework Implementation
+karaf.framework=equinox
 
 # Netconf startup configuration
 netconf.tcp.address=127.0.0.1
index 288fe629f806ff74a3c241a3d27e95a39e86fcf5..ca8c83c380aea4f1c51c801a3e846a82e364fbeb 100644 (file)
@@ -7,7 +7,7 @@ mvn\:org.ops4j.pax.swissbox/pax-swissbox-bnd/1.7.0 = 5
 mvn\:org.ops4j.pax.url/pax-url-maven-commons/1.6.0 = 5
 mvn\:org.ops4j.pax.url/pax-url-aether/1.6.0 = 5
 mvn\:org.ops4j.pax.url/pax-url-wrap/1.6.0 = 5
-#mvn\:javax.annotation/javax.annotation-api/1.2 = 5
+mvn\:javax.annotation/javax.annotation-api/1.2 = 5
 mvn\:org.ops4j.pax.logging/pax-logging-api/1.7.2 = 8
 mvn\:org.ops4j.pax.logging/pax-logging-service/1.7.2 = 8
 mvn\:org.apache.karaf.service/org.apache.karaf.service.guard/3.0.1 = 10
index 3916e05496ab2a40fc34e2adb71fd53839172ceb..ef3b5f4fd99e79a3449fcb5846cac80f6271b332 100644 (file)
           <artifactId>protocol-framework</artifactId>
         </dependency>
 
-        <!-- clustering -->
-        <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>remoterpc-routingtable.implementation</artifactId>
-          <version>${mdsal.version}</version>
-        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-binding-api</artifactId>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-netconf-connector</artifactId>
+          <artifactId>sal-inmemory-datastore</artifactId>
+          <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-remote</artifactId>
+          <artifactId>sal-netconf-connector</artifactId>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-remoterpc-connector</artifactId>
+          <artifactId>sal-remote</artifactId>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
         </plugins>
       </build>
     </profile>
+    <profile>
+      <id>docs</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>swagger-ui</artifactId>
+          <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+      </dependencies>
+    </profile>
   </profiles>
 </project>
index d872bfd47b229c4047d0bcfb05e98034474e93d3..afeddbfaabc6283fa9352cc543e23db43310871e 100644 (file)
@@ -15,6 +15,7 @@
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
                     <name>yang-schema-service</name>
                 </module>
+
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
                     <name>runtime-mapping-singleton</name>
                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
                         <name>binding-data-broker</name>
                     </data-broker>
+                    <root-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                        <name>binding-data-broker</name>
+                    </root-data-broker>
+                </module>
+
+
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">prefix:inmemory-config-datastore-provider</type>
+                    <name>config-store-service</name>
+                    <schema-service>
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                        <name>yang-schema-service</name>
+                    </schema-service>
+                </module>
+
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">prefix:inmemory-operational-datastore-provider</type>
+                    <name>operational-store-service</name>
+                    <schema-service>
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                        <name>yang-schema-service</name>
+                    </schema-service>
                 </module>
 
                 <!--
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
                     <name>inmemory-data-broker</name>
+
                     <schema-service>
                         <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
                         <name>yang-schema-service</name>
                     </schema-service>
+
+                   <config-data-store>
+                        <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+                        <name>config-store-service</name>
+                    </config-data-store>
+
+                    <operational-data-store>
+                        <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+                        <name>operational-store-service</name>
+                    </operational-data-store>
                 </module>
                 <module>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
                         <name>runtime-mapping-singleton</name>
                     </binding-mapping-service>
                 </module>
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-forwarded-data-broker</type>
+                    <name>binding-async-data-broker</name>
+                    <binding-forwarded-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                        <dom-async-broker>
+                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+                            <name>dom-broker</name>
+                        </dom-async-broker>
+                        <binding-mapping-service>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+                            <name>runtime-mapping-singleton</name>
+                        </binding-mapping-service>
+                    </binding-forwarded-data-broker>
+                </module>
             </modules>
             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                     <service>
                             <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
                         </instance>
                     </service>
+                <service>
+                    <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+                    <instance>
+                        <name>config-store-service</name>
+                        <provider>/modules/module[type='inmemory-config-datastore-provider'][name='config-store-service']</provider>
+                    </instance>
+                </service>
+                <service>
+                    <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+                    <instance>
+                        <name>operational-store-service</name>
+                        <provider>/modules/module[type='inmemory-operational-datastore-provider'][name='operational-store-service']</provider>
+                    </instance>
+                </service>
                     <service>
                         <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
                         <instance>
                         </instance>
                     </service>
 
+                    <service>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                        <instance>
+                            <name>binding-data-broker</name>
+                            <provider>/modules/module[type='binding-forwarded-data-broker'][name='binding-async-data-broker']</provider>
+                        </instance>
+                    </service>
+
                     <service>
                         <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
                         <instance>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store?module=opendaylight-config-dom-datastore&amp;revision=2014-06-17</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store?module=opendaylight-operational-dom-datastore&amp;revision=2014-06-17</capability>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider?module=opendaylight-inmemory-datastore-provider&amp;revision=2014-06-17</capability>
+
     </required-capabilities>
 </snapshot>
diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml
new file mode 100644 (file)
index 0000000..8fedbe4
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<snapshot>
+  <configuration>
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+        <!-- Netconf dispatcher to be used by all netconf-connectors --> 
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">prefix:netconf-client-dispatcher</type>
+          <name>global-netconf-dispatcher</name>
+          <boss-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+            <name>global-boss-group</name>
+          </boss-thread-group>
+          <worker-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+            <name>global-worker-group</name>
+          </worker-thread-group>
+          <timer xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-timer</type>
+            <name>global-timer</name>
+          </timer>
+        </module>
+
+        <!-- Thread factory to be used by all threadpools in netconf-connectors --> 
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">prefix:threadfactory-naming</type>
+          <name>global-netconf-processing-executor-threadfactory</name>
+          <name-prefix xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">remote-connector-processing-executor</name-prefix>
+        </module> 
+        <!-- Flexible threadpool for all netconf connectors, Max thread count is set to 4 --> 
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">prefix:threadpool-flexible</type>
+          <name>global-netconf-processing-executor</name>
+          <minThreadCount xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">1</minThreadCount>
+          <max-thread-count xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">4</max-thread-count>
+          <keepAliveMillis xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">600000</keepAliveMillis>
+          <threadFactory xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">
+            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
+            <name>global-netconf-processing-executor-threadfactory</name>
+          </threadFactory>
+        </module>  
+      </modules>
+
+      <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <service>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>
+          <instance>
+            <name>global-netconf-dispatcher</name>
+            <provider>/modules/module[type='netconf-client-dispatcher'][name='global-netconf-dispatcher']</provider>
+          </instance>
+        </service>
+        <service>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
+          <instance>
+            <name>global-netconf-processing-executor-threadfactory</name>
+            <provider>/modules/module[type='threadfactory-naming'][name='global-netconf-processing-executor-threadfactory']</provider>
+          </instance>
+        </service>
+        <service>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
+          <instance>
+            <name>global-netconf-processing-executor</name>
+            <provider>/modules/module[type='threadpool-flexible'][name='global-netconf-processing-executor']</provider>
+          </instance>
+        </service>
+      </services>
+
+    </data>
+  </configuration>
+  <required-capabilities>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher?module=odl-netconfig-client-cfg&amp;revision=2014-04-08</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&amp;revision=2013-04-05</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible?module=threadpool-impl-flexible&amp;revision=2013-12-01</capability>
+  </required-capabilities>
+</snapshot>
diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/02-clustering.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/02-clustering.xml
deleted file mode 100644 (file)
index c5f99fd..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- 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
--->
-<snapshot>
-    <configuration>
-        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                <module>
-                   <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">prefix:remote-zeromq-rpc-server</type>
-                   <name>remoter</name>
-                   <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
-                   <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
-                       <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
-                       <name>dom-broker</name>
-                   </dom-broker>
-               </module>
-            </modules>
-            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-            </services>
-        </data>
-    </configuration>
-
-    <required-capabilities>
-       <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&amp;revision=2013-10-28</capability>
-    </required-capabilities>
-</snapshot>
-
index 502bdebca26588cfc481793a0abd69731b6d708b..3958e185605e155f8b4b092e927ff5e8a679cbd1 100644 (file)
@@ -23,7 +23,7 @@
                     </rpc-registry>
 
                     <data-broker>
-                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
                         <name>binding-data-broker</name>
                     </data-broker>
                     
index b4b433dbca7c332787a8e14aa29e8b981dc308ed..7155eb88839b661372d83309a7dad27e8831c796 100644 (file)
   <configuration>
     <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-
-        <!-- Netconf dispatcher to be used by all netconf-connectors --> 
-        <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">prefix:netconf-client-dispatcher</type>
-          <name>global-netconf-dispatcher</name>
-          <boss-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
-            <name>global-boss-group</name>
-          </boss-thread-group>
-          <worker-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
-            <name>global-worker-group</name>
-          </worker-thread-group>
-          <timer xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-timer</type>
-            <name>global-timer</name>
-          </timer>
-        </module>
-
-        <!-- Netconf dispatcher to be used by all netconf-connectors --> 
-        <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">prefix:threadfactory-naming</type>
-          <name>global-netconf-processing-executor-threadfactory</name>
-          <name-prefix xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">remote-connector-processing-executor</name-prefix>
-        </module>  
-        <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">prefix:threadpool-flexible</type>
-          <name>global-netconf-processing-executor</name>
-          <minThreadCount xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">1</minThreadCount>
-          <max-thread-count xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">4</max-thread-count>
-          <keepAliveMillis xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">600000</keepAliveMillis>
-          <threadFactory xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">
-            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
-            <name>global-netconf-processing-executor-threadfactory</name>
-          </threadFactory>
-        </module>  
-
         <!-- Loopback connection to netconf server in controller using netconf-connector -->
         <module>
           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">prefix:sal-netconf-connector</type>
           </processing-executor>
         </module>
       </modules>
-
-      <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-        <service>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>
-          <instance>
-            <name>global-netconf-dispatcher</name>
-            <provider>/modules/module[type='netconf-client-dispatcher'][name='global-netconf-dispatcher']</provider>
-          </instance>
-        </service>
-        <service>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
-          <instance>
-            <name>global-netconf-processing-executor-threadfactory</name>
-            <provider>/modules/module[type='threadfactory-naming'][name='global-netconf-processing-executor-threadfactory']</provider>
-          </instance>
-        </service>
-        <service>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
-          <instance>
-            <name>global-netconf-processing-executor</name>
-            <provider>/modules/module[type='threadpool-flexible'][name='global-netconf-processing-executor']</provider>
-          </instance>
-        </service>
-      </services>
-
     </data>
   </configuration>
   <required-capabilities>
       <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf?module=odl-sal-netconf-connector-cfg&amp;revision=2013-10-28</capability>
-      <capability>urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher?module=odl-netconfig-client-cfg&amp;revision=2014-04-08</capability>
-      <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&amp;revision=2013-04-05</capability>
-      <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible?module=threadpool-impl-flexible&amp;revision=2013-12-01</capability>
   </required-capabilities>
 </snapshot>
index 72ccd02707ba7f5c76f064e5a16767a42f5fd37f..ce13e3396862a042a37aeb89dad5b3ca66d59094 100644 (file)
@@ -14,6 +14,7 @@ SET jvmMaxMemory=
 SET extraJVMOpts=
 SET consoleOpts=-console -consoleLog
 SET PID=
+SET JAVA_H=%JAVA_HOME%\bin\jps.exe
 
 :LOOP
 IF "%~1" NEQ "" (
@@ -61,7 +62,7 @@ IF "%~1" NEQ "" (
        GOTO :LOOP
     )
     IF "!CARG!"=="-status" (
-       for /F "TOKENS=1" %%G in ('%JAVA_HOME%\bin\jps.exe -lvV ^| find /I "opendaylight"') do (
+       for /F "TOKENS=1" %%G in ('""!JAVA_H!" -lvV ^| find /I "opendaylight""') do (
            set PID=%%G
        )
        if "!PID!" NEQ "" (
@@ -72,7 +73,7 @@ IF "%~1" NEQ "" (
        GOTO :EOF
     )
     IF "!CARG!"=="-stop" (
-       for /F "TOKENS=1" %%G in ('%JAVA_HOME%\bin\jps.exe -lvV ^| find /I "opendaylight"') do (
+       for /F "TOKENS=1" %%G in ('""!JAVA_H!" -lvV ^| find /I "opendaylight""') do (
            set PID=%%G
        )
        if "!PID!" NEQ "" (
@@ -89,18 +90,23 @@ IF "%~1" NEQ "" (
        GOTO :LOOP
     )
     IF "!CARG:~0,2!"=="-D" (
-       SET extraJVMOpts=%extraJVMOpts% !CARG!
+       SET extraJVMOpts=!extraJVMOpts! !CARG!
        SHIFT
        GOTO :LOOP
     )
     IF "!CARG:~0,2!"=="-X" (
-       SET extraJVMOpts=%extraJVMOpts% !CARG!
+       SET extraJVMOpts=!extraJVMOpts! !CARG!
        SHIFT
        GOTO :LOOP
     )
     IF "!CARG!"=="-help" (
-        ECHO "Usage: %0 [-jmx] [-jmxport <num>] [-debug] [-debugsuspend] [-debugport <num>] [-start] [-consoleport <num>]] [-stop] [-status] [-console] [-help] [<other args will automatically be used for the JVM>]"
-        ECHO Note: Enclose any JVM or System properties within double quotes.
+        SHIFT
+        SET CARG=%2
+        IF "!CARG!" NEQ "" (
+             CALL:!CARG!
+        ) ELSE (
+              CALL:helper
+         )
         GOTO :EOF
     )
 
@@ -110,28 +116,24 @@ IF "%~1" NEQ "" (
 
 IF "%debugEnabled%" NEQ "" (
     REM ECHO "DEBUG enabled"
-    SET extraJVMOpts=%extraJVMOpts% -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=%debugport%
+    SET extraJVMOpts=!extraJVMOpts! -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=%debugport%
 )
+
 IF "%debugSuspended%" NEQ "" (
     REM ECHO "DEBUG enabled suspended"
-    SET extraJVMOpts=%extraJVMOpts% -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%debugport%
+    SET extraJVMOpts=!extraJVMOpts! -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%debugport%
 )
 
 IF "%jvmMaxMemory%"=="" (
     SET jvmMaxMemory=-Xmx1G
-    ECHO *****************************************************************
-    ECHO JVM maximum memory was not defined. Setting maximum memory to 1G.
-    ECHO To define the maximum memory, specify the -Xmx setting on the
-    ECHO command line.
-    ECHO                    e.g. run.bat -Xmx1G
-    ECHO *****************************************************************"
+    ECHO Setting maximum memory to 1G.
 )
 
-SET extraJVMOpts=%extraJVMOpts%  %jvmMaxMemory%
+SET extraJVMOpts=!extraJVMOpts!  %jvmMaxMemory%
 
 IF "%jmxEnabled%" NEQ "" (
     REM ECHO "JMX enabled "
-    SET extraJVMOpts=%extraJVMOpts% -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=%jmxport% -Dcom.sun.management.jmxremote
+    SET extraJVMOpts=!extraJVMOpts! -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=%jmxport% -Dcom.sun.management.jmxremote
 )
 IF "%startEnabled%" NEQ "" (
     REM ECHO "START enabled "
@@ -139,7 +141,7 @@ IF "%startEnabled%" NEQ "" (
 )
 
 REM       Check if controller is already running
-for /F "TOKENS=1" %%G in ('%JAVA_HOME%\bin\jps.exe -lvV ^| find /I "opendaylight"') do (
+for /F "TOKENS=1" %%G in ('""!JAVA_H!" -lvV ^| find /I "opendaylight""') do (
     SET PID=%%G
 )
 if "!PID!" NEQ "" (
@@ -154,16 +156,125 @@ SET cp="%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar;%basedir%lib\or
 REM       Now set framework classpath
 SET fwcp="file:\%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar,file:\%basedir%lib\org.eclipse.virgo.kernel.equinox.extensions-3.6.0.RELEASE.jar,file:\%basedir%lib\org.eclipse.equinox.launcher-1.3.0.v20120522-1813.jar"
 
-SET RUN_CMD="%JAVA_HOME%\bin\java.exe" -Dopendaylight.controller %extraJVMOpts% -Djava.io.tmpdir="%basedir%work\tmp" -Djava.awt.headless=true -Dosgi.install.area=%basedir% -Dosgi.configuration.area="%basedir%configuration" -Dosgi.frameworkClassPath=%fwcp% -Dosgi.framework="file:\%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar" -classpath %cp% org.eclipse.equinox.launcher.Main %consoleOpts%
+SET RUN_CMD="%JAVA_HOME%\bin\java.exe" -Dopendaylight.controller !extraJVMOpts! -Djava.io.tmpdir="%basedir%work\tmp" -Djava.awt.headless=true -Dosgi.install.area=%basedir% -Dosgi.configuration.area="%basedir%configuration" -Dosgi.frameworkClassPath=%fwcp% -Dosgi.framework="file:\%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar" -classpath %cp% org.eclipse.equinox.launcher.Main %consoleOpts%
 
-ECHO %RUN_CMD%
+ECHO !RUN_CMD!
 
 if "%startEnabled%" NEQ "" (
-    START /B cmd /C CALL %RUN_CMD% > %basedir%\logs\controller.out 2>&1
+    START /B cmd /C CALL !RUN_CMD! > %basedir%\logs\controller.out 2>&1
     ECHO Running controller in the background.
+    EXIT /B 1
 ) else (
-    %RUN_CMD%
+    !RUN_CMD!
     EXIT /B %ERRORLEVEL%
 )
 
+:helper
+echo. For more information on a specific command, type -help command-name.
+echo.
+echo   jmx              ^[-jmx^]
+echo   jmxport          ^[-jmxport ^<num^>^] - DEFAULT is 1088
+echo   debug            ^[-debug^]
+echo   debugsuspend     ^[-debugsuspend^]
+echo   debugport        ^[-debugport ^<num^>^] - DEFAULT is 8000
+echo   start            ^[-start ^[^<console port^>^]^] - DEFAULT port is 2400
+echo   stop             ^[-stop^]
+echo   status           ^[-status^]
+echo   console          ^[-console^]
+echo   agentpath        ^[-agentpath:^<path to lib^>^]
+exit/B 1
+
+:debugsuspend
+ECHO.
+ECHO. debugsuspend     ^[-debugsuspend^]
+ECHO.
+ECHO. This command sets suspend on true in runjdwp in extra JVM options. If its true, VMStartEvent has a suspendPolicy of SUSPEND_ALL. If its false, VMStartEvent has a suspendPolicy of SUSPEND_NONE.
+ECHO.
+EXIT /B 1
+
+:debugport
+ECHO.
+ECHO. debugport        ^[-debugport ^<num^>^] - DEFAULT is 8000
+ECHO.
+ECHO. Set address for settings in runjdwp in extra JVM options.
+ECHO. The address is transport address for the connection.
+ECHO. The address has to be in the range ^[1024,65535^]. If the option was not call, port will be set to default value.
+ECHO.
+EXIT /B 1
+
+:jmxport
+ECHO.
+ECHO. jmxport          ^[-jmxport ^<num^>^] - DEFAULT is 1088
+ECHO.
+ECHO.    Set jmx port for com.sun.management.jmxremote.port in JMX support. Port has to be in the range ^[1024,65535^]. If this option was not call, port will be set to default value.
+ECHO.
+EXIT /B 1
+
+:debug
+ECHO.
+ECHO. debug            [-debug]
+ECHO.
+ECHO. Run ODL controller with -Xdebug and -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=^$^{debugport^}
+ECHO.
+ECHO.    -Xdebug enables debugging capabilities in the JVM which are used by the Java Virtual Machine Tools Interface (JVMTI). JVMTI is a low-level debugging interface used by debuggers and profiling tools.
+ECHO.
+ECHO.    -Xrunjdwp option loads the JPDA reference implementation of JDWP. This library resides in the target VM and uses JVMDI and JNI to interact with it. It uses a transport and the JDWP protocol to communicate with a separate debugger application.
+ECHO.
+ECHO. settings for -Xrunjdwp:
+ECHO.            transport -  name of the transport to use in connecting to debugger application
+ECHO.            server    -  if 'y', listen for a debugger application to attach; otherwise, attach to the debugger application at the specified address
+ECHO.                      -  if 'y' and no address is specified, choose a transport address at which to listen for a debugger application, and print the address to the standard output stream
+ECHO.            suspend   -  if 'y', VMStartEvent has a suspend Policy of SUSPEND_ALL
+ECHO.                      -  if 'n', VMStartEvent has a suspend policy of SUSPEND_NONE
+ECHO.            address   -  transport address for the connection
+ECHO.                      -  if server=n, attempt to attach to debugger application at this address
+ECHO.          -  if server=y, listen for a connection at this address
+ECHO.
+EXIT /B 1
+
+:jmx
+ECHO.
+ECHO. jmx              [-jmx]
+ECHO.
+ECHO. Add JMX support. With settings for extra JVM options: -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=^$^{jmxport^} -Dcom.sun.management.jmxremote
+ECHO. jmxport can by set with option -jmxport ^<num^>. Default num for the option is 1088.
+ECHO.
+EXIT /B 1
+
+:stop
+ECHO.
+ECHO. stop             ^[-stop^]
+ECHO.
+ECHO. If a controller is running, the command stop controller. Pid will be clean.
+ECHO.
+EXIT /B 1
+
+:status
+ECHO.
+ECHO. status           ^[-status^]
+ECHO.
+ECHO. Find out whether a controller is running and print it.
+ECHO.
+EXIT /B 1
+
+:start
+ECHO.
+ECHO. start            ^[-start ^[^<console port^>^]^]
+ECHO.
+ECHO.    If controller is not running, the command with argument^(for set port, where controller has start^) will start new controller on a port. The port has to be in the range ^[1024,65535^]. If this option was not call, port will be set to default value. Pid will be create.
+EXIT /B 1
+
+:console
+ECHO.
+ECHO. console          [-console]
+ECHO.     Default option.
+EXIT /B 1
+
+:agentpath
+ECHO.
+ECHO. agentpath        ^[-agentpath:^<path to lib^>^]
+ECHO.
+ECHO.    Agentpath option passes path to agent to jvm in order to load native agent library, e.g. yourkit profiler agent.
+EXIT /B 1
+
 
index fc58ed96e1b9fba37af9ff846621e107a3671440..62dc2ffa1a147859d300997293d47c2de5031bee 100644 (file)
@@ -49,7 +49,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
index 6c79e053e16b353a5e4bdd51f6e44a469aec8b26..168dd14d10e20aa54b08a30a5417ed94737810ff 100644 (file)
@@ -26,7 +26,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
index ba68d523af7faf32efd1e17ee040558f7a4b1323..d71858e5c36750cb33b206b6b6977ffcf604ffc8 100644 (file)
@@ -83,6 +83,7 @@ public class ComponentActivator extends ComponentActivatorAbstractBase {
 
     @Override
     protected void init() {
+        // TODO: deprecated, should be removed soon
         NodeIDType.registerIDType(NodeMapping.MD_SAL_TYPE, String.class);
         NodeConnectorIDType.registerIDType(NodeMapping.MD_SAL_TYPE, String.class, NodeMapping.MD_SAL_TYPE);
     }
@@ -232,8 +233,8 @@ public class ComponentActivator extends ComponentActivatorAbstractBase {
 
     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);
+        props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), NodeIDType.OPENFLOW);
+        props.put("protocolName", NodeIDType.OPENFLOW);
         return props;
     }
 }
index e5a9d3e5db87280717058126d6335114d9c2d2d5..acb54ba51aeb3bb6b3f00f2930d7e2c212755bf3 100644 (file)
@@ -163,6 +163,7 @@ public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, Sa
 
     @Override
     public void onFlowRemoved(final FlowRemoved notification) {
+        // notified upon remove flow rpc successfully invoked
         if (notification == null) {
             return;
         }
@@ -190,7 +191,25 @@ public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, Sa
 
     @Override
     public void onSwitchFlowRemoved(final SwitchFlowRemoved notification) {
-        // FIXME: unfinished?
+        // notified upon remove flow message from device arrives
+        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
@@ -228,7 +247,8 @@ public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, Sa
 
         flowId = UUID.randomUUID();
         cache.put(flow, flowId);
-        return this.writeFlowAsync(MDFlowMapping.toMDFlow(flow, flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+        return this.writeFlowAsync(MDFlowMapping.toMDFlow(flow, flowId.toString()), new NodeKey(
+                new NodeId(NodeMapping.OPENFLOW_ID_PREFIX + node.getID())));
     }
 
     private Future<RpcResult<TransactionStatus>> internalModifyFlowAsync(final Node node, final Flow oldFlow, final Flow newFlow, final long rid) {
@@ -242,7 +262,8 @@ public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, Sa
         }
 
         cache.put(newFlow, flowId);
-        return this.writeFlowAsync(MDFlowMapping.toMDFlow(newFlow, flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+        return this.writeFlowAsync(MDFlowMapping.toMDFlow(newFlow, flowId.toString()), new NodeKey(
+                new NodeId(NodeMapping.OPENFLOW_ID_PREFIX + node.getID())));
     }
 
     private Future<RpcResult<TransactionStatus>> internalRemoveFlowAsync(final Node node, final Flow adflow, final long rid) {
@@ -256,7 +277,8 @@ public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, Sa
 
         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()))));
+        modification.removeConfigurationData(flowPath(flow, new NodeKey(
+                new NodeId(NodeMapping.OPENFLOW_ID_PREFIX + node.getID()))));
         return modification.commit();
     }
 
index a879a36f8c23e6321f26c8fee0ec47a4569df2a9..36045cabf4bfefc672d3edde8001a75deba46385 100644 (file)
@@ -205,6 +205,7 @@ public class FromSalConversionsUtils {
             VlanIdBuilder vlanIDBuilder = new VlanIdBuilder();
             vlanIDBuilder.setVlanId(new VlanId((NetUtils
                     .getUnsignedShort((short) vlan.getValue()))));
+            vlanIDBuilder.setVlanIdPresent(true);
             vlanMatchBuild.setVlanId(vlanIDBuilder.build());
         }
 
index 28301654258407536725408981e986c79e1082d1..e2c13867754d187f26f9f9a1dc4414a2b4114572 100644 (file)
@@ -7,9 +7,12 @@
  */
 package org.opendaylight.controller.sal.compatibility;
 
+import com.google.common.collect.Iterables;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -26,6 +29,7 @@ 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.NodeTable;
+import org.opendaylight.controller.sal.core.NodeTable.NodeTableIDType;
 import org.opendaylight.controller.sal.core.Property;
 import org.opendaylight.controller.sal.core.UpdateType;
 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
@@ -489,7 +493,7 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI
                 }
 
                 try {
-                    final Node adNode = new Node(NodeMapping.MD_SAL_TYPE, NodeMapping.toADNodeId(node.getId()));
+                    final Node adNode = NodeMapping.toADNode(node.getId());
                     props.put(adNode, perNodePropMap);
                 } catch (ConstructionException e) {
                     LOG.warn("Failed to construct node for {}, skipping it", node, e);
@@ -572,7 +576,7 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI
         it.setLookupCount(tableStats.getPacketsLookedUp().getValue().longValue());
         it.setMatchedCount(tableStats.getPacketsMatched().getValue().longValue());
         it.setName(tableId.toString());
-        it.setNodeTable(new NodeTable(NodeMapping.MD_SAL_TYPE, tableId, node));
+        it.setNodeTable(new NodeTable(NodeTableIDType.OPENFLOW, tableId.byteValue(), node));
         return it;
     }
 
@@ -732,26 +736,45 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI
     }
 
     private boolean isKnownNodeConnector(final InstanceIdentifier<? extends Object> nodeConnectorIdentifier) {
-        final List<PathArgument> path = nodeConnectorIdentifier.getPath();
-        if (path.size() >= 3) {
-            final PathArgument nodePath = path.get(1);
-            final PathArgument nodeConnectorPath = path.get(2);
-            final List<PathArgument> nodeConnectors = nodeToNodeConnectorsMap.get(nodePath);
-            if (nodeConnectors != null) {
-                return nodeConnectors.contains(nodeConnectorPath);
-            }
+        final Iterator<PathArgument> it = nodeConnectorIdentifier.getPathArguments().iterator();
+
+        if (!it.hasNext()) {
+            return false;
         }
-        return false;
+        it.next();
+
+        if (!it.hasNext()) {
+            return false;
+        }
+        final PathArgument nodePath = it.next();
+
+        if (!it.hasNext()) {
+            return false;
+        }
+        final PathArgument nodeConnectorPath = it.next();
+
+        final List<PathArgument> nodeConnectors = nodeToNodeConnectorsMap.get(nodePath);
+        return nodeConnectors == null ? false :
+            nodeConnectors.contains(nodeConnectorPath);
     }
 
     private boolean recordNodeConnector(final InstanceIdentifier<? extends Object> nodeConnectorIdentifier) {
-        final List<PathArgument> path = nodeConnectorIdentifier.getPath();
-        if (path.size() < 3) {
+        final Iterator<PathArgument> it = nodeConnectorIdentifier.getPathArguments().iterator();
+
+        if (!it.hasNext()) {
             return false;
         }
+        it.next();
 
-        final PathArgument nodePath = path.get(1);
-        final PathArgument nodeConnectorPath = path.get(2);
+        if (!it.hasNext()) {
+            return false;
+        }
+        final PathArgument nodePath = it.next();
+
+        if (!it.hasNext()) {
+            return false;
+        }
+        final PathArgument nodeConnectorPath = it.next();
 
         synchronized (this) {
             List<PathArgument> nodeConnectors = this.nodeToNodeConnectorsMap.get(nodePath);
@@ -765,6 +788,6 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI
     }
 
     private List<PathArgument> removeNodeConnectors(final InstanceIdentifier<? extends Object> nodeIdentifier) {
-        return this.nodeToNodeConnectorsMap.remove(nodeIdentifier.getPath().get(1));
+        return this.nodeToNodeConnectorsMap.remove(Iterables.get(nodeIdentifier.getPathArguments(), 1));
     }
 }
index 67af3e428f8ff22caca6db1b9e60a892673314eb..9b5d0e887541da50e9a802811b84e046f3573b7d 100644 (file)
@@ -357,7 +357,7 @@ public final class MDFlowMapping {
     }
 
     public static Uri toUri(final NodeConnector connector) {
-        return new NodeConnectorId(((String) connector.getID()));
+        return new NodeConnectorId(NodeMapping.OPENFLOW_ID_PREFIX + connector.getNode().getID() + ":" + (connector.getID()));
     }
 
     public static MacAddress toMacAddress(final byte[] bytes) {
index f5701bfaf23419c9c2beaed1bde59f2037095c3c..a700c86b9c5c00f41a3ade60a650298adfc5883d 100644 (file)
@@ -11,7 +11,6 @@ import java.math.BigInteger;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
-
 import org.opendaylight.controller.sal.common.util.Arguments;
 import org.opendaylight.controller.sal.core.AdvertisedBandwidth;
 import org.opendaylight.controller.sal.core.Bandwidth;
@@ -19,8 +18,10 @@ import org.opendaylight.controller.sal.core.Buffers;
 import org.opendaylight.controller.sal.core.Capabilities;
 import org.opendaylight.controller.sal.core.Config;
 import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Description;
 import org.opendaylight.controller.sal.core.MacAddress;
 import org.opendaylight.controller.sal.core.Name;
+import org.opendaylight.controller.sal.core.Node.NodeIDType;
 import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
 import org.opendaylight.controller.sal.core.PeerBandwidth;
 import org.opendaylight.controller.sal.core.Property;
@@ -44,6 +45,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.fl
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
@@ -56,12 +58,21 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 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.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 
 public final class NodeMapping {
-    public final static String MD_SAL_TYPE = "MD_SAL";
+
+    private static final Logger LOG = LoggerFactory
+            .getLogger(NodeMapping.class);
+
+    /** openflow id prefix */
+    public static final String OPENFLOW_ID_PREFIX = "openflow:";
+
+    public final static String MD_SAL_TYPE = "MD_SAL_DEPRECATED";
 
     private final static Class<Node> NODE_CLASS = Node.class;
 
@@ -77,8 +88,19 @@ public final class NodeMapping {
     }
 
     public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) throws ConstructionException {
-        String aDNodeId = NodeMapping.toADNodeId(id);
-        return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, aDNodeId);
+        Long aDNodeId = openflowFullNodeIdToLong(NodeMapping.toADNodeId(id));
+        return new org.opendaylight.controller.sal.core.Node(NodeIDType.OPENFLOW, aDNodeId);
+    }
+
+    /**
+     * @param adNodeId
+     * @return
+     */
+    private static Long openflowFullNodeIdToLong(String adNodeId) {
+        if (adNodeId == null) {
+            return null;
+        }
+        return Long.valueOf(adNodeId.replaceFirst("^.*:", ""));
     }
 
     public static NodeId toNodeId(final InstanceIdentifier<?> id) {
@@ -87,7 +109,14 @@ public final class NodeMapping {
         return key.getId();
     }
 
+    /**
+     * @param nodeId containing "&lt;NodeTypeString&gt;:&lt;plainIntegerId&gt;"
+     * @return adNodeId form
+     */
     public static String toADNodeId(final NodeId nodeId) {
+        if (nodeId == null) {
+            return null;
+        }
         return nodeId.getValue();
     }
 
@@ -104,6 +133,28 @@ public final class NodeMapping {
         return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode);
     }
 
+    /**
+     * @param ncid nodeConnector identifier, e.g.: OF:21 or CTRL
+     * @param node
+     * @return nodeConnector attached to given node
+     * @throws ConstructionException
+     */
+    public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(
+            final NodeConnectorId ncid, final org.opendaylight.controller.sal.core.Node aDNode) throws ConstructionException {
+        NodeId nid = NodeMapping.toNodeId(aDNode);
+        String nodeConnectorType = NodeMapping.toNodeConnectorType(ncid, nid);
+        Object aDNodeConnectorId = NodeMapping.toADNodeConnectorId(ncid, nid);
+        return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode);
+    }
+
+    /**
+     * @param aDNode
+     * @return
+     */
+    private static NodeId toNodeId(org.opendaylight.controller.sal.core.Node aDNode) {
+        return new NodeId(aDNode.getType() + ":" +String.valueOf(aDNode.getID()));
+    }
+
     public static String toNodeConnectorType(final NodeConnectorId ncId, final NodeId nodeId) {
         if (ncId.equals(toLocalNodeConnectorId(nodeId))) {
             return NodeConnectorIDType.SWSTACK;
@@ -112,7 +163,7 @@ public final class NodeMapping {
         } else if (ncId.equals(toControllerNodeConnectorId(nodeId))) {
             return NodeConnectorIDType.CONTROLLER;
         }
-        return MD_SAL_TYPE;
+        return NodeConnectorIDType.OPENFLOW;
     }
 
     public static Object toADNodeConnectorId(final NodeConnectorId nodeConnectorId, final NodeId nodeId) {
@@ -121,7 +172,18 @@ public final class NodeMapping {
                 nodeConnectorId.equals(toControllerNodeConnectorId(nodeId))) {
             return org.opendaylight.controller.sal.core.NodeConnector.SPECIALNODECONNECTORID;
         }
-        return nodeConnectorId.getValue();
+
+        String nodeConnectorIdStripped = nodeConnectorId.getValue().replaceFirst("^.*:", "");
+        if (nodeConnectorIdStripped.matches("[0-9]+")) {
+            Short nodeConnectorIdVal = null;
+            try {
+                nodeConnectorIdVal = Short.valueOf(nodeConnectorIdStripped);
+            } catch (NumberFormatException e) {
+                LOG.warn("nodeConnectorId not supported (short): {}", nodeConnectorIdStripped, e);
+            }
+            return nodeConnectorIdVal;
+        }
+        return nodeConnectorIdStripped;
     }
 
     public static NodeId toAdNodeId(final NodeConnectorId nodeConnectorId) {
@@ -133,21 +195,21 @@ public final class NodeMapping {
     }
 
     public static NodeConnectorId toControllerNodeConnectorId(final NodeId node) {
-        return new NodeConnectorId(node.getValue() + ":" + 4294967293L);
+        return new NodeConnectorId(node.getValue() + ":" + OutputPortValues.CONTROLLER.toString());
     }
 
     public static NodeConnectorId toLocalNodeConnectorId(final NodeId node) {
-        return new NodeConnectorId(node.getValue() + ":" + 4294967294L);
+        return new NodeConnectorId(node.getValue() + ":" + OutputPortValues.LOCAL.toString());
     }
 
     public static NodeConnectorId toNormalNodeConnectorId(final NodeId node) {
-        return new NodeConnectorId(node.getValue() + ":" + 4294967290L);
+        return new NodeConnectorId(node.getValue() + ":" + OutputPortValues.NORMAL.toString());
     }
 
     public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) {
-        Preconditions.checkArgument(MD_SAL_TYPE.equals(node.getType()));
-        final String nodeId = Arguments.<String>checkInstanceOf(node.getID(), String.class);
-        final NodeKey nodeKey = new NodeKey(new NodeId(nodeId));
+        Preconditions.checkArgument(NodeIDType.OPENFLOW.equals(node.getType()));
+        final Long nodeId = Arguments.<Long>checkInstanceOf(node.getID(), Long.class);
+        final NodeKey nodeKey = new NodeKey(new NodeId(OPENFLOW_ID_PREFIX+nodeId));
         final InstanceIdentifier<Node> nodePath = InstanceIdentifier.builder(Nodes.class).child(NODE_CLASS, nodeKey).toInstance();
         return new NodeRef(nodePath);
     }
@@ -170,7 +232,8 @@ public final class NodeMapping {
                 nodeConnectorId = toControllerNodeConnectorId(nodeId);
             }
         } else {
-            nodeConnectorId = new NodeConnectorId(Arguments.<String>checkInstanceOf(nodeConnector.getID(), String.class));
+            nodeConnectorId = new NodeConnectorId(OPENFLOW_ID_PREFIX
+                    + Arguments.<Short>checkInstanceOf(nodeConnector.getID(), Short.class));
         }
         final NodeConnectorKey connectorKey = new NodeConnectorKey(nodeConnectorId);
         final InstanceIdentifier<NodeConnector> path = nodePath.child(NODECONNECTOR_CLASS, connectorKey);
@@ -184,11 +247,27 @@ public final class NodeMapping {
     public static HashSet<Property> toADNodeConnectorProperties(final NodeConnectorUpdated nc) {
         final FlowCapableNodeConnectorUpdated fcncu = nc.<FlowCapableNodeConnectorUpdated>getAugmentation(FlowCapableNodeConnectorUpdated.class);
         if (!Objects.equal(fcncu, null)) {
-            return NodeMapping.toADNodeConnectorProperties(fcncu);
+            HashSet<Property> adNodeConnectorProperties = NodeMapping.toADNodeConnectorProperties(fcncu);
+            return adNodeConnectorProperties;
         }
         return new HashSet<Property>();
     }
 
+    /**
+     * @param id
+     * @return node description in AD form, e.g.: OF|00:00:00:...:01
+     */
+    private static Description toADDescription(NodeRef nodeRef) {
+        Description desc;
+        try {
+            desc = new Description(toADNode(nodeRef).toString());
+        } catch (ConstructionException e) {
+            desc = new Description("none");
+            LOG.warn("node description extraction failed: {}", nodeRef);
+        }
+        return desc;
+    }
+
     public static HashSet<Property> toADNodeConnectorProperties(final NodeConnector nc) {
         final FlowCapableNodeConnector fcnc = nc.<FlowCapableNodeConnector>getAugmentation(FlowCapableNodeConnector.class);
         if (!Objects.equal(fcnc, null)) {
@@ -303,7 +382,9 @@ public final class NodeMapping {
     public static HashSet<Property> toADNodeProperties(final NodeUpdated nu) {
         final FlowCapableNodeUpdated fcnu = nu.getAugmentation(FlowCapableNodeUpdated.class);
         if (fcnu != null) {
-            return toADNodeProperties(fcnu, nu.getId());
+            HashSet<Property> adNodeProperties = toADNodeProperties(fcnu, nu.getId());
+            adNodeProperties.add(toADDescription(nu.getNodeRef()));
+            return adNodeProperties;
         }
         return new HashSet<org.opendaylight.controller.sal.core.Property>();
     }
@@ -342,7 +423,7 @@ public final class NodeMapping {
     }
 
     public static MacAddress toADMacAddress(final NodeId id) {
-        final String nodeId = id.getValue().replaceAll("openflow:", "");
+        final String nodeId = id.getValue().replaceAll(OPENFLOW_ID_PREFIX, "");
         BigInteger nodeIdRaw = new BigInteger(nodeId);
         long lNodeId = nodeIdRaw.longValue();
         byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId);
index e790c2c591a59d81c3f8068ee62eac36e5dea6f3..7bbf7f10e0c2be3c8246849d468fdbc0a8be5996 100644 (file)
@@ -95,6 +95,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 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.action.types.rev131112.address.address.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.GenericFlowAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
@@ -131,7 +133,38 @@ public class ToSalConversionsUtils {
 
     public static Flow toFlow(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source, Node node) {
         final Flow target = new Flow();
+        genericFlowToAdFlow(source, target);
 
+        target.setMatch(toMatch(source.getMatch()));
+
+        List<Action> actions = getAction(source);
+        if (actions != null) {
+            target.setActions(actionFrom(actions, node));
+        }
+
+        return target;
+    }
+
+    /**
+     * @param source notification, missing instructions
+     * @param node corresponding node where the flow change occured
+     * @return ad-sal node, build from given data
+     */
+    public static Flow toFlow(SwitchFlowRemoved source, Node node) {
+        final Flow target = new Flow();
+        genericFlowToAdFlow(source, target);
+
+        target.setMatch(toMatch(source.getMatch()));
+
+        return target;
+    }
+
+    /**
+     * @param source
+     * @param target
+     */
+    private static void genericFlowToAdFlow(GenericFlowAttributes source,
+            final Flow target) {
         Integer hardTimeout = source.getHardTimeout();
         if (hardTimeout != null) {
             target.setHardTimeout(hardTimeout.shortValue());
@@ -146,16 +179,7 @@ public class ToSalConversionsUtils {
         if (priority != null) {
             target.setPriority(priority.shortValue());
         }
-
-        target.setMatch(toMatch(source.getMatch()));
-
-        List<Action> actions = getAction(source);
-        if (actions != null) {
-            target.setActions(actionFrom(actions, node));
-        }
-
         target.setId(source.getCookie().getValue().longValue());
-        return target;
     }
 
     public static List<Action> getAction(
@@ -184,7 +208,8 @@ public class ToSalConversionsUtils {
                 Uri nodeConnector = ((OutputActionCase) sourceAction).getOutputAction().getOutputNodeConnector();
                 if (nodeConnector != null) {
                     //for (Uri uri : nodeConnectors) {
-                        targetAction.add(new Output(fromNodeConnectorRef(nodeConnector, node)));
+                    Uri fullNodeConnector = new Uri(node.getType()+":"+node.getID()+":"+nodeConnector.getValue());
+                        targetAction.add(new Output(fromNodeConnectorRef(fullNodeConnector, node)));
                     //}
                 }
             } else if (sourceAction instanceof PopMplsActionCase) {
@@ -352,17 +377,24 @@ public class ToSalConversionsUtils {
         return null;
     }
 
-    private static NodeConnector fromNodeConnectorRef(Uri uri, Node node) {
+    /**
+     * @param openflow nodeConnector uri
+     * @param node
+     * @return assembled nodeConnector
+     */
+    public static NodeConnector fromNodeConnectorRef(Uri uri, Node node) {
         NodeConnector nodeConnector = null;
         try {
-            nodeConnector = new NodeConnector(NodeMapping.MD_SAL_TYPE,node.getNodeIDString()+":"+uri.getValue(),node);
+            NodeConnectorId nodeConnectorId = new NodeConnectorId(uri.getValue());
+            nodeConnector = NodeMapping.toADNodeConnector(nodeConnectorId, node);
         } catch (ConstructionException e) {
-            e.printStackTrace();
+            LOG.warn("nodeConnector creation failed at node: {} with nodeConnectorUri: {}",
+                    node, uri.getValue());
         }
         return nodeConnector;
     }
 
-    public static Match toMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match source) {
+    public static Match toMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match source) {
         Match target = new Match();
         if (source != null) {
             fillFrom(target, source.getVlanMatch());
index 476a71a4acd0602a7b36ca41b664fcb00b3d5135..6bc669f60b17a378369ae837081c43cab38be244 100644 (file)
@@ -18,7 +18,9 @@ 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.Node.NodeIDType;
 import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
 import org.opendaylight.controller.sal.core.Property;
 import org.opendaylight.controller.sal.core.UpdateType;
 import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
@@ -93,20 +95,20 @@ public final class TopologyMapping {
     }
 
     public static String toADNodeId(final NodeId nodeId) {
-        return nodeId.getValue();
+        return nodeId.getValue().replaceFirst("^.*:", "");
     }
 
     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));
+        return new NodeConnector(NodeConnectorIDType.OPENFLOW, Short.valueOf(toADNodeConnectorId(source)), toADNode(nodeId));
     }
 
     public static String toADNodeConnectorId(final TpId nodeConnectorId) {
-        return nodeConnectorId.getValue();
+        return nodeConnectorId.getValue().replaceFirst("^.*:", "");
     }
 
     public static Node toADNode(final NodeId nodeId) throws ConstructionException {
         checkNotNull(nodeId);
-        return new Node(NodeMapping.MD_SAL_TYPE, toADNodeId(nodeId));
+        return new Node(NodeIDType.OPENFLOW, Long.valueOf(toADNodeId(nodeId)));
     }
 }
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/MDFlowMappingTest.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/MDFlowMappingTest.java
new file mode 100644 (file)
index 0000000..4e5f318
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * 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.test;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+
+/**
+ * test for {@link MDFlowMapping}
+ */
+public class MDFlowMappingTest {
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.compatibility.MDFlowMapping#toUri(org.opendaylight.controller.sal.core.NodeConnector)}.
+     * @throws ConstructionException
+     */
+    @Test
+    public void testToUri() throws ConstructionException {
+        Node node = new Node(NodeIDType.OPENFLOW, 41L);
+        NodeConnector connector = new NodeConnector(NodeConnectorIDType.OPENFLOW, (short) 42, node);
+        Uri observed = MDFlowMapping.toUri(connector );
+
+        Assert.assertEquals("openflow:41:42", observed.getValue());
+    }
+
+}
index b418e6dc25879050d7e9525e671cf080c0444401..8a23ebc933b54359ed7f4dc0d5b4786c05a17d21 100644 (file)
@@ -10,9 +10,18 @@ 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.ConstructionException;
 import org.opendaylight.controller.sal.core.MacAddress;
+import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+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.InstanceIdentifier;
 
 /**
  * test of {@link NodeMapping} utility class
@@ -67,8 +76,118 @@ public class NodeMappingTest {
         observed = NodeMapping.toAdNodeId(null);
         Assert.assertNull(observed);
 
-        observed = NodeMapping.toAdNodeId(new NodeConnectorId("MD_SAL|openflow:5:2"));
-        Assert.assertEquals("MD_SAL|openflow:5", observed.getValue());
+        observed = NodeMapping.toAdNodeId(new NodeConnectorId("openflow:5:2"));
+        Assert.assertEquals("openflow:5", observed.getValue());
     }
 
+    /**
+     * Test method for
+     * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toADNode(NodeId)}
+     * .
+     */
+    @Test
+    public void testToAdNode1() {
+        org.opendaylight.controller.sal.core.Node observed;
+        try {
+            observed = NodeMapping.toADNode((NodeId) null);
+        } catch (NullPointerException | ConstructionException e) {
+            //expected
+        }
+
+        NodeId nodeId = new NodeId("openflow:1");
+        try {
+            observed = NodeMapping.toADNode(nodeId);
+            Assert.assertEquals("OF|00:00:00:00:00:00:00:01", observed.toString());
+        } catch (ConstructionException e) {
+            Assert.fail("should succeed to construct Node: "+e.getMessage());
+        }
+    }
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toNodeConnectorType(NodeConnectorId, NodeId)}
+     * .
+     */
+    @Test
+    public void testToNodeConnectorType() {
+        NodeConnectorId ncId;
+        NodeId nodeId = buildNodeId("1");
+
+        ncId = buildNodeConnectorId("1", "42");
+        Assert.assertEquals(NodeConnectorIDType.OPENFLOW, NodeMapping.toNodeConnectorType(ncId, nodeId ));
+
+        ncId = buildNodeConnectorId("1", OutputPortValues.CONTROLLER.toString());
+        Assert.assertEquals(NodeConnectorIDType.CONTROLLER, NodeMapping.toNodeConnectorType(ncId, nodeId ));
+
+        ncId = buildNodeConnectorId("1", OutputPortValues.NORMAL.toString());
+        Assert.assertEquals(NodeConnectorIDType.HWPATH, NodeMapping.toNodeConnectorType(ncId, nodeId ));
+
+        ncId = buildNodeConnectorId("1", OutputPortValues.LOCAL.toString());
+        Assert.assertEquals(NodeConnectorIDType.SWSTACK, NodeMapping.toNodeConnectorType(ncId, nodeId ));
+    }
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toADNodeConnectorId(NodeConnectorId, NodeId)}
+     * .
+     */
+    @Test
+    public void testToAdNodeConnectorId() {
+        NodeConnectorId nodeConnectorId = buildNodeConnectorId("1", "2");
+        NodeId nodeId = buildNodeId("1");
+        Assert.assertEquals(Short.valueOf((short) 2), NodeMapping.toADNodeConnectorId(nodeConnectorId , nodeId));
+    }
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toNodeRef(Node)}
+     * .
+     * @throws ConstructionException
+     */
+    @Test
+    public void testToNodeRef() throws ConstructionException {
+        org.opendaylight.controller.sal.core.Node node = new org.opendaylight.controller.sal.core.Node(NodeIDType.OPENFLOW, 42L);
+        InstanceIdentifier<?> nodePath = NodeMapping.toNodeRef(node).getValue();
+
+        String observedId = nodePath.firstKeyOf(Node.class, NodeKey.class).getId().getValue();
+        Assert.assertEquals("openflow:42", observedId);
+    }
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toNodeConnectorRef(org.opendaylight.controller.sal.core.NodeConnector)}
+     * .
+     * @throws ConstructionException
+     */
+    @Test
+    public void testToNodeConnectorRef() throws ConstructionException {
+        org.opendaylight.controller.sal.core.Node node = new org.opendaylight.controller.sal.core.Node(NodeIDType.OPENFLOW, 42L);
+        org.opendaylight.controller.sal.core.NodeConnector nodeConnector =
+                new org.opendaylight.controller.sal.core.NodeConnector(
+                        NodeConnectorIDType.OPENFLOW, (short) 1, node);
+
+        InstanceIdentifier<?> nodeConnectorPath = NodeMapping.toNodeConnectorRef(nodeConnector ).getValue();
+        String observedNodeId = nodeConnectorPath.firstKeyOf(Node.class, NodeKey.class).getId().getValue();
+        Assert.assertEquals("openflow:42", observedNodeId);
+
+        String observedNodeConnectorId = nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue();
+        Assert.assertEquals("openflow:1", observedNodeConnectorId);
+    }
+
+    /**
+     * @param nodeId
+     * @param portId
+     * @return nodeConnectorId
+     */
+    public static NodeConnectorId buildNodeConnectorId(String nodeId, String portId) {
+        return new NodeConnectorId(NodeConnectorIDType.OPENFLOW+"|" + nodeId + ":" + portId);
+    }
+
+    /**
+     * @param id
+     * @return nodeId
+     */
+    public static NodeId buildNodeId(String id) {
+        return new NodeId(NodeConnectorIDType.OPENFLOW+"|" + id);
+    }
 }
index 4d3509769c5c791e399e6a98357759c6c009d952..0157bc0c6415835b8ed52a7add015d707d57a6d8 100644 (file)
@@ -22,6 +22,8 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import junit.framework.Assert;
+
 import org.junit.Test;
 import org.opendaylight.controller.sal.action.Flood;
 import org.opendaylight.controller.sal.action.FloodAll;
@@ -47,6 +49,7 @@ import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
@@ -182,6 +185,17 @@ public class TestToSalConversionsUtils {
         checkSalFlow(salFlow);
     }
 
+    /**
+     * test of {@link ToSalConversionsUtils#fromNodeConnectorRef(Uri, Node)}
+     * @throws ConstructionException
+     */
+    @Test
+    public void testFromNodeConnectorRef() throws ConstructionException {
+        Node node = new Node(NodeIDType.OPENFLOW, 42L);
+        NodeConnector nodeConnector = ToSalConversionsUtils.fromNodeConnectorRef(new Uri("1"), node);
+        Assert.assertEquals("OF|1@OF|00:00:00:00:00:00:00:2a", nodeConnector.toString());
+    }
+
     private void checkSalMatch(org.opendaylight.controller.sal.match.Match match, MtchType mt) {
         switch (mt) {
         case other:
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/topology/test/TopologyMappingTest.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/topology/test/TopologyMappingTest.java
new file mode 100644 (file)
index 0000000..b76370a
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ * 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.test;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyMapping;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+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;
+
+/**
+ * test for {@link TopologyMapping}
+ */
+public class TopologyMappingTest {
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.compatibility.topology.TopologyMapping#toADNodeId(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId)}.
+     */
+    @Test
+    public void testToADNodeId() {
+        NodeId nodeId = new NodeId("openflow:1");
+        String observedNodeId = TopologyMapping.toADNodeId(nodeId);
+
+        Assert.assertEquals("1", observedNodeId);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.compatibility.topology.TopologyMapping#toADNodeConnector(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId, org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId)}.
+     * @throws ConstructionException
+     */
+    @Test
+    public void testToADNodeConnector() throws ConstructionException {
+        NodeId nodeId = new NodeId("openflow:1");
+        TpId source = new TpId("foo:2");
+        NodeConnector observedNodeConnector = TopologyMapping.toADNodeConnector(source, nodeId);
+
+        Assert.assertEquals("OF|2@OF|00:00:00:00:00:00:00:01", observedNodeConnector.toString());
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.compatibility.topology.TopologyMapping#toADNodeConnectorId(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId)}.
+     */
+    @Test
+    public void testToADNodeConnectorId() {
+        TpId source = new TpId("foo:2");
+        String observedNodeConnectorId = TopologyMapping.toADNodeConnectorId(source);
+
+        Assert.assertEquals("2", observedNodeConnectorId);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.compatibility.topology.TopologyMapping#toADNode(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId)}.
+     * @throws ConstructionException
+     */
+    @Test
+    public void testToADNode() throws ConstructionException {
+        NodeId nodeId = new NodeId("openflow:1");
+        Node observedNode = TopologyMapping.toADNode(nodeId);
+
+        Assert.assertEquals("OF|00:00:00:00:00:00:00:01", observedNode.toString());
+    }
+
+}
index 9bd63d3c3bb5268d8d6e5142dd38da888a90b906..b3096e6478857aa1ca0286efda6c7a78912b4813 100644 (file)
@@ -18,7 +18,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>flow-management-compatibility</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 7e4190f1df4b7246da4a175d2efabb103282383a..6ed61e3024b9522dbc89d99a979f93fbcb147c7f 100644 (file)
  */
 package org.opendaylight.controller.md.inventory.manager;
 
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class FlowCapableInventoryProvider implements AutoCloseable {
+import com.google.common.base.Preconditions;
+
+class FlowCapableInventoryProvider implements AutoCloseable, Runnable {
+    private static final Logger LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider.class);
+    private static final int QUEUE_DEPTH = 500;
+    private static final int MAX_BATCH = 100;
+
+    private final BlockingQueue<InventoryOperation> queue = new LinkedBlockingDeque<>(QUEUE_DEPTH);
+    private final NotificationProviderService notificationService;
+    private final DataProviderService dataService;
+    private Registration<?> listenerRegistration;
+    private Thread thread;
 
-    private final static Logger LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider.class);
+    FlowCapableInventoryProvider(final DataProviderService dataService, final NotificationProviderService notificationService) {
+        this.dataService = Preconditions.checkNotNull(dataService);
+        this.notificationService = Preconditions.checkNotNull(notificationService);
+    }
+
+    void start() {
+        final NodeChangeCommiter changeCommiter = new NodeChangeCommiter(FlowCapableInventoryProvider.this);
+        this.listenerRegistration = this.notificationService.registerNotificationListener(changeCommiter);
 
-    private DataProviderService dataService;
-    private NotificationProviderService notificationService;
-    private Registration<NotificationListener> listenerRegistration;
-    private final NodeChangeCommiter changeCommiter = new NodeChangeCommiter(FlowCapableInventoryProvider.this);
+        thread = new Thread(this);
+        thread.setDaemon(true);
+        thread.setName("FlowCapableInventoryProvider");
+        thread.start();
 
-    public void start() {
-        this.listenerRegistration = this.notificationService.registerNotificationListener(this.changeCommiter);
         LOG.info("Flow Capable Inventory Provider started.");
     }
 
-    protected DataModificationTransaction startChange() {
-        DataProviderService _dataService = this.dataService;
-        return _dataService.beginTransaction();
+    void enqueue(final InventoryOperation op) {
+        try {
+            queue.put(op);
+        } catch (InterruptedException e) {
+            LOG.warn("Failed to enqueue operation {}", op, e);
+        }
     }
 
     @Override
-    public void close() {
-        try {
-            LOG.info("Flow Capable Inventory Provider stopped.");
-            if (this.listenerRegistration != null) {
+    public void close() throws InterruptedException {
+        LOG.info("Flow Capable Inventory Provider stopped.");
+        if (this.listenerRegistration != null) {
+            try {
                 this.listenerRegistration.close();
+            } catch (Exception e) {
+                LOG.error("Failed to stop inventory provider", e);
             }
-        } catch (Exception e) {
-            String errMsg = "Error by stop Flow Capable Inventory Provider.";
-            LOG.error(errMsg, e);
-            throw new RuntimeException(errMsg, e);
+            listenerRegistration = null;
         }
-    }
 
-    public DataProviderService getDataService() {
-        return this.dataService;
-    }
+        if (thread != null) {
+            thread.interrupt();
+            thread.join();
+            thread = null;
+        }
 
-    public void setDataService(final DataProviderService dataService) {
-        this.dataService = dataService;
-    }
 
-    public NotificationProviderService getNotificationService() {
-        return this.notificationService;
     }
 
-    public void setNotificationService(
-            final NotificationProviderService notificationService) {
-        this.notificationService = notificationService;
+    @Override
+    public void run() {
+        try {
+            for (;;) {
+                InventoryOperation op = queue.take();
+
+                final DataModificationTransaction tx = dataService.beginTransaction();
+                LOG.debug("New operations available, starting transaction {}", tx.getIdentifier());
+
+                int ops = 0;
+                do {
+                    op.applyOperation(tx);
+
+                    ops++;
+                    if (ops < MAX_BATCH) {
+                        op = queue.poll();
+                    } else {
+                        op = null;
+                    }
+                } while (op != null);
+
+                LOG.debug("Processed {} operations, submitting transaction {}", ops, tx.getIdentifier());
+
+                try {
+                    final RpcResult<TransactionStatus> result = tx.commit().get();
+                    if(!result.isSuccessful()) {
+                        LOG.error("Transaction {} failed", tx.getIdentifier());
+                    }
+                } catch (ExecutionException e) {
+                    LOG.warn("Failed to commit inventory change", e.getCause());
+                }
+            }
+        } catch (InterruptedException e) {
+            LOG.info("Processing interrupted, terminating", e);
+        }
+
+        // Drain all events, making sure any blocked threads are unblocked
+        while (!queue.isEmpty()) {
+            queue.poll();
+        }
     }
 }
index 6c06088fc4abefdeaaa859e52fc0f9a34da38edc..5bcae367e3e98a6270e01e270adbd2f231256fa9 100644 (file)
@@ -12,23 +12,32 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderCo
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class InventoryActivator extends AbstractBindingAwareProvider {
-
-    private static FlowCapableInventoryProvider provider = new FlowCapableInventoryProvider();
+    private static final Logger LOG = LoggerFactory.getLogger(InventoryActivator.class);
+    private FlowCapableInventoryProvider provider;
 
     @Override
     public void onSessionInitiated(final ProviderContext session) {
-        DataProviderService salDataService = session.<DataProviderService> getSALService(DataProviderService.class);
+        DataProviderService salDataService = session.getSALService(DataProviderService.class);
         NotificationProviderService salNotifiService =
-                session.<NotificationProviderService> getSALService(NotificationProviderService.class);
-        InventoryActivator.provider.setDataService(salDataService);
-        InventoryActivator.provider.setNotificationService(salNotifiService);
-        InventoryActivator.provider.start();
+                session.getSALService(NotificationProviderService.class);
+
+        provider = new FlowCapableInventoryProvider(salDataService, salNotifiService);
+        provider.start();
     }
 
     @Override
     protected void stopImpl(final BundleContext context) {
-        InventoryActivator.provider.close();
+        if (provider != null) {
+            try {
+                provider.close();
+            } catch (InterruptedException e) {
+                LOG.warn("Interrupted while waiting for shutdown", e);
+            }
+            provider = null;
+        }
     }
 }
@@ -1,20 +1,16 @@
-/*
+/**
  * 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;
+package org.opendaylight.controller.md.inventory.manager;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+
+interface InventoryOperation {
+
+    void applyOperation(DataModificationTransaction tx);
 
-/**
- * Factory interface for creating data trees.
- */
-public interface DataTreeFactory {
-    /**
-     * Create a new data tree.
-     *
-     * @return A data tree instance.
-     */
-    DataTree create();
 }
index 674ae398d3194d06e8a097d28be01a5b8d7a1ec3..3db3c93fcce11ccf46569514b901ef3c9c99e60d 100644 (file)
@@ -7,15 +7,11 @@
  */
 package org.opendaylight.controller.md.inventory.manager;
 
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
@@ -31,123 +27,90 @@ 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 org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-
-public class NodeChangeCommiter implements OpendaylightInventoryListener {
+import com.google.common.base.Preconditions;
 
-    protected final static Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
+class NodeChangeCommiter implements OpendaylightInventoryListener {
+    private static final Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
 
     private final FlowCapableInventoryProvider manager;
 
     public NodeChangeCommiter(final FlowCapableInventoryProvider manager) {
-        this.manager = manager;
-    }
-
-    public FlowCapableInventoryProvider getManager() {
-        return this.manager;
+        this.manager = Preconditions.checkNotNull(manager);
     }
 
     @Override
     public synchronized void onNodeConnectorRemoved(final NodeConnectorRemoved connector) {
-
-        final NodeConnectorRef ref = connector.getNodeConnectorRef();
-        final DataModificationTransaction it = this.getManager().startChange();
-        LOG.debug("removing node connector {} ", ref.getValue());
-        it.removeOperationalData(ref.getValue());
-        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
-        listenOnTransactionState(it.getIdentifier(), commitResult, "nodeConnector removal", ref.getValue());
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(final DataModificationTransaction tx) {
+                final NodeConnectorRef ref = connector.getNodeConnectorRef();
+                LOG.debug("removing node connector {} ", ref.getValue());
+                tx.removeOperationalData(ref.getValue());
+            }
+        });
     }
 
     @Override
     public synchronized void onNodeConnectorUpdated(final NodeConnectorUpdated connector) {
-
-        final NodeConnectorRef ref = connector.getNodeConnectorRef();
-        final FlowCapableNodeConnectorUpdated flowConnector = connector
-                .getAugmentation(FlowCapableNodeConnectorUpdated.class);
-        final DataModificationTransaction it = this.manager.startChange();
-        final NodeConnectorBuilder data = new NodeConnectorBuilder(connector);
-        NodeConnectorId id = connector.getId();
-        NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(id);
-        data.setKey(nodeConnectorKey);
-        boolean notEquals = (!Objects.equal(flowConnector, null));
-        if (notEquals) {
-            final FlowCapableNodeConnector augment = InventoryMapping.toInventoryAugment(flowConnector);
-            data.addAugmentation(FlowCapableNodeConnector.class, augment);
-        }
-        InstanceIdentifier<? extends Object> value = ref.getValue();
-        LOG.debug("updating node connector : {}.", value);
-        NodeConnector build = data.build();
-        it.putOperationalData((value), build);
-        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
-        listenOnTransactionState(it.getIdentifier(), commitResult, "nodeConnector update", ref.getValue());
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(final DataModificationTransaction tx) {
+                final NodeConnectorRef ref = connector.getNodeConnectorRef();
+                final NodeConnectorBuilder data = new NodeConnectorBuilder(connector);
+                data.setKey(new NodeConnectorKey(connector.getId()));
+
+                final FlowCapableNodeConnectorUpdated flowConnector = connector
+                        .getAugmentation(FlowCapableNodeConnectorUpdated.class);
+                if (flowConnector != null) {
+                    final FlowCapableNodeConnector augment = InventoryMapping.toInventoryAugment(flowConnector);
+                    data.addAugmentation(FlowCapableNodeConnector.class, augment);
+                }
+                InstanceIdentifier<? extends Object> value = ref.getValue();
+                LOG.debug("updating node connector : {}.", value);
+                NodeConnector build = data.build();
+                tx.putOperationalData(value, build);
+            }
+        });
     }
 
     @Override
     public synchronized void onNodeRemoved(final NodeRemoved node) {
-
-        final NodeRef ref = node.getNodeRef();
-        final DataModificationTransaction it = this.manager.startChange();
-        LOG.debug("removing node : {}", ref.getValue());
-        it.removeOperationalData((ref.getValue()));
-        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
-        listenOnTransactionState(it.getIdentifier(), commitResult, "node removal", ref.getValue());
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(final DataModificationTransaction tx) {
+                final NodeRef ref = node.getNodeRef();
+                LOG.debug("removing node : {}", ref.getValue());
+                tx.removeOperationalData((ref.getValue()));
+            }
+        });
     }
 
     @Override
     public synchronized void onNodeUpdated(final NodeUpdated node) {
-
-        final NodeRef ref = node.getNodeRef();
-        final FlowCapableNodeUpdated flowNode = node
-                .<FlowCapableNodeUpdated> getAugmentation(FlowCapableNodeUpdated.class);
-        final DataModificationTransaction it = this.manager.startChange();
-        final NodeBuilder nodeBuilder = new NodeBuilder(node);
-        nodeBuilder.setKey(new NodeKey(node.getId()));
-        boolean equals = Objects.equal(flowNode, null);
-        if (equals) {
+        final FlowCapableNodeUpdated flowNode = node.getAugmentation(FlowCapableNodeUpdated.class);
+        if (flowNode == null) {
             return;
         }
-        final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
-        nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
-        InstanceIdentifier<? extends Object> value = ref.getValue();
-        InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) value).builder();
-        InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder
-                .<FlowCapableNode> augmentation(FlowCapableNode.class);
-        final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
-        LOG.debug("updating node :{} ", path);
-        it.putOperationalData(path, augment);
-
-        Future<RpcResult<TransactionStatus>> commitResult = it.commit();
-        listenOnTransactionState(it.getIdentifier(), commitResult, "node update", ref.getValue());
-    }
-
-    /**
-     * @param txId transaction identificator
-     * @param future transaction result
-     * @param action performed by transaction
-     * @param nodeConnectorPath target value
-     */
-    private static void listenOnTransactionState(final Object txId, Future<RpcResult<TransactionStatus>> future,
-            final String action, final InstanceIdentifier<?> nodeConnectorPath) {
-        Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future),new FutureCallback<RpcResult<TransactionStatus>>() {
-
-            @Override
-            public void onFailure(Throwable t) {
-                LOG.error("Action {} [{}] failed for Tx:{}", action, nodeConnectorPath, txId, t);
-
-            }
 
+        manager.enqueue(new InventoryOperation() {
             @Override
-            public void onSuccess(RpcResult<TransactionStatus> result) {
-                if(!result.isSuccessful()) {
-                    LOG.error("Action {} [{}] failed for Tx:{}", action, nodeConnectorPath, txId);
-                }
+            public void applyOperation(final DataModificationTransaction tx) {
+                final NodeRef ref = node.getNodeRef();
+                final NodeBuilder nodeBuilder = new NodeBuilder(node);
+                nodeBuilder.setKey(new NodeKey(node.getId()));
+
+                final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
+                nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
+
+                @SuppressWarnings("unchecked")
+                InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
+                InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
+                final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
+                LOG.debug("updating node :{} ", path);
+                tx.putOperationalData(path, augment);
             }
         });
     }
index efe1ce3e3aaebad8d2b2a0a866d5d12392238a7c..deff6f17984cce55c8bcf97b43159f42852ebfec 100644 (file)
@@ -275,6 +275,17 @@ module opendaylight-match-types {
         }
     }
 
+    grouping "tunnel-ipv4-match-fields" {
+        leaf tunnel-ipv4-source {
+            description "IPv4 source tunnel endpoint address.";
+            type inet:ipv4-prefix;
+        }
+        leaf tunnel-ipv4-destination {
+            description "IPv4 destination tunnel endpoint address.";
+            type inet:ipv4-prefix;
+        }
+    }
+
     grouping match {
         leaf in-port {
             type inv:node-connector-id;
@@ -321,6 +332,9 @@ module opendaylight-match-types {
             case "arp-match" {
                 uses "arp-match-fields";
             }
+            case "tunnel-ipv4-match" {
+                uses "tunnel-ipv4-match-fields";
+            }
         }
 
         choice layer-4-match {
index f1cbd8dc29e7b2a5d0b29cef831c9c0068752a7d..9e880987524c3cee54d7f0486f7dce5df272ae17 100644 (file)
@@ -62,7 +62,10 @@ module opendaylight-port-types {
     grouping common-port {
 
         leaf port-number {
-            type uint32;
+            type union {
+                type uint32;
+                type string;
+            }
         }
         
         leaf hardware-address {
index c271f8f4d00a6b99318bc25baeae9251ac13ea97..393f6db9febbc0970b36c3dca1d8bf4d24ae674d 100644 (file)
@@ -192,6 +192,14 @@ module opendaylight-table-types {
         base match-field;
         description "TCP Flag Match";
     }
+    identity tunnel_ipv4_dst {
+        base match-field;
+        description "IPv4 destination tunnel endpoint address.";
+    }
+    identity tunnel_ipv4_src {
+        base match-field;
+        description "IPv4 source tunnel endpoint address.";
+    }
         
     grouping set-field-match {
         list set-field-match {
diff --git a/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang b/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang
deleted file mode 100644 (file)
index 1ccdfe8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-module opendaylight-inventory-config {
-    namespace "urn:opendaylight:inventory:config";
-    prefix inv-config;
-
-    import yang-ext {prefix ext; revision-date "2013-07-09";}
-    import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
-
-
-    revision "2013-08-19" {
-        description "Initial revision of Inventory model";
-    }
-    /** Base structure **/
-    container nodes {
-        list node {
-            key "id";
-            ext:context-instance "node-context";
-
-            uses inv:node;
-        }
-    }    
-}
index 8d4901d31b118659980148a20f79c0826b71a171..24dcfad02bf46b4e610aa1ad0bac0f76d9070671 100644 (file)
     <!-- Compability Packages -->
     <module>compatibility</module>
 
-    <!-- Clustering -->
-    <module>remoterpc-routingtable/implementation</module>
-    <module>sal-remoterpc-connector/implementation</module>
     <!-- Documentation -->
     <module>sal-rest-docgen</module>
 
-    <!--  Karaf feature -->
-    <module>feature</module>
+    <!--InMemory DOM DataStore-->
+    <module>sal-inmemory-datastore</module>
+
+    <!--sal-protocolbuffer-encoding-->
+    <module>sal-protocolbuffer-encoding</module>
+
+      <!--  Karaf feature -->
+      <module>feature</module>
 
   </modules>
 
@@ -88,7 +91,7 @@
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>findbugs-maven-plugin</artifactId>
-        <version>2.4.0</version>
+        <version>${findbugs.maven.plugin.version}</version>
         <configuration>
           <effort>Max</effort>
           <threshold>Low</threshold>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jdepend-maven-plugin</artifactId>
-        <version>2.0-beta-2</version>
+        <version>${jdepend.maven.plugin.version}</version>
       </plugin>
     </plugins>
   </reporting>
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/pom.xml b/opendaylight/md-sal/remoterpc-routingtable/implementation/pom.xml
deleted file mode 100644 (file)
index 8cab0b5..0000000
+++ /dev/null
@@ -1,97 +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>
-
-  <artifactId>remoterpc-routingtable.implementation</artifactId>
-  <packaging>bundle</packaging>
-  <dependencies>
-
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>clustering.services</artifactId>
-      <version>${clustering.services.version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>org.osgi</groupId>
-          <artifactId>org.osgi.compendium</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-connector-api</artifactId>
-      <version>${project.version}</version>
-    </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>
-
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${bundle.plugin.version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Export-Package>org.opendaylight.controller.sal.connector.remoterpc.api,
-                            org.opendaylight.controller.sal.connector.remoterpc.impl</Export-Package>
-            <Import-Package>javax.xml.bind.annotation,
-                            org.opendaylight.controller.sal.core,
-                            org.opendaylight.controller.sal.utils,
-                            org.opendaylight.controller.sal.packet,
-                            org.opendaylight.controller.sal.topology,
-                            org.opendaylight.controller.clustering.services,
-                            org.opendaylight.controller.md.sal.common.api.data,
-                            org.opendaylight.yangtools.yang.binding,
-                            org.osgi.service.component,
-                            org.slf4j,
-                            org.apache.felix.dm,
-                            org.apache.commons.lang3.builder,
-                            org.apache.commons.lang3.tuple,
-                            org.eclipse.osgi.framework.console,
-                            org.osgi.framework,
-                            javax.transaction,
-                            com.google.common.base,
-                            com.google.common.collect</Import-Package>
-            <Bundle-Activator>org.opendaylight.controller.sal.connector.remoterpc.impl.Activator</Bundle-Activator>
-          </instructions>
-          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <scm>
-    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-    <tag>HEAD</tag>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
-  </scm>
-</project>
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java
deleted file mode 100644 (file)
index c9b47ed..0000000
+++ /dev/null
@@ -1,18 +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.connector.remoterpc.api;
-
-import java.util.EventListener;
-
-public interface RouteChangeListener<I,R> extends EventListener {
-
-
-   void onRouteUpdated(I key, R new_value);
-
-   void onRouteDeleted(I key);
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java
deleted file mode 100644 (file)
index e5e314c..0000000
+++ /dev/null
@@ -1,113 +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.connector.remoterpc.api;
-
-import java.util.Set;
-
-public interface RoutingTable<I,R> {
-
-  /**
-   * Adds a network address for the route. If the route already exists,
-   * it throws <code>DuplicateRouteException</code>.
-   * This method would be used when registering a global service.
-   *
-   *
-   * @param routeId route identifier
-   * @param route network address
-   * @throws DuplicateRouteException
-   * @throws RoutingTableException
-   */
-  public void addGlobalRoute(I routeId, R route) throws  RoutingTableException, SystemException;
-
-  /**
-   * Remove the route.
-   * This method would be used when registering a global service.
-   * @param routeId
-   * @throws RoutingTableException
-   * @throws SystemException
-   */
-  public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException;
-
-  /**
-   * Adds a network address for the route. If the route already exists,
-   * it throws <code>DuplicateRouteException</code>.
-   * This method would be used when registering a global service.
-   *
-   *
-   * @param routeId route identifier
-   * @param route network address
-   * @throws DuplicateRouteException
-   * @throws RoutingTableException
-   */
-  public R getGlobalRoute(I routeId) throws  RoutingTableException, SystemException;
-
-  /**
-   * Adds a network address for the route. If address for route
-   * exists, appends the address to the list
-   *
-   * @param routeId route identifier
-   * @param route network address
-   * @throws RoutingTableException for any logical exception
-   * @throws SystemException
-   */
-  public void addRoute(I routeId, R route) throws RoutingTableException,SystemException;
-
-
-  /**
-   * Removes the network address for the route from routing table. If only
-   * one network address existed, remove the route as well.
-   * @param routeId
-   * @param route
-   */
-  public void removeRoute(I routeId, R route) throws RoutingTableException,SystemException;
-
-  /**
-   * Adds address for a set of route identifiers. If address for route
-   * exists, appends the address to the set.
-   *
-   * @param routeIds a set of routeIds
-   * @param route network address
-   * @throws RoutingTableException for any logical exception
-   * @throws SystemException
-   */
-  public void addRoutes(Set<I> routeIds, R route) throws  RoutingTableException,SystemException;
-
-  /**
-   * Removes address for a set of route identifiers.
-   *
-   * @param routeIds a set of routeIds
-   * @param route network address
-   * @throws RoutingTableException for any logical exception
-   * @throws SystemException
-   */
-  public void removeRoutes(Set<I> routeIds, R route) throws  RoutingTableException,SystemException;
-
-  /**
-   * Returns a set of network addresses associated with this route
-   * @param routeId
-   * @return
-   */
-  public Set<R> getRoutes(I routeId);
-
-
-  /**
-   * Returns the last inserted address from the list of network addresses
-   * associated with the route.
-   * @param routeId
-   * @return
-   */
-  public R getLastAddedRoute(I routeId);
-
-  public class DuplicateRouteException extends RoutingTableException {
-      public DuplicateRouteException(String message) {
-          super(message);
-      }
-
-  }
-
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java
deleted file mode 100644 (file)
index fc7f6f1..0000000
+++ /dev/null
@@ -1,52 +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.connector.remoterpc.api;
-
-/**
- * @author: syedbahm
- */
-public class RoutingTableException extends Exception {
-
-    /**
-     * Constructs a new exception with {@code null} as its detail message.
-     * The cause is not initialized, and may subsequently be initialized by a
-     * call to {@link #initCause}.
-     */
-    public RoutingTableException() {
-        super();
-    }
-
-    /**
-     * Constructs a new exception with the specified detail message.  The
-     * cause is not initialized, and may subsequently be initialized by
-     * a call to {@link #initCause}.
-     *
-     * @param message the detail message. The detail message is saved for
-     *                later retrieval by the {@link #getMessage()} method.
-     */
-    public RoutingTableException(String message) {
-        super(message);
-    }
-
-    /**
-     * Constructs a new exception with the specified detail message and
-     * cause.  <p>Note that the detail message associated with
-     * {@code cause} is <i>not</i> automatically incorporated in
-     * this exception's detail message.
-     *
-     * @param message the detail message (which is saved for later retrieval
-     *                by the {@link #getMessage()} method).
-     * @param cause   the cause (which is saved for later retrieval by the
-     *                {@link #getCause()} method).  (A <tt>null</tt> value is
-     *                permitted, and indicates that the cause is nonexistent or
-     *                unknown.)
-     */
-    public RoutingTableException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java
deleted file mode 100644 (file)
index 491858e..0000000
+++ /dev/null
@@ -1,56 +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.connector.remoterpc.api;
-
-/**
- * @author: syedbahm
- *
- */
-public class SystemException extends  Exception {
-    /**
-     * Constructs a new exception with {@code null} as its detail message.
-     * The cause is not initialized, and may subsequently be initialized by a
-     * call to {@link #initCause}.
-     */
-    public SystemException() {
-        super();
-    }
-
-    /**
-     * Constructs a new exception with the specified detail message.  The
-     * cause is not initialized, and may subsequently be initialized by
-     * a call to {@link #initCause}.
-     *
-     * @param message the detail message. The detail message is saved for
-     *                later retrieval by the {@link #getMessage()} method.
-     */
-    public SystemException(String message) {
-        super(message);
-    }
-
-    /**
-     * Constructs a new exception with the specified detail message and
-     * cause.  <p>Note that the detail message associated with
-     * {@code cause} is <i>not</i> automatically incorporated in
-     * this exception's detail message.
-     *
-     * @param message the detail message (which is saved for later retrieval
-     *                by the {@link #getMessage()} method).
-     * @param cause   the cause (which is saved for later retrieval by the
-     *                {@link #getCause()} method).  (A <tt>null</tt> value is
-     *                permitted, and indicates that the cause is nonexistent or
-     *                unknown.)
-     * @since 1.4
-     */
-    public SystemException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java
deleted file mode 100644 (file)
index a826a3c..0000000
+++ /dev/null
@@ -1,95 +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.connector.remoterpc.impl;
-
-import org.apache.felix.dm.Component;
-import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Set;
-
-/**
- * @author: syedbahm
- */
-public class Activator extends ComponentActivatorAbstractBase {
-
-    protected static final Logger logger = LoggerFactory
-            .getLogger(Activator.class);
-    private static final String CACHE_UPDATE_AWARE_REGISTRY_KEY = "cachenames" ;
-
-
-    /**
-     * Method which tells how many Global implementations are
-     * supported by the bundle. This way we can tune the number of
-     * components created. This components will be created ONLY at the
-     * time of bundle startup and will be destroyed only at time of
-     * bundle destruction, this is the major difference with the
-     * implementation retrieved via getImplementations where all of
-     * them are assumed to be in a container!
-     *
-     *
-     * @return The list of implementations the bundle will support,
-     * in Global version
-     */
-
-    @Override
-    protected Object[] getGlobalImplementations(){
-        logger.debug("Calling getGlobalImplementations to return:", RoutingTableImpl.class);
-        return new Object[] {
-                RoutingTableImpl.class
-        };
-    }
-
-    /**
-     * Configure the dependency for a given instance Global
-     *
-     * @param c Component assigned for this instance, this will be
-     * what will be used for configuration
-     * @param imp implementation to be configured
-     *
-     */
-    @Override
-    protected void configureGlobalInstance(Component c, Object imp){
-        if (imp.equals(RoutingTableImpl.class)) {
-            Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
-            Set<String> propSet = new HashSet<String>();
-            propSet.add(RoutingTableImpl.GLOBALRPC_CACHE);
-            propSet.add(RoutingTableImpl.RPC_CACHE);
-            props.put(CACHE_UPDATE_AWARE_REGISTRY_KEY, propSet);
-
-            c.setInterface(new String[] { RoutingTable.class.getName(),ICacheUpdateAware.class.getName()  }, props);
-            logger.debug("configureGlobalInstance adding dependency:", IClusterGlobalServices.class);
-
-
-            // RouteChangeListener services will be none or many so the
-            // dependency is optional
-            c.add(createServiceDependency()
-                    .setService(RouteChangeListener.class)
-                    .setCallbacks("setRouteChangeListener", "unsetRouteChangeListener")
-                    .setRequired(false));
-
-            //dependency is required as it provides us the caching support
-            c.add(createServiceDependency().setService(
-                    IClusterGlobalServices.class).setCallbacks(
-                    "setClusterGlobalServices",
-                    "unsetClusterGlobalServices").setRequired(true));
-
-        }
-    }
-
-
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java
deleted file mode 100644 (file)
index e242b0a..0000000
+++ /dev/null
@@ -1,464 +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.connector.remoterpc.impl;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-
-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.CacheListenerAddException;
-import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-
-public class RoutingTableImpl<I, R> implements RoutingTable<I, R>, ICacheUpdateAware<I, R> {
-
-    private final Logger log = LoggerFactory.getLogger(RoutingTableImpl.class);
-
-    private IClusterGlobalServices clusterGlobalServices = null;
-
-    private ConcurrentMap<I,R> globalRpcCache = null;
-    private ConcurrentMap<I, LinkedHashSet<R>> rpcCache = null;  //need routes to ordered by insert-order
-
-    public static final String GLOBALRPC_CACHE = "remoterpc_routingtable.globalrpc_cache";
-    public static final String RPC_CACHE = "remoterpc_routingtable.rpc_cache";
-
-    public RoutingTableImpl() {
-    }
-
-    @Override
-    public R getGlobalRoute(final I routeId) throws RoutingTableException, SystemException {
-        Preconditions.checkNotNull(routeId, "getGlobalRoute: routeId cannot be null!");
-        return globalRpcCache.get(routeId);
-    }
-
-    @Override
-    public void addGlobalRoute(final I routeId, final R route) throws RoutingTableException, SystemException {
-        Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
-        Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
-        try {
-
-            log.debug("addGlobalRoute: adding  a new route with id[{}] and value [{}]", routeId, route);
-            clusterGlobalServices.tbegin();
-            if (globalRpcCache.putIfAbsent(routeId, route) != null) {
-                throw new DuplicateRouteException(" There is already existing route " + routeId);
-            }
-            clusterGlobalServices.tcommit();
-
-        } catch (NotSupportedException | HeuristicRollbackException | RollbackException | HeuristicMixedException e) {
-            throw new RoutingTableException("Transaction error - while trying to create route id="
-                    + routeId + "with route" + route, e);
-        } catch (javax.transaction.SystemException e) {
-            throw new SystemException("System error occurred - while trying to create with value", e);
-        }
-
-    }
-
-    @Override
-    public void removeGlobalRoute(final I routeId) throws RoutingTableException, SystemException {
-        Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
-        try {
-            log.debug("removeGlobalRoute: removing  a new route with id [{}]", routeId);
-
-            clusterGlobalServices.tbegin();
-            globalRpcCache.remove(routeId);
-            clusterGlobalServices.tcommit();
-
-        } catch (NotSupportedException | HeuristicRollbackException | RollbackException | HeuristicMixedException e) {
-            throw new RoutingTableException("Transaction error - while trying to remove route id="
-                    + routeId, e);
-        } catch (javax.transaction.SystemException e) {
-            throw new SystemException("System error occurred - while trying to remove with value", e);
-        }
-    }
-
-
-    @Override
-    public Set<R> getRoutes(final I routeId) {
-        Preconditions.checkNotNull(routeId, "getRoutes: routeId cannot be null!");
-        Set<R> routes = rpcCache.get(routeId);
-
-        if (routes == null) {
-            return Collections.emptySet();
-        }
-
-        return ImmutableSet.copyOf(routes);
-    }
-
-
-
-    @Override
-    public R getLastAddedRoute(final I routeId) {
-
-        Set<R> routes = getRoutes(routeId);
-
-        if (routes.isEmpty()) {
-            return null;
-        }
-
-        R route = null;
-        Iterator<R> iter = routes.iterator();
-        while (iter.hasNext()) {
-            route = iter.next();
-        }
-
-        return route;
-    }
-
-    @Override
-    public void addRoute(final I routeId, final R route)  throws RoutingTableException, SystemException {
-        Preconditions.checkNotNull(routeId, "addRoute: routeId cannot be null");
-        Preconditions.checkNotNull(route, "addRoute: route cannot be null");
-
-        try{
-            clusterGlobalServices.tbegin();
-            log.debug("addRoute: adding a route with k/v [{}/{}]", routeId, route);
-            threadSafeAdd(routeId, route);
-            clusterGlobalServices.tcommit();
-
-        } catch (NotSupportedException | HeuristicRollbackException | RollbackException | HeuristicMixedException e) {
-            throw new RoutingTableException("Transaction error - while trying to remove route id="
-                    + routeId, e);
-        } catch (javax.transaction.SystemException e) {
-            throw new SystemException("System error occurred - while trying to remove with value", e);
-        }
-    }
-
-    @Override
-    public void addRoutes(final Set<I> routeIds, final R route) throws RoutingTableException, SystemException {
-        Preconditions.checkNotNull(routeIds, "addRoutes: routeIds must not be null");
-        for (I routeId : routeIds){
-            addRoute(routeId, route);
-        }
-    }
-
-    @Override
-    public void removeRoute(final I routeId, final R route) throws RoutingTableException, SystemException {
-        Preconditions.checkNotNull(routeId, "removeRoute: routeId cannot be null!");
-        Preconditions.checkNotNull(route, "removeRoute: route cannot be null!");
-
-        LinkedHashSet<R> routes = rpcCache.get(routeId);
-        if (routes == null) {
-            return;
-        }
-
-        try {
-            log.debug("removeRoute: removing  a new route with k/v [{}/{}]", routeId, route);
-
-            clusterGlobalServices.tbegin();
-            threadSafeRemove(routeId, route);
-            clusterGlobalServices.tcommit();
-
-        } catch (NotSupportedException | HeuristicRollbackException | RollbackException | HeuristicMixedException e) {
-            throw new RoutingTableException("Transaction error - while trying to remove route id="
-                    + routeId, e);
-        } catch (javax.transaction.SystemException e) {
-            throw new SystemException("System error occurred - while trying to remove with value", e);
-        }
-    }
-
-    @Override
-    public void removeRoutes(final Set<I> routeIds, final R route) throws RoutingTableException, SystemException {
-        Preconditions.checkNotNull(routeIds, "removeRoutes: routeIds must not be null");
-        for (I routeId : routeIds){
-            removeRoute(routeId, route);
-        }
-    }
-
-    /**
-     * This method guarantees that no 2 thread over write each other's changes.
-     * Just so that we dont end up in infinite loop, it tries for 100 times then throw
-     */
-    private void threadSafeAdd(final I routeId, final R route) {
-
-        for (int i=0;i<100;i++){
-
-            LinkedHashSet<R> updatedRoutes = new LinkedHashSet<>();
-            updatedRoutes.add(route);
-            LinkedHashSet<R> oldRoutes = rpcCache.putIfAbsent(routeId, updatedRoutes);
-            if (oldRoutes == null) {
-                return;
-            }
-
-            updatedRoutes = new LinkedHashSet<>(oldRoutes);
-            updatedRoutes.add(route);
-
-            if (rpcCache.replace(routeId, oldRoutes, updatedRoutes)) {
-                return;
-            }
-        }
-        //the method did not already return means it failed to add route in 10 attempts
-        throw new IllegalStateException("Failed to add route [" + routeId + "]");
-    }
-
-    /**
-     * This method guarantees that no 2 thread over write each other's changes.
-     * Just so that we dont end up in infinite loop, it tries for 10 times then throw
-     */
-    private void threadSafeRemove(final I routeId, final R route) {
-        LinkedHashSet<R> updatedRoutes = null;
-        for (int i=0;i<10;i++){
-            LinkedHashSet<R> oldRoutes = rpcCache.get(routeId);
-
-            // if route to be deleted is the only entry in the set then remove routeId from the cache
-            if ((oldRoutes.size() == 1) && oldRoutes.contains(route)){
-                rpcCache.remove(routeId);
-                return;
-            }
-
-            // if there are multiple routes for this routeId, remove the route to be deleted only from the set.
-            updatedRoutes = new LinkedHashSet<>(oldRoutes);
-            updatedRoutes.remove(route);
-            if (rpcCache.replace(routeId, oldRoutes, updatedRoutes)) {
-                return;
-            }
-
-        }
-        //the method did not already return means it failed to remove route in 10 attempts
-        throw new IllegalStateException("Failed to remove route [" + routeId + "]");
-    }
-
-
-    //    /**
-    //     * @deprecated doesn't do anything will be removed once listeners used
-    //     *             whiteboard pattern Registers listener for sending any change
-    //     *             notification
-    //     * @param listener
-    //     */
-    //    @Override
-    //    public void registerRouteChangeListener(RouteChangeListener listener) {
-    //
-    //    }
-
-    //    public void setRouteChangeListener(RouteChangeListener rcl) {
-    //        if(rcl != null){
-    //            routeChangeListeners.add(rcl);
-    //        }else{
-    //            log.warn("setRouteChangeListener called with null listener");
-    //        }
-    //    }
-    //
-    //    public void unSetRouteChangeListener(RouteChangeListener rcl) {
-    //        if(rcl != null){
-    //         routeChangeListeners.remove(rcl);
-    //        }else{
-    //            log.warn("unSetRouteChangeListener called with null listener");
-    //        }
-    //    }
-
-    /**
-     * Returning the set of route change listeners for Unit testing Note: the
-     * package scope is default
-     *
-     * @return List of registered RouteChangeListener<I,R> listeners
-     */
-    //    Set<RouteChangeListener> getRegisteredRouteChangeListeners() {
-    //        return routeChangeListeners;
-    //    }
-    public void setClusterGlobalServices(final IClusterGlobalServices clusterGlobalServices) {
-        this.clusterGlobalServices = clusterGlobalServices;
-    }
-
-    public void unsetClusterGlobalServices(final IClusterGlobalServices clusterGlobalServices) {
-        if ((clusterGlobalServices != null) && (this.clusterGlobalServices.equals(clusterGlobalServices))) {
-            this.clusterGlobalServices = null;
-        }
-    }
-
-    /**
-     * Finds OR Creates clustered cache for Global RPCs
-     *
-     * @throws CacheExistException       -- cluster global services exception when cache exist
-     * @throws CacheConfigException      -- cluster global services exception during cache config
-     * @throws CacheListenerAddException -- cluster global services exception during adding of listener
-     */
-
-    @SuppressWarnings("unchecked")
-    void findOrCreateGlobalRpcCache() throws CacheExistException, CacheConfigException,
-    CacheListenerAddException {
-        // TBD: HOW DO WE DECIDE ON PROPERTIES OF THE CACHE i.e. what duration it
-        // should be caching?
-
-        // let us check here if the cache already exists -- if so don't create
-        if (!clusterGlobalServices.existCache(GLOBALRPC_CACHE)) {
-
-            globalRpcCache = (ConcurrentMap<I,R>) clusterGlobalServices.createCache(GLOBALRPC_CACHE,
-                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-            log.debug("Cache created [{}] ", GLOBALRPC_CACHE);
-
-        } else {
-            globalRpcCache = (ConcurrentMap<I,R>) clusterGlobalServices.getCache(GLOBALRPC_CACHE);
-            log.debug("Cache exists [{}] ", GLOBALRPC_CACHE);
-        }
-    }
-
-    /**
-     * Finds OR Creates clustered cache for Routed RPCs
-     *
-     * @throws CacheExistException       -- cluster global services exception when cache exist
-     * @throws CacheConfigException      -- cluster global services exception during cache config
-     * @throws CacheListenerAddException -- cluster global services exception during adding of listener
-     */
-
-    @SuppressWarnings("unchecked")
-    void findOrCreateRpcCache() throws CacheExistException, CacheConfigException,
-    CacheListenerAddException {
-        // TBD: HOW DO WE DECIDE ON PROPERTIES OF THE CACHE i.e. what duration it
-        // should be caching?
-
-        if (clusterGlobalServices.existCache(RPC_CACHE)){
-            rpcCache = (ConcurrentMap<I,LinkedHashSet<R>>) clusterGlobalServices.getCache(RPC_CACHE);
-            log.debug("Cache exists [{}] ", RPC_CACHE);
-            return;
-        }
-
-        //cache doesnt exist, create one
-        rpcCache = (ConcurrentMap<I,LinkedHashSet<R>>) clusterGlobalServices.createCache(RPC_CACHE,
-                EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-        log.debug("Cache created [{}] ", RPC_CACHE);
-    }
-
-
-    /**
-     * Function called by the dependency manager when all the required
-     * dependencies are satisfied
-     */
-    void init(final Component c) {
-        try {
-
-            findOrCreateGlobalRpcCache();
-            findOrCreateRpcCache();
-
-        } catch (CacheExistException|CacheConfigException|CacheListenerAddException e) {
-            throw new IllegalStateException("could not construct routing table cache");
-        }
-    }
-
-    /**
-     * Useful for unit testing <note>It has package
-     * scope</note>
-     */
-    ConcurrentMap<I, R> getGlobalRpcCache() {
-        return this.globalRpcCache;
-    }
-
-    /**
-     * Useful for unit testing <note>It has package
-     * scope</note>
-     */
-    ConcurrentMap<I, LinkedHashSet<R>> getRpcCache() {
-        return this.rpcCache;
-    }
-
-    /**
-     * This is used from integration test NP rest API to check out the result of the
-     * cache population
-     * <Note> For testing purpose only-- use it wisely</Note>
-     *
-     * @return
-     */
-    public String dumpGlobalRpcCache() {
-        Set<Map.Entry<I, R>> cacheEntrySet = this.globalRpcCache.entrySet();
-        StringBuilder sb = new StringBuilder();
-        for (Map.Entry<I, R> entry : cacheEntrySet) {
-            sb.append("Key:").append(entry.getKey()).append("---->Value:")
-            .append((entry.getValue() != null) ? entry.getValue() : "null")
-            .append("\n");
-        }
-        return sb.toString();
-    }
-
-    public String dumpRpcCache() {
-        Set<Map.Entry<I, LinkedHashSet<R>>> cacheEntrySet = this.rpcCache.entrySet();
-        StringBuilder sb = new StringBuilder();
-        for (Map.Entry<I, LinkedHashSet<R>> entry : cacheEntrySet) {
-            sb.append("Key:").append(entry.getKey()).append("---->Value:")
-            .append((entry.getValue() != null) ? entry.getValue() : "null")
-            .append("\n");
-        }
-        return sb.toString();
-    }
-    /**
-     * Invoked when a new entry is available in the cache, the key is only
-     * provided, the value will come as an entryUpdate invocation
-     *
-     * @param key         Key for the entry just created
-     * @param cacheName   name of the cache for which update has been received
-     * @param originLocal true if the event is generated from this node
-     */
-    @Override
-    public void entryCreated(final I key, final String cacheName, final boolean originLocal) {
-        // TBD: do we require this.
-        if (log.isDebugEnabled()) {
-            log.debug("RoutingTableUpdates: entryCreated  routeId = " + key + " cacheName=" + cacheName);
-        }
-    }
-
-    /**
-     * Called anytime a given entry is updated
-     *
-     * @param key         Key for the entry modified
-     * @param new_value   the new value the key will have
-     * @param cacheName   name of the cache for which update has been received
-     * @param originLocal true if the event is generated from this node
-     */
-    @Override
-    public void entryUpdated(final I key, final R new_value, final String cacheName, final boolean originLocal) {
-        if (log.isDebugEnabled()) {
-            log.debug("RoutingTableUpdates: entryUpdated  routeId = " + key + ",value = " + new_value
-                    + " ,cacheName=" + cacheName + " originLocal=" + originLocal);
-        }
-        //        if (!originLocal) {
-        //            for (RouteChangeListener rcl : routeChangeListeners) {
-        //                rcl.onRouteUpdated(key, new_value);
-        //            }
-        //        }
-    }
-
-    /**
-     * Called anytime a given key is removed from the ConcurrentHashMap we are
-     * listening to.
-     *
-     * @param key         Key of the entry removed
-     * @param cacheName   name of the cache for which update has been received
-     * @param originLocal true if the event is generated from this node
-     */
-    @Override
-    public void entryDeleted(final I key, final String cacheName, final boolean originLocal) {
-        if (log.isDebugEnabled()) {
-            log.debug("RoutingTableUpdates: entryUpdated  routeId = " + key + " local = " + originLocal
-                    + " cacheName=" + cacheName + " originLocal=" + originLocal);
-        }
-        //        if (!originLocal) {
-        //            for (RouteChangeListener rcl : routeChangeListeners) {
-        //                rcl.onRouteDeleted(key);
-        //            }
-        //        }
-    }
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java
deleted file mode 100644 (file)
index 1ff49c1..0000000
+++ /dev/null
@@ -1,334 +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.connector.remoterpc.impl;
-
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.when;
-
-import java.net.URI;
-import java.util.EnumSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import junit.framework.Assert;
-
-import org.apache.felix.dm.Component;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-public class RoutingTableImplTest {
-
-    private final URI namespace = URI.create("http://cisco.com/example");
-    private final QName QNAME = new QName(namespace, "global");
-
-    private IClusterGlobalServices clusterService;
-    private RoutingTableImpl<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
-    ConcurrentMap mockGlobalRpcCache;
-    ConcurrentMap mockRpcCache;
-
-    @Before
-    public void setUp() throws Exception{
-        clusterService = mock(IClusterGlobalServices.class);
-        routingTable = new RoutingTableImpl<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
-        mockGlobalRpcCache = new ConcurrentHashMap<>();
-        mockRpcCache = new ConcurrentHashMap<>();
-        createRoutingTableCache();
-    }
-
-    @After
-    public void tearDown(){
-        reset(clusterService);
-        mockGlobalRpcCache = null;
-        mockRpcCache = null;
-    }
-
-    @Test
-    public void addGlobalRoute_ValidArguments_ShouldAdd() throws Exception {
-
-        Assert.assertNotNull(mockGlobalRpcCache);
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
-
-        final String expectedRoute = "172.27.12.1:5000";
-        routingTable.addGlobalRoute(routeIdentifier, expectedRoute);
-
-        ConcurrentMap latestCache = routingTable.getGlobalRpcCache();
-        Assert.assertEquals(mockGlobalRpcCache, latestCache);
-        Assert.assertEquals(expectedRoute, latestCache.get(routeIdentifier));
-    }
-
-    @Test (expected = RoutingTable.DuplicateRouteException.class)
-    public void addGlobalRoute_DuplicateRoute_ShouldThrow() throws Exception{
-
-        Assert.assertNotNull(mockGlobalRpcCache);
-
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
-        routingTable.addGlobalRoute(routeIdentifier, new String());
-        routingTable.addGlobalRoute(routeIdentifier, new String());
-    }
-
-    @Test
-    public void getGlobalRoute_ExistingRouteId_ShouldReturnRoute() throws Exception {
-
-        Assert.assertNotNull(mockGlobalRpcCache);
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
-        String expectedRoute = "172.27.12.1:5000";
-
-        routingTable.addGlobalRoute(routeIdentifier, expectedRoute);
-
-        String actualRoute = routingTable.getGlobalRoute(routeIdentifier);
-        Assert.assertEquals(expectedRoute, actualRoute);
-    }
-
-    @Test
-    public void getGlobalRoute_NonExistentRouteId_ShouldReturnNull() throws Exception {
-
-        Assert.assertNotNull(mockGlobalRpcCache);
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
-
-        String actualRoute = routingTable.getGlobalRoute(routeIdentifier);
-        Assert.assertNull(actualRoute);
-    }
-
-    @Test
-    public void removeGlobalRoute_ExistingRouteId_ShouldRemove() throws Exception {
-
-        Assert.assertNotNull(mockGlobalRpcCache);
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
-
-        ConcurrentMap cache = routingTable.getGlobalRpcCache();
-        Assert.assertTrue(cache.size() == 0);
-        routingTable.addGlobalRoute(routeIdentifier, "172.27.12.1:5000");
-        Assert.assertTrue(cache.size() == 1);
-
-        routingTable.removeGlobalRoute(routeIdentifier);
-        Assert.assertTrue(cache.size() == 0);
-
-    }
-
-    @Test
-    public void removeGlobalRoute_NonExistentRouteId_ShouldDoNothing() throws Exception {
-
-        Assert.assertNotNull(mockGlobalRpcCache);
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
-
-        ConcurrentMap cache = routingTable.getGlobalRpcCache();
-        Assert.assertTrue(cache.size() == 0);
-
-        routingTable.removeGlobalRoute(routeIdentifier);
-        Assert.assertTrue(cache.size() == 0);
-
-    }
-
-    @Test
-    public void addRoute_ForNewRouteId_ShouldAddRoute() throws Exception {
-        Assert.assertTrue(mockRpcCache.size() == 0);
-
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeId = getRouteIdentifier();
-
-        routingTable.addRoute(routeId, new String());
-        Assert.assertTrue(mockRpcCache.size() == 1);
-
-        Set<String> routes = routingTable.getRoutes(routeId);
-        Assert.assertEquals(1, routes.size());
-    }
-
-    @Test
-    public void addRoute_ForExistingRouteId_ShouldAppendRoute() throws Exception {
-
-        Assert.assertTrue(mockRpcCache.size() == 0);
-
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeId = getRouteIdentifier();
-
-        String route_1 = "10.0.0.1:5955";
-        String route_2 = "10.0.0.2:5955";
-
-        routingTable.addRoute(routeId, route_1);
-        routingTable.addRoute(routeId, route_2);
-
-        Assert.assertTrue(mockRpcCache.size() == 1);
-
-        Set<String> routes = routingTable.getRoutes(routeId);
-        Assert.assertEquals(2, routes.size());
-        Assert.assertTrue(routes.contains(route_1));
-        Assert.assertTrue(routes.contains(route_2));
-    }
-
-    @Test
-    public void addRoute_UsingMultipleThreads_ShouldNotOverwrite(){
-        ExecutorService threadPool = Executors.newCachedThreadPool();
-
-        int numOfRoutesToAdd = 100;
-        String routePrefix_1   = "10.0.0.1:555";
-        RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
-        threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_1, routeId));
-        String routePrefix_2   = "10.0.0.1:556";
-        threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_2, routeId));
-
-        // wait for all tasks to complete; timeout in 10 sec
-        threadPool.shutdown();
-        try {
-            threadPool.awaitTermination(10, TimeUnit.SECONDS); //
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-
-        Assert.assertEquals(2*numOfRoutesToAdd, routingTable.getRoutes(routeId).size());
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void addRoute_NullRouteId_shouldThrowNpe() throws Exception {
-
-        routingTable.addRoute(null, new String());
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void addRoute_NullRoute_shouldThrowNpe() throws Exception{
-
-        routingTable.addRoute(getRouteIdentifier(), null);
-    }
-
-    @Test (expected = UnsupportedOperationException.class)
-    public void getRoutes_Call_ShouldReturnImmutableCopy() throws Exception{
-        Assert.assertNotNull(routingTable);
-        RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
-        routingTable.addRoute(routeId, new String());
-
-        Set<String> routes = routingTable.getRoutes(routeId); //returns Immutable Set
-
-        routes.add(new String()); //can not be modified; should throw
-    }
-
-    @Test
-    public void getRoutes_With2RoutesFor1RouteId_ShouldReturnASetWithSize2() throws Exception{
-        Assert.assertNotNull(routingTable);
-        RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
-        routingTable.addRoute(routeId, "10.0.0.1:5555");
-        routingTable.addRoute(routeId, "10.0.0.2:5555");
-
-        Set<String> routes = routingTable.getRoutes(routeId); //returns Immutable Set
-
-        Assert.assertEquals(2, routes.size());
-    }
-
-    @Test
-    public void getLastAddedRoute_WhenMultipleRoutesExists_ShouldReturnLatestRoute()
-            throws Exception {
-
-        Assert.assertNotNull(routingTable);
-        RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
-        String route_1 = "10.0.0.1:5555";
-        String route_2 = "10.0.0.2:5555";
-        routingTable.addRoute(routeId, route_1);
-        routingTable.addRoute(routeId, route_2);
-
-        Assert.assertEquals(route_2, routingTable.getLastAddedRoute(routeId));
-    }
-
-    @Test
-    public void removeRoute_WhenMultipleRoutesExist_RemovesGivenRoute() throws Exception{
-        Assert.assertNotNull(routingTable);
-        RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
-        String route_1 = "10.0.0.1:5555";
-        String route_2 = "10.0.0.2:5555";
-
-        routingTable.addRoute(routeId, route_1);
-        routingTable.addRoute(routeId, route_2);
-
-        Assert.assertEquals(2, routingTable.getRoutes(routeId).size());
-
-        routingTable.removeRoute(routeId, route_1);
-        Assert.assertEquals(1, routingTable.getRoutes(routeId).size());
-
-    }
-
-    @Test
-    public void removeRoute_WhenOnlyOneRouteExists_RemovesRouteId() throws Exception{
-        Assert.assertNotNull(routingTable);
-        RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
-        String route_1 = "10.0.0.1:5555";
-
-        routingTable.addRoute(routeId, route_1);
-        Assert.assertEquals(1, routingTable.getRoutes(routeId).size());
-
-        routingTable.removeRoute(routeId, route_1);
-        ConcurrentMap cache = routingTable.getRpcCache();
-        Assert.assertFalse(cache.containsKey(routeId));
-
-    }
-
-    /*
-     * Private helper methods
-     */
-    private void createRoutingTableCache() throws Exception {
-
-        //here init
-        Component c = mock(Component.class);
-
-        when(clusterService.existCache(
-                RoutingTableImpl.GLOBALRPC_CACHE)).thenReturn(false);
-
-        when(clusterService.createCache(RoutingTableImpl.GLOBALRPC_CACHE,
-                EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).
-                thenReturn(mockGlobalRpcCache);
-
-        when(clusterService.existCache(
-                RoutingTableImpl.RPC_CACHE)).thenReturn(false);
-
-        when(clusterService.createCache(RoutingTableImpl.RPC_CACHE,
-                EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).
-                thenReturn(mockRpcCache);
-
-        doNothing().when(clusterService).tbegin();
-        doNothing().when(clusterService).tcommit();
-
-        routingTable.setClusterGlobalServices(this.clusterService);
-        routingTable.init(c);
-
-        Assert.assertEquals(mockGlobalRpcCache, routingTable.getGlobalRpcCache());
-        Assert.assertEquals(mockRpcCache, routingTable.getRpcCache());
-    }
-
-    private RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> getRouteIdentifier(){
-        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = mock(RpcRouter.RouteIdentifier.class);
-        InstanceIdentifier identifier = mock(InstanceIdentifier.class);
-        when(routeIdentifier.getType()).thenReturn(QNAME);
-        when(routeIdentifier.getRoute()).thenReturn(identifier);
-
-        return routeIdentifier;
-    }
-
-    private Runnable addRoutes(final int numRoutes, final String routePrefix, final RpcRouter.RouteIdentifier routeId){
-        return new Runnable() {
-            @Override
-            public void run() {
-                for (int i=0;i<numRoutes;i++){
-                    String route = routePrefix + i;
-                    try {
-                        routingTable.addRoute(routeId, route);
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                }
-            }
-        };
-    }
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/pom.xml b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/pom.xml
deleted file mode 100644 (file)
index 6db143a..0000000
+++ /dev/null
@@ -1,271 +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>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>
-    <tag>HEAD</tag>
-  </scm>
-
-  <artifactId>remoterpc-routingtable.integrationtest</artifactId>
-  <version>0.4.1-SNAPSHOT</version>
-
-  <dependencies>
-    <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>remoterpc-routingtable.implementation</artifactId>
-        <version>0.4.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>clustering.services</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal.implementation</artifactId>
-          <version>0.4.0-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>containermanager</artifactId>
-          <version>0.5.0-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>containermanager.it.implementation</artifactId>
-          <version>0.5.0-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>clustering.stub</artifactId>
-          <version>0.4.0-SNAPSHOT</version>
-      </dependency>
-        <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-    </dependency>
-    <dependency>
-       <groupId>org.ops4j.pax.exam</groupId>
-       <artifactId>pax-exam-container-native</artifactId>
-       <scope>test</scope>
-     </dependency>
-     <dependency>
-       <groupId>org.ops4j.pax.exam</groupId>
-       <artifactId>pax-exam-junit4</artifactId>
-       <scope>test</scope>
-     </dependency>
-     <dependency>
-        <groupId>org.ops4j.pax.exam</groupId>
-        <artifactId>pax-exam-link-mvn</artifactId>
-        <scope>test</scope>
-      </dependency>
-      <dependency>
-        <groupId>org.ops4j.pax.url</groupId>
-        <artifactId>pax-url-aether</artifactId>
-        <scope>test</scope>
-      </dependency>
-      <dependency>
-        <groupId>org.slf4j</groupId>
-        <artifactId>log4j-over-slf4j</artifactId>
-      </dependency>
-      <dependency>
-        <groupId>ch.qos.logback</groupId>
-        <artifactId>logback-core</artifactId>
-      </dependency>
-      <dependency>
-        <groupId>ch.qos.logback</groupId>
-        <artifactId>logback-classic</artifactId>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
-      </dependency>
-      <dependency>
-        <groupId>eclipselink</groupId>
-        <artifactId>javax.resource</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>com.google.guava</groupId>
-          <artifactId>guava</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal</artifactId>
-          <version>0.5.1-SNAPSHOT</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.controller</groupId>
-          <artifactId>sal-connector-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>junit</groupId>
-          <artifactId>junit</artifactId>
-      </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-binding-broker-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>
-      </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.ops4j.pax.exam</groupId>
-          <artifactId>pax-exam-link-mvn</artifactId>
-          <version>${exam.version}</version>
-          <scope>test</scope>
-      </dependency>
-
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>config-manager</artifactId>
-          <version>0.2.3-SNAPSHOT</version>
-      </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.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>
-      </dependency>
-
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>clustering.services</artifactId>
-          <version>0.4.1-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>junit</groupId>
-          <artifactId>junit</artifactId>
-          <scope>test</scope>
-      </dependency>
-
-      <dependency>
-          <groupId>equinoxSDK381</groupId>
-          <artifactId>org.eclipse.osgi</artifactId>
-          <version>3.8.1.v20120830-144521</version>
-      </dependency>
-      <dependency>
-          <groupId>org.ops4j.pax.exam</groupId>
-          <artifactId>pax-exam-junit4</artifactId>
-          <version>3.0.0</version>
-      </dependency>
-      <dependency>
-          <groupId>org.ops4j.pax.exam</groupId>
-          <artifactId>pax-exam-junit4</artifactId>
-          <version>3.0.0</version>
-      </dependency>
-      <dependency>
-          <groupId>org.ops4j.pax.exam</groupId>
-          <artifactId>pax-exam</artifactId>
-          <version>3.0.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>../implementation/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/remoterpc-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java
deleted file mode 100644 (file)
index 9249212..0000000
+++ /dev/null
@@ -1,330 +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.connector.remoterpc.impl;
-
-import junit.framework.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.yangtools.yang.common.QName;
-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.PathUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.inject.Inject;
-import java.io.Serializable;
-import java.net.URI;
-import java.util.Set;
-
-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;
-
-
-
-
-@RunWith(PaxExam.class)
-public class
-        ZeroMQRoutingTableTestIT {
-    private Logger log = LoggerFactory
-            .getLogger(ZeroMQRoutingTableTestIT.class);
-
-    public static final String ODL = "org.opendaylight.controller";
-    public static final String YANG = "org.opendaylight.yangtools";
-    public static final String CONTROLLER = "org.opendaylight.controller";
-    public static final String YANGTOOLS = "org.opendaylight.yangtools";
-    RoutingIdentifierImpl rii  = new RoutingIdentifierImpl();
-    // get the OSGI bundle context
-    @Inject
-    private BundleContext bc;
-    @Inject
-    private RoutingTable routingTable = null;
-
-    // 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"),
-                // 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(),
-                // List all the bundles on which the test case depends
-                mavenBundle(ODL,
-                        "clustering.services").versionAsInProject(),
-
-                mavenBundle(ODL, "sal").versionAsInProject(),
-                mavenBundle(ODL,
-                        "sal.implementation").versionAsInProject(),
-                mavenBundle(ODL, "containermanager").versionAsInProject(),
-                mavenBundle(ODL,
-                        "containermanager.it.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(),
-                mavenBundle("org.apache.felix",
-                        "org.apache.felix.dependencymanager.shell").versionAsInProject(),
-                mavenBundle("eclipselink", "javax.resource").versionAsInProject(),
-
-                mavenBundle("com.google.guava","guava").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(),
-
-                mavenBundle(ODL, "clustering.services")
-                        .versionAsInProject(),
-                mavenBundle(ODL, "clustering.stub")
-                        .versionAsInProject(),
-
-
-                // List all the bundles on which the test case depends
-                mavenBundle(ODL, "sal")
-                        .versionAsInProject(),
-                mavenBundle(ODL, "sal-connector-api")
-                        .versionAsInProject(),
-                mavenBundle(ODL, "remoterpc-routingtable.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(),
-
-                mavenBundle(ODL,
-                        "sal-core-api")
-                        .versionAsInProject(),
-                mavenBundle("org.opendaylight.yangtools","yang-data-api")
-                        .versionAsInProject(),
-                mavenBundle("org.opendaylight.yangtools","yang-model-api")
-                        .versionAsInProject(),
-                mavenBundle("org.opendaylight.yangtools","yang-binding")
-                        .versionAsInProject(),
-
-                mavenBundle(CONTROLLER, "sal-binding-api").versionAsInProject(), //
-                mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
-                mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
-                mavenBundle("org.javassist", "javassist").versionAsInProject(), //
-                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
-
-                mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
-                mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
-                mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
-                mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
-                mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
-                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
-
-
-                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
-                mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
-                mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
-                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
-                mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
-                mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
-                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
-                mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
-
-
-                mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
-                mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
-                mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
-
-                mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
-
-                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(),
-                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
-                mavenBundle("org.javassist", "javassist").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(ODL, "sal-common").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
-                mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
-
-                mavenBundle(ODL, "config-api").versionAsInProject(), //
-                mavenBundle(ODL, "config-manager").versionAsInProject(), //
-                mavenBundle("commons-io", "commons-io").versionAsInProject(),
-                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
-
-                mavenBundle(ODL, "sal-binding-api").versionAsInProject(), //
-                mavenBundle(ODL, "sal-binding-config").versionAsInProject(),
-                mavenBundle("org.javassist", "javassist").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-util").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, "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(YANG, "binding-generator-api").versionAsInProject(),
-                mavenBundle(YANG, "binding-generator-spi").versionAsInProject(),
-                mavenBundle(YANG, "binding-generator-impl").versionAsInProject(),
-
-
-                mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
-
-                mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
-
-                mavenBundle(YANG, "concepts").versionAsInProject(),
-                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
-                mavenBundle(YANG, "yang-common").versionAsInProject(), //
-                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(),
-                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
-                mavenBundle("org.javassist", "javassist").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 testAddGlobalRoute () throws Exception{
-
-       routingTable.addGlobalRoute(rii,"172.27.12.1:5000");
-
-       Set<String> routes = routingTable.getRoutes(rii);
-
-       for(String route:routes){
-           Assert.assertEquals(route,"172.27.12.1:5000");
-       }
-
-
-    }
-
-
-    @Test
-    public  void testDeleteGlobalRoute () throws Exception{
-
-        routingTable.removeGlobalRoute(rii);
-
-        Set<String> routes = routingTable.getRoutes(rii);
-
-        Assert.assertNull(routes);
-
-
-    }
-
-
-
-   class RoutingIdentifierImpl implements RpcRouter.RouteIdentifier,Serializable {
-
-       private final URI namespace = URI.create("http://cisco.com/example");
-       private final QName QNAME = new QName(namespace,"global");
-       private final QName instance = new QName(URI.create("127.0.0.1"),"local");
-
-       @Override
-       public QName getContext() {
-           return QNAME;
-       }
-
-       @Override
-       public QName getType() {
-           return QNAME;
-       }
-
-       @Override
-       public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
-           return InstanceIdentifier.of(instance);
-       }
-
-       @Override
-       public boolean equals(Object o) {
-           if (this == o) return true;
-           if (o == null || getClass() != o.getClass()) return false;
-
-           RoutingIdentifierImpl that = (RoutingIdentifierImpl) o;
-
-           if (QNAME != null ? !QNAME.equals(that.QNAME) : that.QNAME != null) return false;
-           if (instance != null ? !instance.equals(that.instance) : that.instance != null) return false;
-           if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;
-
-           return true;
-       }
-
-       @Override
-       public int hashCode() {
-           int result = namespace != null ? namespace.hashCode() : 0;
-           result = 31 * result + (QNAME != null ? QNAME.hashCode() : 0);
-           result = 31 * result + (instance != null ? instance.hashCode() : 0);
-           return result;
-       }
-   }
-
-
-
-
-
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/pom.xml b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/pom.xml
deleted file mode 100644 (file)
index 1fd4b76..0000000
+++ /dev/null
@@ -1,92 +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>
-    <artifactId>sal-remoterpc-connector-test-parent</artifactId>
-    <groupId>org.opendaylight.controller.tests</groupId>
-    <version>1.0-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>remoterpc-routingtable-nb-it</artifactId>
-  <packaging>bundle</packaging>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${bundle.plugin.version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Export-Package>
-             org.opendaylight.controller.tests.zmqroutingtable.rest
-            </Export-Package>
-            <Import-Package>
-              com.sun.jersey.spi.container.servlet,
-              com.fasterxml.jackson.annotation,
-              javax.ws.rs,
-              javax.ws.rs.core,
-              javax.xml.bind,
-              javax.xml.bind.annotation,
-              org.slf4j,
-              org.apache.catalina.filters,
-              org.codehaus.jackson.jaxrs,
-              org.opendaylight.controller.sal.utils,
-              org.opendaylight.yangtools.yang.common,
-              org.opendaylight.controller.sal.connector.api,
-              org.opendaylight.controller.sal.connector.remoterpc.api,
-              org.opendaylight.controller.sal.connector.remoterpc.impl,
-              org.osgi.framework,
-              com.google.common.base,
-              org.opendaylight.yangtools.yang.data.api,
-              !org.codehaus.enunciate.jaxrs
-
-            </Import-Package>
-            <Web-ContextPath>/controller/nb/v2/zmqnbrt</Web-ContextPath>
-            <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
-          </instructions>
-          <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <dependencies>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>containermanager</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>commons.northbound</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-      <version>5.0.0</version>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-    </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>remoterpc-routingtable.implementation</artifactId>
-          <version>0.4.1-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>com.google.guava</groupId>
-          <artifactId>guava</artifactId>
-      </dependency>
-  </dependencies>
-
- </project>
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/RouteIdentifierImpl.java b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/RouteIdentifierImpl.java
deleted file mode 100644 (file)
index eb5ecd7..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.tests.zmqroutingtable.rest;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import java.io.Serializable;
-import java.net.URI;
-
-/**
- * @author: syedbahm
- * Date: 12/10/13
- */
-public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier, Serializable {
-
-    private final URI namespace;
-    private final QName QNAME;
-    private final QName instance;
-
-    public RouteIdentifierImpl() {
-        namespace = URI.create("http://cisco.com/example");
-        QNAME = new QName(namespace, "global");
-        instance = new QName(URI.create("127.0.0.1"), "local");
-    }
-
-    public RouteIdentifierImpl(String url,String instanceIP){
-        namespace = URI.create(url);
-        QNAME = new QName(namespace,"global");
-        instance =  new QName(URI.create(instanceIP), "local");
-    }
-
-
-    @Override
-    public QName getContext() {
-        return QNAME;
-    }
-
-    @Override
-    public QName getType() {
-        return QNAME;
-    }
-
-    @Override
-    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
-        return InstanceIdentifier.of(instance);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        RouteIdentifierImpl that = (RouteIdentifierImpl) o;
-
-        if (!QNAME.equals(that.QNAME)) return false;
-        if (!instance.equals(that.instance)) return false;
-        if (!namespace.equals(that.namespace)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = namespace.hashCode();
-        result = 31 * result + QNAME.hashCode();
-        result = 31 * result + instance.hashCode();
-        return result;
-    }
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/Router.java b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/Router.java
deleted file mode 100644 (file)
index 9bf6e53..0000000
+++ /dev/null
@@ -1,164 +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.tests.zmqroutingtable.rest;
-
-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.impl.RoutingTableImpl;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleReference;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import java.io.Serializable;
-import java.net.URI;
-
-@Path("router")
-public class Router implements Serializable {
-  private Logger _logger = LoggerFactory.getLogger(Router.class);
-  private final URI namespace = URI.create("http://cisco.com/example");
-  private final QName QNAME = new QName(namespace, "heartbeat");
-
-
-  @GET
-  @Path("/hello")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String hello() {
-    return "Hello";
-  }
-
-
-
-
-    @GET
-    @Path("/rtadd")
-    @Produces(MediaType.TEXT_PLAIN)
-    public String addToRoutingTable(@QueryParam("nsp") String namespace,@QueryParam("inst") String instance,@QueryParam("port") String port) {
-        _logger.info("Invoking adding an entry in routing table");
-
-        BundleContext ctx = getBundleContext();
-        ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
-        if (routingTableServiceReference == null) {
-            _logger.debug("Could not get routing table impl reference");
-            return "Could not get routingtable referen ";
-        }
-        RoutingTableImpl routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
-        if (routingTable == null) {
-            _logger.info("Could not get routing table service");
-            return "Could not get routing table service";
-        }
-
-
-        RouteIdentifierImpl rii = new RouteIdentifierImpl(namespace,instance);
-        try {
-            routingTable.addGlobalRoute(rii, instance+":"+ port);
-        } catch (RoutingTableException e) {
-            _logger.error("error in adding routing identifier" + e.getMessage());
-
-        } catch (SystemException e) {
-            _logger.error("error in adding routing identifier" + e.getMessage());
-        }
-
-        StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append("Result of adding route:").append("\n")
-                     .append(routingTable.dumpRoutingTableCache());
-        return stringBuilder.toString();
-    }
-
-  @GET
-  @Path("/rtdelete")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String invokeDeleteRoutingTable(@QueryParam("nsp") String namespace,@QueryParam("inst") String instance) {
-    _logger.info("Invoking delete an entry in routing table");
-
-    BundleContext ctx = getBundleContext();
-    ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
-    if (routingTableServiceReference == null) {
-      _logger.debug("Could not get routing table impl reference");
-      return "Could not get routingtable referen ";
-    }
-    RoutingTableImpl routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
-    if (routingTable == null) {
-      _logger.info("Could not get routing table service");
-      return "Could not get routing table service";
-    }
-
-
-    RouteIdentifierImpl rii = new RouteIdentifierImpl(namespace,instance);
-    try {
-      routingTable.removeGlobalRoute(rii);
-    } catch (RoutingTableException e) {
-      _logger.error("error in adding routing identifier" + e.getMessage());
-
-    } catch (SystemException e) {
-      _logger.error("error in adding routing identifier" + e.getMessage());
-    }
-
-
-    StringBuilder stringBuilder = new StringBuilder();
-    stringBuilder.append("Result of deleting route:").append("\n")
-              .append(routingTable.dumpRoutingTableCache());
-
-    return stringBuilder.toString();
-  }
-
-    @GET
-    @Path("/routingtable")
-    @Produces(MediaType.TEXT_PLAIN)
-    public String invokeGetRoutingTable() {
-        _logger.info("Invoking getting of routing table");
-
-        BundleContext ctx = getBundleContext();
-        ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
-        if (routingTableServiceReference == null) {
-            _logger.debug("Could not get routing table impl reference");
-            return "Could not get routingtable referen ";
-        }
-        RoutingTableImpl routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
-        if (routingTable == null) {
-            _logger.info("Could not get routing table service");
-            return "Could not get routing table service";
-        }
-
-
-        StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append("Result of getting routetable:").append("\n")
-                .append(routingTable.dumpRoutingTableCache());
-
-        return stringBuilder.toString();
-    }
-
-
-
-  private BundleContext getBundleContext() {
-    ClassLoader tlcl = Thread.currentThread().getContextClassLoader();
-    Bundle bundle = null;
-
-    if (tlcl instanceof BundleReference) {
-      bundle = ((BundleReference) tlcl).getBundle();
-    } else {
-      _logger.info("Unable to determine the bundle context based on " +
-          "thread context classloader.");
-      bundle = FrameworkUtil.getBundle(this.getClass());
-    }
-    return (bundle == null ? null : bundle.getBundleContext());
-  }
-
-
-
-}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml
deleted file mode 100644 (file)
index 2a0f3f3..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
-        version="3.0">
-  <servlet>
-    <servlet-name>JAXRSZmqRT</servlet-name>
-    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
-    <init-param>
-      <param-name>javax.ws.rs.Application</param-name>
-      <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-
-  <servlet-mapping>
-    <servlet-name>JAXRSZmqRT</servlet-name>
-    <url-pattern>/*</url-pattern>
-  </servlet-mapping>
-
-
-
-        <security-constraint>
-          <web-resource-collection>
-            <web-resource-name>NB api</web-resource-name>
-            <url-pattern>/*</url-pattern>
-            <http-method>POST</http-method>
-            <http-method>GET</http-method>
-            <http-method>PUT</http-method>
-            <http-method>PATCH</http-method>
-            <http-method>DELETE</http-method>
-            <http-method>HEAD</http-method>
-          </web-resource-collection>
-          <auth-constraint>
-            <role-name>System-Admin</role-name>
-            <role-name>Network-Admin</role-name>
-            <role-name>Network-Operator</role-name>
-            <role-name>Container-User</role-name>
-          </auth-constraint>
-        </security-constraint>
-
-        <security-role>
-                <role-name>System-Admin</role-name>
-        </security-role>
-        <security-role>
-                <role-name>Network-Admin</role-name>
-        </security-role>
-        <security-role>
-                <role-name>Network-Operator</role-name>
-        </security-role>
-        <security-role>
-                <role-name>Container-User</role-name>
-        </security-role>
-
-        <login-config>
-                <auth-method>BASIC</auth-method>
-                <realm-name>opendaylight</realm-name>
-        </login-config>
-</web-app>
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingDataBroker.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingDataBroker.java
deleted file mode 100644 (file)
index c6a9efe..0000000
+++ /dev/null
@@ -1,29 +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.binding.api;
-
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public interface BindingDataBroker extends AsyncDataBroker<InstanceIdentifier<?>, DataObject, BindingDataChangeListener>{
-    @Override
-    BindingDataReadTransaction newReadOnlyTransaction();
-
-    @Override
-    BindingDataReadWriteTransaction newReadWriteTransaction();
-
-    @Override
-    BindingDataWriteTransaction newWriteOnlyTransaction();
-
-    @Override
-    ListenerRegistration<BindingDataChangeListener> registerDataChangeListener(LogicalDatastoreType store,
-            InstanceIdentifier<?> path, BindingDataChangeListener listener, DataChangeScope triggeringScope);
-}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingService.java
new file mode 100644 (file)
index 0000000..ccce73c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.binding.api;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareService;
+
+/**
+ *
+ * Marker interface for MD-SAL services which are available for users of MD-SAL.
+ *
+ * BindingService is marker interface for infrastructure services provided by
+ * the SAL. These services may be session-specific, and wrapped by custom
+ * delegator patterns in order to introduce additional semantics / checks
+ * to the system.
+ *
+ * This interface extends {@link BindingAwareService}, order to be make
+ * new services available via
+ * {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext}
+ * and via
+ * {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext}
+ *
+ */
+public interface BindingService extends BindingAwareService {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/BindingTransactionChain.java
new file mode 100644 (file)
index 0000000..eac65ad
--- /dev/null
@@ -0,0 +1,18 @@
+package org.opendaylight.controller.md.sal.binding.api;
+
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface BindingTransactionChain extends TransactionChain<InstanceIdentifier<?>, DataObject> {
+
+    @Override
+    ReadOnlyTransaction newReadOnlyTransaction();
+
+    @Override
+    ReadWriteTransaction newReadWriteTransaction();
+
+    @Override
+    WriteTransaction newWriteOnlyTransaction();
+
+}
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/DataBroker.java
new file mode 100644 (file)
index 0000000..b60d8ff
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.binding.api;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainFactory;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Provides access to a conceptual data tree store and also provides the ability to
+ * subscribe for changes to data under a given branch of the tree.
+ * <p>
+ * For more information on usage, please see the documentation in {@link AsyncDataBroker}.
+ */
+public interface DataBroker extends AsyncDataBroker<InstanceIdentifier<?>, DataObject, DataChangeListener>, BindingService, TransactionChainFactory<InstanceIdentifier<?>, DataObject> {
+    @Override
+    ReadOnlyTransaction newReadOnlyTransaction();
+
+    @Override
+    ReadWriteTransaction newReadWriteTransaction();
+
+    @Override
+    WriteTransaction newWriteOnlyTransaction();
+
+    @Override
+    ListenerRegistration<DataChangeListener> registerDataChangeListener(LogicalDatastoreType store,
+            InstanceIdentifier<?> path, DataChangeListener listener, DataChangeScope triggeringScope);
+}
@@ -12,7 +12,7 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListene
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public interface BindingDataChangeListener extends AsyncDataChangeListener<InstanceIdentifier<?>, DataObject> {
+public interface DataChangeListener extends AsyncDataChangeListener<InstanceIdentifier<?>, DataObject> {
     @Override
     void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change);
 }
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ReadOnlyTransaction.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ReadOnlyTransaction.java
new file mode 100644 (file)
index 0000000..f3b42b9
--- /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.binding.api;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncReadOnlyTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * A transaction that provides a stateful read-only view of the data tree.
+ * <p>
+ * For more information on usage and examples, please see the documentation in
+ *  {@link org.opendaylight.controller.md.sal.common.api.data.AsyncReadTransaction}.
+ */
+public interface ReadOnlyTransaction extends ReadTransaction, AsyncReadOnlyTransaction<InstanceIdentifier<?>, DataObject> {
+
+}
@@ -15,7 +15,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 
-public interface BindingDataReadTransaction extends AsyncReadTransaction<InstanceIdentifier<?>, DataObject> {
+public interface ReadTransaction extends AsyncReadTransaction<InstanceIdentifier<?>, DataObject> {
     @Override
     ListenableFuture<Optional<DataObject>> read(LogicalDatastoreType store, InstanceIdentifier<?> path);
 }
@@ -12,9 +12,10 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
- * Logical capture of a combination of both {@link BindingDataReadTransaction} and
- * {@link BindingDataWriteTransaction}.
+ * A transaction that enables combined read/write capabilities.
+ * <p>
+ * For more information on usage and examples, please see the documentation in {@link AsyncReadWriteTransaction}.
  */
-public interface BindingDataReadWriteTransaction extends BindingDataReadTransaction, BindingDataWriteTransaction, AsyncReadWriteTransaction<InstanceIdentifier<?>, DataObject> {
+public interface ReadWriteTransaction extends ReadTransaction, WriteTransaction, AsyncReadWriteTransaction<InstanceIdentifier<?>, DataObject> {
 
 }
@@ -12,7 +12,12 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public interface BindingDataWriteTransaction extends AsyncWriteTransaction<InstanceIdentifier<?>, DataObject> {
+/**
+ * A transaction that provides mutation capabilities on a data tree.
+ * <p>
+ * For more information on usage and examples, please see the documentation in {@link AsyncWriteTransaction}.
+ */
+public interface WriteTransaction extends AsyncWriteTransaction<InstanceIdentifier<?>, DataObject> {
     @Override
     void put(LogicalDatastoreType store, InstanceIdentifier<?> path, DataObject data);
 
index 453ff449118ffab0898f429cb02c8ec0ca8ed5ff..a41186dae11eda694687e7698663dffbc3364c26 100644 (file)
@@ -156,11 +156,26 @@ public interface BindingAwareBroker {
         void unregisterFunctionality(ProviderFunctionality functionality);
     }
 
+    /**
+     * Represents an RPC implementation registration. Users should call the
+     * {@link ObjectRegistration#close close} method when the registration is no longer needed.
+     *
+     * @param <T> the implemented RPC service interface
+     */
     public interface RpcRegistration<T extends RpcService> extends ObjectRegistration<T> {
 
+        /**
+         * Returns the implemented RPC service interface.
+         */
         Class<T> getServiceType();
     }
 
+    /**
+     * Represents a routed RPC implementation registration. Users should call the
+     * {@link RoutedRegistration#close close} method when the registration is no longer needed.
+     *
+     * @param <T> the implemented RPC service interface
+     */
     public interface RoutedRpcRegistration<T extends RpcService> extends RpcRegistration<T>,
             RoutedRegistration<Class<? extends BaseIdentity>, InstanceIdentifier<?>, T> {
 
index 6e8bda56d89e84e5fe0a7920ebcdfd07c2c5b84e..46e372aea652e29439408da9b6d1ccc963e86acc 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.controller.sal.binding.api;
 
-import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
 public interface NotificationService extends BindingAwareService {
@@ -16,9 +16,9 @@ public interface NotificationService extends BindingAwareService {
      *
      * @param notificationType
      * @param listener
-     * @return Registration for listener. To unregister listener invoke {@link Registration#close()} method.
+     * @return Registration for listener. To unregister listener invoke {@link ListenerRegistration#close()} method.
      */
-    <T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(
+    <T extends Notification> ListenerRegistration<NotificationListener<T>> registerNotificationListener(
             Class<T> notificationType, NotificationListener<T> listener);
 
     /**
@@ -27,8 +27,8 @@ public interface NotificationService extends BindingAwareService {
      * Listener is registered for all notifications present in implemented interfaces.
      *
      * @param listener
-     * @return Registration for listener. To unregister listener invoke {@link Registration#close()} method.
+     * @return Registration for listener. To unregister listener invoke {@link ListenerRegistration#close()} method.
      */
-    Registration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(
+    ListenerRegistration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(
             org.opendaylight.yangtools.yang.binding.NotificationListener listener);
 }
index 7da0a48517fddf715db5f55ced1d431680f0a755..615acd3195c8a99ed5b5f372f53dee46d5faac7b 100644 (file)
@@ -10,16 +10,60 @@ package org.opendaylight.controller.sal.binding.api;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 
 /**
- * Base interface defining contract for retrieving MD-SAL
- * version of RpcServices
+ * Provides access to registered Remote Procedure Call (RPC) service implementations. The RPCs are
+ * defined in YANG models.
+ * <p>
+ * RPC implementations are registered using the {@link RpcProviderRegistry}.
  *
  */
 public interface RpcConsumerRegistry extends BindingAwareService {
     /**
-     * Returns a session specific instance (implementation) of requested
-     * YANG module implementation / service provided by consumer.
+     * Returns an implementation of a requested RPC service.
      *
-     * @return Session specific implementation of service
+     * <p>
+     * The returned instance is not an actual implementation of the RPC service
+     * interface, but a proxy implementation of the interface that forwards to
+     * an actual implementation, if any.
+     * <p>
+     *
+     * The following describes the behavior of the proxy when invoking RPC methods:
+     * <ul>
+     * <li>If an actual implementation is registered with the MD-SAL, all invocations are
+     * forwarded to the registered implementation.</li>
+     * <li>If no actual implementation is registered, all invocations will fail by
+     * throwing {@link IllegalStateException}.</li>
+     * <li>Prior to invoking the actual implementation, the method arguments are are validated.
+     * If any are invalid, an {@link IllegalArgumentException} is thrown.
+     * </ul>
+     *
+     * The returned proxy is automatically updated with the most recent
+     * registered implementation.
+     * <p>
+     * The generated RPC method APIs require implementors to return a {@link java.util.concurrent.Future Future}
+     * instance that wraps the {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}. Since
+     * RPC methods may be implemented asynchronously, callers should avoid blocking on the
+     * {@link java.util.concurrent.Future Future} result. Instead, it is recommended to use
+     * {@link com.google.common.util.concurrent.JdkFutureAdapters#listenInPoolThread(java.util.concurrent.Future)}
+     * or {@link com.google.common.util.concurrent.JdkFutureAdapters#listenInPoolThread(java.util.concurrent.Future, java.util.concurrent.Executor)}
+     * to listen for Rpc Result. This will asynchronously listen for future result in executor and
+     * will not block current thread.
+     *
+     * <pre>
+     *   final Future<RpcResult<SomeRpcOutput>> future = someRpcService.someRpc( ... );
+     *   Futures.addCallback(JdkFutureAdapters.listenInThreadPool(future), new FutureCallback<RpcResult<SomeRpcOutput>>() {
+     *
+     *       public void onSuccess(RpcResult<SomeRpcOutput> result) {
+     *          // process result ...
+     *       }
+     *
+     *       public void onFailure(Throwable t) {
+     *          // RPC failed
+     *       }
+     *   );
+     * </pre>
+     * @param serviceInterface the interface of the RPC Service. Typically this is an interface generated
+     *                         from a YANG model.
+     * @return the proxy for the requested RPC service. This method never returns null.
      */
-    <T extends RpcService> T getRpcService(Class<T> module);
+    <T extends RpcService> T getRpcService(Class<T> serviceInterface);
 }
index cdf55844b3d94d680a7a21ad052deb9a7aa73ac4..22db985ba96b82cc4245a42f28ccd3e1f9959774 100644 (file)
@@ -15,39 +15,256 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 
 /**
- * Interface defining provider's access to the Rpc Registry which could be used
- * to register their implementations of service to the MD-SAL.
+ * Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are
+ * defined in YANG models.
+ * <p>
+ * There are 2 types of RPCs:
+ * <ul>
+ * <li>Global</li>
+ * <li>Routed</li>
+ * </ul>
  *
- * @author ttkacik
+ * <h2>Global RPC</h2>
+ * <p>
+ * An RPC is global if there is intended to be only 1 registered implementation. A global RPC is not
+ * explicitly declared as such, essentially any RPC that is not defined to be routed is considered global.
+ * <p>
+ * Global RPCs are registered using the
+ * {@link #addRpcImplementation(Class, RpcService)} method.
  *
+ * <h2>Routed RPC</h2>
+ * <p>
+ * MD-SAL supports routing of RPC between multiple implementations where the appropriate
+ * implementation is selected at run time based on the content of the RPC message as described in
+ * YANG model.
+ * <p>
+ * RPC routing is based on:
+ * <ul>
+ * <li><b>Route identifier</b> -
+ * An {@link org.opendaylight.yangtools.yang.binding.InstanceIdentifier InstanceIdentifier} value
+ * which is part of the RPC input. This value is used to select the correct
+ * implementation at run time.</li>
+ * <li><b>Context Type</b> - A YANG-defined construct which constrains the subset of
+ * valid route identifiers for a particular RPC.</li>
+ * </ul>
+ *
+ * <h3>Context type</h3>
+ * <p>
+ * A context type is modeled in YANG using a combination of a YANG <code>identity</code>
+ * and Opendaylight specific extensions from <code>yang-ext</code> module. These extensions are:
+ * <ul>
+ * <li><b>context-instance</b> - This is used in the data tree part of a YANG model to
+ * define a context type that associates nodes with a specified context <code>identity</code>.
+ * Instance identifiers that reference these nodes are valid route identifiers for RPCs that
+ * reference this context type.</li>
+ * <li><b>context-reference</b> - This is used in RPC input to mark a leaf of type
+ * <code>instance-identifier</code> as a reference to the particular context type defined by the
+ * specified context <code>identity</code>. The value of this
+ * leaf is used by the RPC broker at run time to route the RPC request to the correct implementation.
+ * Note that <code>context-reference</code> may only be used on leaf elements of type
+ * <code>instance-identifier</code> or a type derived from <code>instance-identifier</code>.</li>
+ * </ul>
+ *
+ *
+ * <h3>Routed RPC example</h3>
+ * <p>
+ * <h5>1. Defining a Context Type</h5>
+ * <p>
+ * The following snippet declares a simple YANG <code>identity</code> named <code>example-context</code>:
+ *
+ * <pre>
+ * module example {
+ *     ...
+ *     identity example-context {
+ *          description "Identity used to define an example-context type";
+ *     }
+ *     ...
+ * }
+ * </pre>
+ * <p>
+ * We then use the declared identity to define a context type by using it in combination
+ * with the <code>context-instance</code> YANG extension. We'll associate the context type
+ * with a list element in the data tree. This defines the set of nodes whose instance
+ * identifiers are valid for the <code>example-context</code> context type.
+ * <p>
+ * The following YANG snippet imports the <code>yang-ext</code> module and defines the list
+ * element named <code>item</code> inside a container named <code>foo</code>:
+ *
+ * <pre>
+ * module foo {
+ *     ...
+ *     import yang-ext {prefix ext;}
+ *     ...
+ *     container foo {
+ *          list item {
+ *              key "id";
+ *              leaf id {type string;}
+ *              ext:context-instance "example-context";
+ *          }
+ *     }
+ *     ...
+ * }
+ * </pre>
+ * <p>
+ * The statement <code>ext:context-instance "example-context";</code> inside the list element
+ * declares that any instance identifier referencing <code>item</code> in the data
+ * tree is valid for <code>example-context</code>. For example, the following instance
+ * identifier:
+ * <pre>
+ *     InstanceIdentifier.create(Foo.class).child(Item.class,new ItemKey("Foo"))
+ * </pre>
+ * is valid for <code>example-context</code>. However the following:
+ * <pre>
+ *     InstanceIdentifier.create(Example.class)
+ * </pre>
+ * is not valid.
+ * <p>
+ * So using an <code>identity</code> in combination with <code>context-instance</code> we
+ * have effectively defined a context type that can be referenced in a YANG RPC input.
+ *
+ * <h5>2. Defining an RPC to use the Context Type</h5>
+ * <p>
+ * To define an RPC to be routed based on the context type we need to add an input leaf element
+ * that references the context type which will hold an instance identifier value to be
+ * used to route the RPC.
+ * <p>
+ * The following snippet defines an RPC named <code>show-item</code> with 2 leaf elements
+ * as input: <code>item</code> of type <code>instance-identifier</code> and <code>description</code>:
+ *
+ * <pre>
+ * module foo {
+ *      ...
+ *      import yang-ext {prefix ext;}
+ *      ...
+ *      rpc show-item {
+ *          input {
+ *              leaf item {
+ *                  type instance-identifier;
+ *                  ext:context-reference example-context;
+ *              }
+ *              leaf description {
+ *                  type "string";
+ *              }
+ *          }
+ *      }
+ * }
+ * </pre>
+ * <p>
+ * We mark the <code>item</code> leaf with a <code>context-reference</code> statement that
+ * references the <code>example-context</code> context type. RPC calls will then be routed
+ * based on the instance identifier value contained in <code>item</code>. Only instance
+ * identifiers that point to a <code>foo/item</code> node are valid as input.
+ * <p>
+ * The generated RPC Service interface for the module is:
+ *
+ * <pre>
+ * interface FooService implements RpcService {
+ *      Future&lt;RpcResult&lt;Void&gt;&gt; showItem(ShowItemInput input);
+ * }
+ * </pre>
+ * <p>
+ * For constructing the RPC input, there are generated classes ShowItemInput and ShowItemInputBuilder.
+ *
+ * <h5>3. Registering a routed RPC implementation</h5>
+ * <p>
+ * To register a routed implementation for the <code>show-item</code> RPC, we must use the
+ * {@link #addRoutedRpcImplementation(Class, RpcService)} method. This
+ * will return a {@link RoutedRpcRegistration} instance which can then be used to register /
+ * unregister routed paths associated with the registered implementation.
+ * <p>
+ * The following snippet registers <code>myImpl</code> as the RPC implementation for an
+ * <code>item</code> with key <code>"foo"</code>:
+ * <pre>
+ * // Create the instance identifier path for item "foo"
+ * InstanceIdentifier path = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey(&quot;foo&quot;));
+ *
+ * // Register myImpl as the implementation for the FooService RPC interface
+ * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
+ *
+ * // Now register for the context type and specific path ID. The context type is specified by the
+ * // YANG-generated class for the example-context identity.
+ * reg.registerPath(ExampleContext.class, path);
+ * </pre>
+ * <p>
+ * It is also possible to register the same implementation for multiple paths:
+ *
+ * <pre>
+ * InstanceIdentifier one = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey(&quot;One&quot;));
+ * InstanceIdentifier two = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey(&quot;Two&quot;));
+ *
+ * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
+ * reg.registerPath(ExampleContext.class, one);
+ * reg.registerPath(ExampleContext.class, two);
+ * </pre>
+ *
+ * <p>
+ * When another client invokes the <code>showItem(ShowItemInput)</code> method on the proxy instance
+ * retrieved via {@link RpcConsumerRegistry#getRpcService(Class)}, the proxy will inspect the
+ * arguments in ShowItemInput, extract the InstanceIdentifier value of the <code>item</code> leaf and select
+ * the implementation whose registered path matches the InstanceIdentifier value of the <code>item</code> leaf.
+ *
+ * <h2>Notes for RPC Implementations</h2>
+ *
+ * <h3>RpcResult</h3>
+ * <p>
+ * The generated interfaces require implementors to return
+ *  {@link java.util.concurrent.Future Future}&lt;{@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}&lt;{RpcName}Output&gt;&gt; instances.
+ *
+ * Implementations should do processing of RPC calls asynchronously and update the
+ * returned {@link java.util.concurrent.Future Future} instance when processing is complete.
+ * However using {@link com.google.common.util.concurrent.Futures#immediateFuture(Object) Futures.immediateFuture}
+ * is valid only if the result is immediately available and asynchronous processing is unnecessary and
+ * would only introduce additional complexity.
+ *
+ * <p>
+ * The {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult} is a generic
+ * wrapper for the RPC output payload, if any, and also allows for attaching error or
+ * warning information (possibly along with the payload) should the RPC processing partially
+ * or completely fail. This is intended to provide additional human readable information
+ * for users of the API and to transfer warning / error information across the system
+ * so it may be visible via other external APIs such as Restconf.
+ * <p>
+ * It is recommended to use the {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
+ * for conveying appropriate error information
+ * on failure rather than purposely throwing unchecked exceptions if at all possible.
+ * While unchecked exceptions will fail the returned {@link java.util.concurrent.Future Future},
+ * using the intended RpcResult to convey the error information is more user-friendly.
  */
 public interface RpcProviderRegistry extends //
         RpcConsumerRegistry, //
         RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
     /**
-     * Registers a global RpcService implementation.
+     * Registers a global implementation of the provided RPC service interface.
+     * All methods of the interface are required to be implemented.
+     *
+     * @param serviceInterface the YANG-generated interface of the RPC Service for which to register.
+     * @param implementation "the implementation of the RPC service interface.
+     * @return an RpcRegistration instance that should be used to unregister the RPC implementation
+     *         when no longer needed by calling {@link RpcRegistration#close()}.
      *
-     * @param type
-     * @param implementation
-     * @return
+     * @throws IllegalStateException
+     *             if the supplied RPC interface is a routed RPC type.
      */
-    <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
+    <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation)
             throws IllegalStateException;
 
     /**
+     * Registers an implementation of the given routed RPC service interface.
+     * <p>
+     * See the {@link RpcProviderRegistry class} documentation for information and example on
+     * how to use routed RPCs.
      *
-     * Register a Routed RpcService where routing is determined on annotated
-     * (in YANG model) context-reference and value of annotated leaf.
-     *
-     * @param type
-     *            Type of RpcService, use generated interface class, not your
-     *            implementation class
-     * @param implementation
-     *            Implementation of RpcService
-     * @return Registration object for routed Rpc which could be used to unregister
+     * @param serviceInterface the YANG-generated interface of the RPC Service for which to register.
+     * @param implementation the implementation instance to register.
+     * @return a RoutedRpcRegistration instance which can be used to register paths for the RPC
+     *         implementation via invoking {@link RoutedRpcRegistration#registerPath(....).
+     *         {@link RoutedRpcRegistration#close()} should be called to unregister the implementation
+     *         and all previously registered paths when no longer needed.
      *
      * @throws IllegalStateException
+     *            if the supplied RPC interface is not a routed RPC type.
      */
-    <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type, T implementation)
+    <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface,
+                                                                               T implementation)
             throws IllegalStateException;
 }
index d0225768b4e2500acf0eccfb13e4999e0a8591e3..d30ca6beaf6fc209f600fbe09175895d4b9bdd62 100644 (file)
@@ -21,7 +21,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  *
  *
  * @see DataProviderService
+ * @deprecated Replaced by newer better documented version {@link org.opendaylight.controller.md.sal.binding.api.DataBroker}
  */
+@Deprecated
 public interface DataBrokerService extends //
         BindingAwareService, //
         DataModificationTransactionFactory<InstanceIdentifier<? extends DataObject>, DataObject>, //
@@ -31,16 +33,26 @@ public interface DataBrokerService extends //
      * Creates a data modification transaction.
      *
      * @return new blank data modification transaction.
+     * @deprecated Replaced by more specific transaction types. Please use
+     *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadOnlyTransaction(),
+     *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadWriteTransaction()
+     *          or
+     *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newWriteOnlyTransaction().
      */
+    @Deprecated
     @Override
     DataModificationTransaction beginTransaction();
 
     /**
      * Reads data subtree from configurational store.
      * (Store which is populated by consumer, which is usually used to
-     * inject state into providers. E.g. Flow configuration)-
+     * inject state into providers. E.g. Flow configuration)
+     *
+     *
+     * @deprecated Please use {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadOnlyTransaction()}
      *
      */
+    @Deprecated
     @Override
     public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path);
 
@@ -49,7 +61,9 @@ public interface DataBrokerService extends //
      * (Store which is populated by providers, which is usually used to
      * capture state of providers. E.g. Topology)
      *
+     * @deprecated Please use {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadOnlyTransaction()}
      */
+    @Deprecated
     @Override
     public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path);
 
@@ -58,7 +72,10 @@ public interface DataBrokerService extends //
      *
      * Callback is invoked each time data in subtree changes.
      *
+     * @deprecated Please use {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#registerDataChangeListener(org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType, InstanceIdentifier, org.opendaylight.controller.md.sal.binding.api.DataChangeListener, org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope)}
+     * which provides more fine-grained registration options.
      */
+    @Deprecated
     @Override
     public ListenerRegistration<DataChangeListener> registerDataChangeListener(
             InstanceIdentifier<? extends DataObject> path, DataChangeListener listener);
index 6373cfbf4a3ec6a67f8cdd2c3b423ea1eb5b4e28..e26cbcef29b7e40a3757425216f0253d706fcda1 100644 (file)
@@ -11,6 +11,12 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
+/**
+ *
+ * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}
+ *
+ */
+@Deprecated
 public interface DataChangeListener extends
         org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> {
 
index 5fafabbd1b6e9104bd72c3946acce0aa2e580871..0c250fdbee4c2454d0d9c1afa981ef71b4c05acc 100644 (file)
@@ -17,6 +17,18 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
+/**
+ *
+ *
+ * @deprecated Replaced by more specific transaction types. Please use
+ *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadOnlyTransaction(),
+ *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadWriteTransaction()
+ *          or
+ *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newWriteOnlyTransaction().
+ *
+ *
+ */
+@Deprecated
 public interface DataModificationTransaction extends DataModification<InstanceIdentifier<? extends DataObject>, DataObject> {
     /**
      * Returns an unique identifier for transaction
index b496d1dfb4ba58636e2af34abcd1e7cd186f4f55..5aa3b99b3009ea850c8131eef042391b0d7c6d5a 100644 (file)
@@ -16,7 +16,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 /**
  * DataProviderService is common access point for {@link org.opendaylight.controller.sal.binding.api.BindingAwareProvider} providers
  * to access data trees described by the YANG model.
+ *
+ * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.common.api.data.AsyncConfigurationCommitCoordinator} service.
  */
+@Deprecated
 public interface DataProviderService extends DataBrokerService, DataProvisionService<InstanceIdentifier<? extends DataObject>, DataObject> {
     /**
      * Registers a data reader for particular subtree of overal YANG data tree.
@@ -27,6 +30,8 @@ public interface DataProviderService extends DataBrokerService, DataProvisionSer
      * @param path Subpath which is handled by registered data reader
      * @param reader Instance of reader which
      * @return Registration object for reader. Invoking {@link Registration#close()} will unregister reader.
+     * @deprecated Data Reader contract is removed from capabilities of MD-SAL and is replaced by  replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore contract.
      */
+    @Deprecated
     Registration<DataReader<InstanceIdentifier<? extends DataObject>,DataObject>> registerDataReader(InstanceIdentifier<? extends DataObject> path,DataReader<InstanceIdentifier<? extends DataObject>,DataObject> reader);
 }
index 3334f2a037b119711916a52ad7c9d86b6424201d..c0c8f4f2112fd0ccb7dcde3427009595c880ccc2 100644 (file)
@@ -13,8 +13,9 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
  * Trigger for refreshing of the data exposed by the {@link Provider}
  *
  *
- *
+ * @deprecated Unused, not supported. Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore.
  */
+@Deprecated
 public interface DataRefresher extends BindingAwareProvider.ProviderFunctionality {
 
     /**
index 85a2b82ee0397174966e8e584a6607eb61de3433..273f20f01da8c27562017d7f4aede2a144c6bffe 100644 (file)
@@ -15,9 +15,11 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 /**
  * Utility interface which does type capture for BindingAware DataReader.
  *
- * @author
+ *
+ * @deprecated Removed, replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore.
  *
  */
+@Deprecated
 public interface RuntimeDataProvider extends ProviderFunctionality,DataReader<InstanceIdentifier<? extends DataObject>, DataObject> {
 
 
index da6d46d499317d647673cfb2b7ef5d60e43b2eae..fc0d3964ea07ff7d107d99e0278a0df7263f9772 100644 (file)
@@ -25,12 +25,19 @@ import com.google.common.base.Preconditions;
  *
  * To get instance of synchronized wrapper use {@link #from(DataModificationTransaction)}
  *
+ * @deprecated Replaced by more specific transaction types. Please use
+ *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadOnlyTransaction(),
+ *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newReadWriteTransaction()
+ *          or
+ *          {@link org.opendaylight.controller.md.sal.binding.api.DataBroker#newWriteOnlyTransaction().
+ *
  */
+@Deprecated
 public final class SynchronizedTransaction implements DataModificationTransaction,Delegator<DataModificationTransaction> {
 
     private final DataModificationTransaction delegate;
 
-    private SynchronizedTransaction(DataModificationTransaction delegate) {
+    private SynchronizedTransaction(final DataModificationTransaction delegate) {
         this.delegate = delegate;
     }
 
@@ -40,7 +47,7 @@ public final class SynchronizedTransaction implements DataModificationTransactio
      * @param transaction Transaction for which synchronized wrapper should be created.
      * @return Synchronized wrapper over transaction.
      */
-    public static final SynchronizedTransaction from(DataModificationTransaction transaction) {
+    public static final SynchronizedTransaction from(final DataModificationTransaction transaction) {
         Preconditions.checkArgument(transaction != null, "Transaction must not be null.");
         if (transaction instanceof SynchronizedTransaction) {
             return (SynchronizedTransaction) transaction;
@@ -59,7 +66,7 @@ public final class SynchronizedTransaction implements DataModificationTransactio
     }
 
     @Override
-    public synchronized DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+    public synchronized DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
         return delegate.readOperationalData(path);
     }
 
@@ -79,7 +86,7 @@ public final class SynchronizedTransaction implements DataModificationTransactio
     }
 
     @Override
-    public synchronized DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+    public synchronized DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
         return delegate.readConfigurationData(path);
     }
 
@@ -89,12 +96,12 @@ public final class SynchronizedTransaction implements DataModificationTransactio
     }
 
     @Override
-    public synchronized void putOperationalData(InstanceIdentifier<? extends DataObject> path, DataObject data) {
+    public synchronized void putOperationalData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
         delegate.putOperationalData(path, data);
     }
 
     @Override
-    public synchronized void putConfigurationData(InstanceIdentifier<? extends DataObject> path, DataObject data) {
+    public synchronized void putConfigurationData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
         delegate.putConfigurationData(path, data);
     }
 
@@ -104,12 +111,12 @@ public final class SynchronizedTransaction implements DataModificationTransactio
     }
 
     @Override
-    public synchronized void removeOperationalData(InstanceIdentifier<? extends DataObject> path) {
+    public synchronized void removeOperationalData(final InstanceIdentifier<? extends DataObject> path) {
         delegate.removeOperationalData(path);
     }
 
     @Override
-    public synchronized void removeConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+    public synchronized void removeConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
         delegate.removeConfigurationData(path);
     }
 
@@ -129,7 +136,7 @@ public final class SynchronizedTransaction implements DataModificationTransactio
     }
 
     @Override
-    public synchronized ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener) {
+    public synchronized ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
         return delegate.registerListener(listener);
     }
 
@@ -152,7 +159,7 @@ public final class SynchronizedTransaction implements DataModificationTransactio
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
index 2470ba513376e73669fe951f1f2fc9d77acf952f..35b186db6aeeaf5ed53ee8a7e43bf5d9e4fb1b82 100644 (file)
@@ -82,7 +82,6 @@
     <dependency>
       <groupId>org.reflections</groupId>
       <artifactId>reflections</artifactId>
-      <version>0.9.9-RC1</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
                             org.opendaylight.controller.md.sal.binding.impl,
               <!--org.opendaylight.controller.sal.binding.dom.*,-->
               org.opendaylight.controller.sal.binding.osgi.*,
-                            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.impl.rev131028
+                            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.impl.rev131028.*
             </Private-Package>
           </instructions>
         </configuration>
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingAsyncDataBrokerImplModule.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingAsyncDataBrokerImplModule.java
new file mode 100644 (file)
index 0000000..018e268
--- /dev/null
@@ -0,0 +1,63 @@
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.sal.core.api.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.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+public class BindingAsyncDataBrokerImplModule extends
+        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingAsyncDataBrokerImplModule implements
+        Provider {
+
+    public BindingAsyncDataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public BindingAsyncDataBrokerImplModule(
+            final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            final org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModule oldModule,
+            final java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        Broker domBroker = getDomAsyncBrokerDependency();
+        BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
+
+        // FIXME: Switch this to DOM Broker registration which would not require
+        // BundleContext when API are updated.
+        ProviderSession session = domBroker.registerProvider(this, null);
+        DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class);
+        SchemaService schemaService = session.getService(SchemaService.class);
+        return new ForwardedBindingDataBroker(domDataBroker, mappingService, schemaService);
+    }
+
+
+
+
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public void onSessionInitiated(final ProviderSession arg0) {
+        // intentional NOOP
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingAsyncDataBrokerImplModuleFactory.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingAsyncDataBrokerImplModuleFactory.java
new file mode 100644 (file)
index 0000000..a7c8843
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: opendaylight-sal-binding-broker-impl yang module local name: binding-forwarded-data-broker
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri May 16 17:18:18 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
+
+public class BindingAsyncDataBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingAsyncDataBrokerImplModuleFactory {
+
+}
index 44a508c0a0bd2561c20517323f47735479688611..61e7a2e6a240d9e7ab98574f7dd1bee2058ed987 100644 (file)
@@ -1,95 +1,85 @@
-/*\r
- * Copyright (c) 2014 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
-/**\r
- * Generated file\r
-\r
- * Generated from: yang module name: opendaylight-sal-binding-broker-impl  yang module local name: binding-broker-impl\r
- * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator\r
- * Generated at: Wed Nov 20 17:33:01 CET 2013\r
- *\r
- * Do not modify this file unless it is present under src/main directory\r
- */\r
-package org.opendaylight.controller.config.yang.md.sal.binding.impl;\r
-\r
-import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;\r
-import org.opendaylight.controller.sal.binding.impl.RootBindingAwareBroker;\r
-import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;\r
-import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBindingBrokerImpl;\r
-import org.opendaylight.controller.sal.binding.impl.forward.DomForwardingUtils;\r
-import org.osgi.framework.BundleContext;\r
-\r
-/**\r
-*\r
-*/\r
-public final class BindingBrokerImplModule extends\r
-        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingBrokerImplModule {\r
-\r
-    private BundleContext bundleContext;\r
-\r
-    public BindingBrokerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
-            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {\r
-        super(identifier, dependencyResolver);\r
-    }\r
-\r
-    public BindingBrokerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
-            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,\r
-            BindingBrokerImplModule oldModule, java.lang.AutoCloseable oldInstance) {\r
-        super(identifier, dependencyResolver, oldModule, oldInstance);\r
-    }\r
-\r
-    @Override\r
-    public void validate() {\r
-        super.validate();\r
-    }\r
-\r
-    @Override\r
-    public java.lang.AutoCloseable createInstance() {\r
-\r
-        RootBindingAwareBroker broker;\r
-        if (DomForwardingUtils.isDomForwardedBroker(getDataBrokerDependency())) {\r
-            broker = createForwardedBroker();\r
-        } else {\r
-            broker = createStandaloneBroker();\r
-        }\r
-        broker.start();\r
-        return broker;\r
-    }\r
-\r
-    private RootBindingAwareBroker createStandaloneBroker() {\r
-        RootBindingAwareBroker broker = new RootBindingAwareBroker(getIdentifier().getInstanceName());\r
-\r
-        broker.setDataBroker(getDataBrokerDependency());\r
-        broker.setNotificationBroker(getNotificationServiceDependency());\r
-        broker.setRpcBroker(new RpcProviderRegistryImpl(broker.getIdentifier()));\r
-        return broker;\r
-    }\r
-\r
-    private RootBindingAwareBroker createForwardedBroker() {\r
-        DomForwardedBindingBrokerImpl broker = new DomForwardedBindingBrokerImpl(getIdentifier().getInstanceName());\r
-\r
-        broker.setDataBroker(getDataBrokerDependency());\r
-        broker.setNotificationBroker(getNotificationServiceDependency());\r
-        broker.setRpcBroker(new RpcProviderRegistryImpl(broker.getIdentifier()));\r
-\r
-        broker.getMountManager().setDataCommitExecutor(SingletonHolder.getDefaultCommitExecutor());\r
-        broker.getMountManager().setNotificationExecutor(SingletonHolder.getDefaultNotificationExecutor());\r
-\r
-\r
-        DomForwardingUtils.reuseForwardingFrom(broker, broker.getDataBroker());\r
-        broker.startForwarding();\r
-        return broker;\r
-    }\r
-\r
-    public BundleContext getBundleContext() {\r
-        return bundleContext;\r
-    }\r
-\r
-    public void setBundleContext(BundleContext bundleContext) {\r
-        this.bundleContext = bundleContext;\r
-    }\r
-}\r
+/*
+ * 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: opendaylight-sal-binding-broker-impl  yang module local name: binding-broker-impl
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 20 17:33:01 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
+import org.opendaylight.controller.sal.binding.impl.RootBindingAwareBroker;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBindingBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.forward.DomForwardingUtils;
+
+/**
+*
+*/
+public final class BindingBrokerImplModule extends
+        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingBrokerImplModule {
+
+    public BindingBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public BindingBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            final BindingBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+
+        RootBindingAwareBroker broker;
+        if (DomForwardingUtils.isDomForwardedBroker(getDataBrokerDependency())) {
+            broker = createForwardedBroker();
+        } else {
+            broker = createStandaloneBroker();
+        }
+        broker.start();
+        return broker;
+    }
+
+    private RootBindingAwareBroker createStandaloneBroker() {
+        RootBindingAwareBroker broker = new RootBindingAwareBroker(getIdentifier().getInstanceName());
+
+        broker.setLegacyDataBroker(getDataBrokerDependency());
+        broker.setNotificationBroker(getNotificationServiceDependency());
+        broker.setRpcBroker(new RpcProviderRegistryImpl(broker.getIdentifier()));
+        broker.setDataBroker(getRootDataBrokerDependency());
+        return broker;
+    }
+
+    private RootBindingAwareBroker createForwardedBroker() {
+        DomForwardedBindingBrokerImpl broker = new DomForwardedBindingBrokerImpl(getIdentifier().getInstanceName());
+
+        broker.setLegacyDataBroker(getDataBrokerDependency());
+        broker.setNotificationBroker(getNotificationServiceDependency());
+        broker.setRpcBroker(new RpcProviderRegistryImpl(broker.getIdentifier()));
+
+        broker.getMountManager().setDataCommitExecutor(SingletonHolder.getDefaultCommitExecutor());
+        broker.getMountManager().setNotificationExecutor(SingletonHolder.getDefaultNotificationExecutor());
+
+        broker.setDataBroker(getRootDataBrokerDependency());
+        DomForwardingUtils.reuseForwardingFrom(broker, broker.getDataBroker());
+        broker.startForwarding();
+        return broker;
+    }
+}
index a11a7d67f5d4077006676dc476cf154e1de8ade8..181b568cf51e898a807053dbe16ab353fdfab2de 100644 (file)
 */
 package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
-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 BindingBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingBrokerImplModuleFactory {
 
-
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
-        BindingBrokerImplModule module = (BindingBrokerImplModule) super.createModule(instanceName, dependencyResolver, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver,
-            DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
-        BindingBrokerImplModule module = (BindingBrokerImplModule) super.createModule(instanceName, dependencyResolver, old, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
 }
index 7357926b9e6226a612bd0fc453dc28b737cff5b8..4a4e8000781381f906888369a8db0ac6b683e525 100644 (file)
@@ -5,8 +5,8 @@
  * 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.config.yang.md.sal.binding.impl;\r
-\r
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
 import java.util.concurrent.ExecutorService;
 
 import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
@@ -16,85 +16,64 @@ import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndepende
 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedDataBrokerImpl;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-\r
-/**\r
-*\r
-*/\r
-public final class DataBrokerImplModule extends\r
-        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractDataBrokerImplModule {\r
-\r
-    private BundleContext bundleContext;\r
-\r
-    public DataBrokerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
-            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {\r
-        super(identifier, dependencyResolver);\r
-    }\r
-\r
-    public DataBrokerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
-            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,\r
-            DataBrokerImplModule oldModule, java.lang.AutoCloseable oldInstance) {\r
-        super(identifier, dependencyResolver, oldModule, oldInstance);\r
-    }\r
-\r
-    @Override\r
-    public void validate() {\r
-        super.validate();\r
-    }\r
-\r
-    @Override\r
-    public java.lang.AutoCloseable createInstance() {\r
-        RootDataBrokerImpl dataBindingBroker;\r
-\r
-\r
-        ExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();\r
-        BindingIndependentMappingService potentialMapping = resolveMappingServiceDependency();\r
-        if (getDomBrokerDependency() != null && potentialMapping != null) {\r
-\r
-            dataBindingBroker = createDomConnectedBroker(listeningExecutor,potentialMapping);\r
-        } else {\r
-            dataBindingBroker = createStandAloneBroker(listeningExecutor);\r
-        }\r
-        dataBindingBroker.registerRuntimeBean(getRootRuntimeBeanRegistratorWrapper());\r
-        dataBindingBroker.setNotificationExecutor(SingletonHolder.getDefaultChangeEventExecutor());\r
-        return dataBindingBroker;\r
-    }\r
-    private BindingIndependentMappingService resolveMappingServiceDependency() {\r
-        if(getMappingService() != null) {\r
-            return getMappingServiceDependency();\r
-        }\r
-\r
-        ServiceReference<BindingIndependentMappingService> potentialMappingService = bundleContext.getServiceReference(BindingIndependentMappingService.class);\r
-        if(potentialMappingService != null) {\r
-            return bundleContext.getService(potentialMappingService);\r
-        }\r
-        return null;\r
-    }\r
-\r
-    private RootDataBrokerImpl createStandAloneBroker(ExecutorService listeningExecutor) {\r
-        RootDataBrokerImpl broker = new RootDataBrokerImpl();\r
-        broker.setExecutor(listeningExecutor);\r
-        return broker;\r
-    }\r
-\r
-    private RootDataBrokerImpl createDomConnectedBroker(ExecutorService listeningExecutor, BindingIndependentMappingService mappingService) {\r
-        DomForwardedDataBrokerImpl forwardedBroker = new DomForwardedDataBrokerImpl();\r
-        forwardedBroker.setExecutor(listeningExecutor);\r
-        BindingIndependentConnector connector = BindingDomConnectorDeployer.createConnector(mappingService);\r
-        getDomBrokerDependency().registerProvider(forwardedBroker, getBundleContext());\r
-        ProviderSession domContext = forwardedBroker.getDomProviderContext();\r
-        forwardedBroker.setConnector(connector);\r
-        forwardedBroker.setDomProviderContext(domContext);\r
-        forwardedBroker.startForwarding();\r
-        return forwardedBroker;\r
-    }\r
-\r
-    public BundleContext getBundleContext() {\r
-        return bundleContext;\r
-    }\r
-\r
-    public void setBundleContext(BundleContext bundleContext2) {\r
-        this.bundleContext = bundleContext2;\r
-    }\r
-}\r
+
+/**
+*
+*/
+public final class DataBrokerImplModule extends
+        org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractDataBrokerImplModule {
+
+    public DataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public DataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            final DataBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        RootDataBrokerImpl dataBindingBroker;
+
+
+        ExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();
+        BindingIndependentMappingService potentialMapping = getMappingServiceDependency();
+        if (getDomBrokerDependency() != null && potentialMapping != null) {
+
+            dataBindingBroker = createDomConnectedBroker(listeningExecutor,potentialMapping);
+        } else {
+            dataBindingBroker = createStandAloneBroker(listeningExecutor);
+        }
+        dataBindingBroker.registerRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
+        dataBindingBroker.setNotificationExecutor(SingletonHolder.getDefaultChangeEventExecutor());
+        return dataBindingBroker;
+    }
+
+
+    private RootDataBrokerImpl createStandAloneBroker(final ExecutorService listeningExecutor) {
+        RootDataBrokerImpl broker = new RootDataBrokerImpl();
+        broker.setExecutor(listeningExecutor);
+        return broker;
+    }
+
+    private RootDataBrokerImpl createDomConnectedBroker(final ExecutorService listeningExecutor, final BindingIndependentMappingService mappingService) {
+        DomForwardedDataBrokerImpl forwardedBroker = new DomForwardedDataBrokerImpl();
+        forwardedBroker.setExecutor(listeningExecutor);
+        BindingIndependentConnector connector = BindingDomConnectorDeployer.createConnector(mappingService);
+        getDomBrokerDependency().registerProvider(forwardedBroker, null);
+        ProviderSession domContext = forwardedBroker.getDomProviderContext();
+        forwardedBroker.setConnector(connector);
+        forwardedBroker.setDomProviderContext(domContext);
+        forwardedBroker.startForwarding();
+        return forwardedBroker;
+    }
+
+}
index 9ce3ebf73f26793089c171126e33db8c6d3d956d..d3fc5ac215d7c201e66e9dfdf6022cc12d1fe3eb 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
-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;
 
 /**
 *
@@ -18,21 +14,4 @@ import org.osgi.framework.BundleContext;
 public class DataBrokerImplModuleFactory extends
         org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractDataBrokerImplModuleFactory {
 
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
-        DataBrokerImplModule module = (DataBrokerImplModule) super.createModule(instanceName, dependencyResolver,
-                bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver,
-            DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
-        DataBrokerImplModule module = (DataBrokerImplModule) super.createModule(instanceName, dependencyResolver, old,
-                bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
 }
index 647ca85671a73bcca9f958bcc4b003e40d9e828a..0ea30f7e66a817f63c63cc81e20f3890170ea7b5 100644 (file)
@@ -19,7 +19,6 @@ import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
-import org.osgi.framework.BundleContext;
 
 import com.google.common.util.concurrent.ListeningExecutorService;
 
@@ -30,8 +29,6 @@ public final class ForwardedCompatibleDataBrokerImplModule extends
         org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModule
         implements Provider {
 
-    private BundleContext bundleContext;
-
     public ForwardedCompatibleDataBrokerImplModule(
             final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
             final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@@ -57,26 +54,17 @@ public final class ForwardedCompatibleDataBrokerImplModule extends
         BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
 
         Broker domBroker = getDomAsyncBrokerDependency();
-        ProviderSession session = domBroker.registerProvider(this, getBundleContext());
+        ProviderSession session = domBroker.registerProvider(this, null);
         DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class);
+        SchemaService schemaService = session.getService(SchemaService.class);
         ForwardedBackwardsCompatibleDataBroker dataBroker = new ForwardedBackwardsCompatibleDataBroker(domDataBroker,
-                mappingService, listeningExecutor);
-
-        session.getService(SchemaService.class).registerSchemaServiceListener(dataBroker);
+                mappingService, schemaService,listeningExecutor);
 
         dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(getBindingMappingServiceDependency()));
         dataBroker.setDomProviderContext(session);
         return dataBroker;
     }
 
-    public BundleContext getBundleContext() {
-        return bundleContext;
-    }
-
-    public void setBundleContext(final BundleContext bundleContext2) {
-        this.bundleContext = bundleContext2;
-    }
-
     @Override
     public void onSessionInitiated(final ProviderSession session) {
 
index f01977503e8239128ac5b3bb022d6c4278bc863b..5b5fb45fd9904eb80ece3e9de0faa56351f6f796 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
-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;
 
 
 /**
@@ -19,20 +15,4 @@ import org.osgi.framework.BundleContext;
 public class ForwardedCompatibleDataBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractForwardedCompatibleDataBrokerImplModuleFactory
 {
 
-
-    @Override
-    public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
-        ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule) super.createModule(instanceName, dependencyResolver, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
-    @Override
-    public Module createModule(final String instanceName, final DependencyResolver dependencyResolver,
-            final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
-        ForwardedCompatibleDataBrokerImplModule module = (ForwardedCompatibleDataBrokerImplModule)  super.createModule(instanceName, dependencyResolver, old, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
 }
index 2a866a94b358ebcc031c5965e16305dcc5930b0f..b109f89ff61adfb016b9eaa5e86818b0ec6b6965 100644 (file)
@@ -7,14 +7,16 @@
  */
 package org.opendaylight.controller.md.sal.binding.impl;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -23,6 +25,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBroker;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -33,14 +36,16 @@ import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMapping
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
 
 public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker,
-        SchemaContextListener {
+        SchemaContextListener, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedDataBroker.class);
     // The Broker to whom we do all forwarding
@@ -53,12 +58,14 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     private final BindingToNormalizedNodeCodec codec;
     private BindingIndependentConnector connector;
     private ProviderSession context;
+    private final ListenerRegistration<SchemaServiceListener> schemaListenerRegistration;
 
     protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
-            final BindingIndependentMappingService mappingService) {
+            final BindingIndependentMappingService mappingService,final SchemaService schemaService) {
         this.domDataBroker = domDataBroker;
         this.mappingService = mappingService;
         this.codec = new BindingToNormalizedNodeCodec(mappingService);
+        this.schemaListenerRegistration = schemaService.registerSchemaServiceListener(this);
     }
 
     protected BindingToNormalizedNodeCodec getCodec() {
@@ -79,8 +86,8 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         codec.onGlobalContextUpdated(ctx);
     }
 
-    public ListenerRegistration<BindingDataChangeListener> registerDataChangeListener(final LogicalDatastoreType store,
-            final InstanceIdentifier<?> path, final BindingDataChangeListener listener,
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path, final DataChangeListener listener,
             final DataChangeScope triggeringScope) {
         DOMDataChangeListener domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener,
                 triggeringScope);
@@ -93,8 +100,8 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     protected Map<InstanceIdentifier<?>, DataObject> toBinding(
             final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
         Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
-        for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized
-                .entrySet()) {
+
+        for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : sortedEntries(normalized)) {
             try {
                 Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(
                         entry);
@@ -109,6 +116,21 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         return newMap;
     }
 
+    private static <T> Iterable<Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier,T>> sortedEntries(final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, T> map) {
+        ArrayList<Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, T>> entries = new ArrayList<>(map.entrySet());
+        Collections.sort(entries, new Comparator<Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, T>>() {
+
+            @Override
+            public int compare(final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, T> left,
+                    final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, T> right) {
+                int leftSize = Iterables.size(left.getKey().getPathArguments());
+                int rightSize = Iterables.size(right.getKey().getPathArguments());
+                return Integer.compare(leftSize, rightSize);
+            }
+        });
+        return entries;
+    }
+
     protected Set<InstanceIdentifier<?>> toBinding(
             final Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> normalized) {
         Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
@@ -139,13 +161,13 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     }
 
     private class TranslatingDataChangeInvoker implements DOMDataChangeListener {
-        private final BindingDataChangeListener bindingDataChangeListener;
+        private final DataChangeListener bindingDataChangeListener;
         private final LogicalDatastoreType store;
         private final InstanceIdentifier<?> path;
         private final DataChangeScope triggeringScope;
 
         public TranslatingDataChangeInvoker(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
-                final BindingDataChangeListener bindingDataChangeListener, final DataChangeScope triggeringScope) {
+                final DataChangeListener bindingDataChangeListener, final DataChangeScope triggeringScope) {
             this.store = store;
             this.path = path;
             this.bindingDataChangeListener = bindingDataChangeListener;
@@ -246,10 +268,10 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         }
     }
 
-    private static class ListenerRegistrationImpl extends AbstractListenerRegistration<BindingDataChangeListener> {
+    private static class ListenerRegistrationImpl extends AbstractListenerRegistration<DataChangeListener> {
         private final ListenerRegistration<DOMDataChangeListener> registration;
 
-        public ListenerRegistrationImpl(final BindingDataChangeListener listener,
+        public ListenerRegistrationImpl(final DataChangeListener listener,
                 final ListenerRegistration<DOMDataChangeListener> registration) {
             super(listener);
             this.registration = registration;
@@ -286,4 +308,9 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         // NOOP
     }
 
+    @Override
+    public void close() throws Exception {
+        this.schemaListenerRegistration.close();
+    }
+
 }
index a935a33a5eb26ee13371554165db996f390469b8..e5e1e300c17437e52962218f168da911b3f54526 100644 (file)
  */
 package org.opendaylight.controller.md.sal.binding.impl;
 
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Nullable;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-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.dom.api.DOMDataReadTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
 import com.google.common.base.Optional;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
+import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
-public class AbstractForwardedTransaction<T extends AsyncTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>>
-        implements Delegator<T> {
 
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedTransaction.class);
+abstract class AbstractForwardedTransaction<T extends AsyncTransaction<InstanceIdentifier, NormalizedNode<?, ?>>>
+        implements Delegator<T>, Identifiable<Object> {
+
     private final T delegate;
-    private final static CacheBuilder<Object, Object> CACHE_BUILDER = CacheBuilder.newBuilder()
-            .expireAfterWrite(10, TimeUnit.MILLISECONDS).maximumSize(100);
     private final BindingToNormalizedNodeCodec codec;
-    private final EnumMap<LogicalDatastoreType, Cache<InstanceIdentifier<?>, DataObject>> cacheMap;
 
-    protected AbstractForwardedTransaction(final T delegate, final BindingToNormalizedNodeCodec codec) {
-        super();
-        this.delegate = delegate;
-        this.codec = codec;
+    public AbstractForwardedTransaction(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
+        this.delegate = Preconditions.checkNotNull(delegateTx, "Delegate must not be null");
+        this.codec = Preconditions.checkNotNull(codec, "Codec must not be null");
+    }
 
-        this.cacheMap = new EnumMap<>(LogicalDatastoreType.class);
-        cacheMap.put(LogicalDatastoreType.OPERATIONAL, CACHE_BUILDER.<InstanceIdentifier<?>, DataObject> build());
-        cacheMap.put(LogicalDatastoreType.CONFIGURATION, CACHE_BUILDER.<InstanceIdentifier<?>, DataObject> build());
 
+    @Override
+    public final  Object getIdentifier() {
+        return delegate.getIdentifier();
     }
 
     @Override
-    public T getDelegate() {
+    public final  T getDelegate() {
         return delegate;
     }
 
-    protected final BindingToNormalizedNodeCodec getCodec() {
-        return codec;
-    }
-
-    protected ListenableFuture<Optional<DataObject>> transformFuture(final LogicalDatastoreType store,
-            final InstanceIdentifier<?> path, final ListenableFuture<Optional<NormalizedNode<?, ?>>> future) {
-        return Futures.transform(future, new Function<Optional<NormalizedNode<?, ?>>, Optional<DataObject>>() {
-            @Nullable
-            @Override
-            public Optional<DataObject> apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
-                if (normalizedNode.isPresent()) {
-                    final DataObject dataObject;
-                    try {
-                        dataObject = codec.toBinding(path, normalizedNode.get());
-                    } catch (DeserializationException e) {
-                        LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e);
-                        throw new IllegalStateException("Failed to create dataobject", e);
-                    }
-
-                    if (dataObject != null) {
-                        updateCache(store, path, dataObject);
-                        return Optional.of(dataObject);
-                    }
-                }
-                return Optional.absent();
-            }
-        });
-    }
-
-    protected void doPut(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
-            final InstanceIdentifier<?> path, final DataObject data) {
-        invalidateCache(store, path);
-        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
-                .toNormalizedNode(path, data);
-        writeTransaction.put(store, normalized.getKey(), normalized.getValue());
-    }
-
-    protected void doPutWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction,
-            final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
-        invalidateCache(store, path);
-        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
-                .toNormalizedNode(path, data);
-
-        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
-        ensureParentsByMerge(writeTransaction, store, normalizedPath, path);
-        LOG.debug("Tx: {} : Putting data {}", getDelegate().getIdentifier(), normalizedPath);
-        writeTransaction.put(store, normalizedPath, normalized.getValue());
-    }
-
-    protected void doMergeWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction,
-            final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
-        invalidateCache(store, path);
-        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
-                .toNormalizedNode(path, data);
-
-        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
-        ensureParentsByMerge(writeTransaction, store, normalizedPath, path);
-        LOG.debug("Tx: {} : Merge data {}",getDelegate().getIdentifier(),normalizedPath);
-        writeTransaction.merge(store, normalizedPath, normalized.getValue());
+    @SuppressWarnings("unchecked")
+    protected final <S extends AsyncTransaction<InstanceIdentifier, NormalizedNode<?, ?>>> S getDelegateChecked(final Class<S> txType) {
+        Preconditions.checkState(txType.isInstance(delegate));
+        return (S) delegate;
     }
 
-    private void ensureParentsByMerge(final DOMDataReadWriteTransaction writeTransaction,
-            final LogicalDatastoreType store,
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath,
-            final InstanceIdentifier<?> path) {
-        List<PathArgument> currentArguments = new ArrayList<>();
-        DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
-        Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
-        while (iterator.hasNext()) {
-            PathArgument currentArg = iterator.next();
-            try {
-                currentOp = currentOp.getChild(currentArg);
-            } catch (DataNormalizationException e) {
-                throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", path), e);
-            }
-            currentArguments.add(currentArg);
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
-                    currentArguments);
-
-            final Optional<NormalizedNode<?, ?>> d;
-            try {
-                d = writeTransaction.read(store, currentPath).get();
-            } catch (InterruptedException | ExecutionException e) {
-                LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
-                throw new IllegalStateException("Failed to read pre-existing data", e);
-            }
-
-            if (!d.isPresent() && iterator.hasNext()) {
-                writeTransaction.merge(store, currentPath, currentOp.createDefault(currentArg));
-            }
-        }
-    }
-
-    protected void doMerge(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
-            final InstanceIdentifier<?> path, final DataObject data) {
-        invalidateCache(store, path);
-        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
-                .toNormalizedNode(path, data);
-        writeTransaction.merge(store, normalized.getKey(), normalized.getValue());
-    }
-
-    protected void doDelete(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
-            final InstanceIdentifier<?> path) {
-        invalidateCache(store, path);
-        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = codec.toNormalized(path);
-        writeTransaction.delete(store, normalized);
-    }
-
-    protected ListenableFuture<RpcResult<TransactionStatus>> doCommit(final DOMDataWriteTransaction writeTransaction) {
-        return writeTransaction.commit();
-    }
-
-    protected void doCancel(final DOMDataWriteTransaction writeTransaction) {
-        writeTransaction.cancel();
-    }
-
-    protected ListenableFuture<Optional<DataObject>> doRead(final DOMDataReadTransaction readTransaction,
-            final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
-        final DataObject dataObject = getFromCache(store, path);
-        if (dataObject == null) {
-            final ListenableFuture<Optional<NormalizedNode<?, ?>>> future = readTransaction.read(store,
-                    codec.toNormalized(path));
-            return transformFuture(store, path, future);
-        } else {
-            return Futures.immediateFuture(Optional.of(dataObject));
-        }
-    }
-
-    private DataObject getFromCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
-        Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
-        if (cache != null) {
-            return cache.getIfPresent(path);
-        }
-        return null;
-    }
-
-    private void updateCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
-            final DataObject dataObject) {
-        // Check if cache exists. If not create one.
-        Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
-        if (cache == null) {
-            cache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(1, TimeUnit.MINUTES).build();
-
-        }
-
-        cache.put(path, dataObject);
+    protected final BindingToNormalizedNodeCodec getCodec() {
+        return codec;
     }
 
-    private void invalidateCache(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
-        // FIXME: Optimization: invalidate only parents and children of path
-        Cache<InstanceIdentifier<?>, DataObject> cache = cacheMap.get(store);
-        cache.invalidateAll();
-        LOG.trace("Cache invalidated");
+    protected final ListenableFuture<Optional<DataObject>> doRead(final DOMDataReadTransaction readTx,
+            final LogicalDatastoreType store, final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> path) {
+        return Futures.transform(readTx.read(store, codec.toNormalized(path)), codec.deserializeFunction(path));
     }
-
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java
new file mode 100644 (file)
index 0000000..3988bc6
--- /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.md.sal.binding.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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;
+
+public class AbstractReadWriteTransaction extends AbstractWriteTransaction<DOMDataReadWriteTransaction> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractReadWriteTransaction.class);
+
+    public AbstractReadWriteTransaction(final DOMDataReadWriteTransaction delegate, final BindingToNormalizedNodeCodec codec) {
+        super(delegate, codec);
+    }
+
+    protected final void doPutWithEnsureParents(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec()
+                .toNormalizedNode(path, data);
+
+        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+        ensureParentsByMerge(store, normalizedPath, path);
+        LOG.debug("Tx: {} : Putting data {}", getDelegate().getIdentifier(), normalizedPath);
+        doPut(store, path, data);
+    }
+
+    protected final void doMergeWithEnsureParents(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec()
+                .toNormalizedNode(path, data);
+
+        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+        ensureParentsByMerge(store, normalizedPath, path);
+        LOG.debug("Tx: {} : Merge data {}", getDelegate().getIdentifier(), normalizedPath);
+        doMerge(store, path, data);
+    }
+
+    private final void ensureParentsByMerge(final LogicalDatastoreType store,
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath,
+            final InstanceIdentifier<?> path) {
+        List<PathArgument> currentArguments = new ArrayList<>();
+        DataNormalizationOperation<?> currentOp = getCodec().getDataNormalizer().getRootOperation();
+        Iterator<PathArgument> iterator = normalizedPath.getPathArguments().iterator();
+        while (iterator.hasNext()) {
+            PathArgument currentArg = iterator.next();
+            try {
+                currentOp = currentOp.getChild(currentArg);
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", path), e);
+            }
+            currentArguments.add(currentArg);
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(
+                    currentArguments);
+
+            final Optional<NormalizedNode<?, ?>> d;
+            try {
+                d = getDelegate().read(store, currentPath).get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
+                throw new IllegalStateException("Failed to read pre-existing data", e);
+            }
+
+            if (!d.isPresent() && iterator.hasNext()) {
+                getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg));
+            }
+        }
+    }
+
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractWriteTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractWriteTransaction.java
new file mode 100644 (file)
index 0000000..5ce6687
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.binding.impl;
+
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ *
+ * Abstract Base Transaction for transactions which are backed by
+ * {@link DOMDataWriteTransaction}
+ */
+public class AbstractWriteTransaction<T extends DOMDataWriteTransaction> extends
+        AbstractForwardedTransaction<T> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractWriteTransaction.class);
+
+    protected AbstractWriteTransaction(final T delegate,
+            final BindingToNormalizedNodeCodec codec) {
+        super(delegate, codec);
+    }
+
+    protected final void doPut(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path, final DataObject data) {
+        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec()
+                .toNormalizedNode(path, data);
+        getDelegate().put(store, normalized.getKey(), normalized.getValue());
+    }
+
+    protected final void doMerge(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path, final DataObject data) {
+        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec()
+                .toNormalizedNode(path, data);
+        getDelegate().merge(store, normalized.getKey(), normalized.getValue());
+    }
+
+    protected final void doDelete(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = getCodec().toNormalized(path);
+        getDelegate().delete(store, normalized);
+    }
+
+    protected final ListenableFuture<RpcResult<TransactionStatus>> doCommit() {
+        return getDelegate().commit();
+    }
+
+    protected final boolean doCancel() {
+        return getDelegate().cancel();
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataReadTransactionImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataReadTransactionImpl.java
new file mode 100644 (file)
index 0000000..e71404d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+class BindingDataReadTransactionImpl extends AbstractForwardedTransaction<DOMDataReadOnlyTransaction> implements
+        ReadOnlyTransaction {
+
+    protected BindingDataReadTransactionImpl(final DOMDataReadOnlyTransaction delegate,
+            final BindingToNormalizedNodeCodec codec) {
+        super(delegate, codec);
+    }
+
+    @Override
+    public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        return doRead(getDelegate(),store, path);
+    }
+
+    @Override
+    public void close() {
+        getDelegate().close();
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataReadWriteTransactionImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataReadWriteTransactionImpl.java
new file mode 100644 (file)
index 0000000..5a89cc7
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.binding.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+class BindingDataReadWriteTransactionImpl extends
+        BindingDataWriteTransactionImpl<DOMDataReadWriteTransaction> implements ReadWriteTransaction {
+
+    protected BindingDataReadWriteTransactionImpl(final DOMDataReadWriteTransaction delegate,
+            final BindingToNormalizedNodeCodec codec) {
+        super(delegate, codec);
+    }
+
+    @Override
+    public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        return doRead(getDelegate(), store, path);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataWriteTransactionImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataWriteTransactionImpl.java
new file mode 100644 (file)
index 0000000..a62319b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.binding.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+class BindingDataWriteTransactionImpl<T extends DOMDataWriteTransaction> extends
+        AbstractWriteTransaction<T> implements WriteTransaction {
+
+    protected BindingDataWriteTransactionImpl(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
+        super(delegateTx, codec);
+    }
+
+
+
+    @Override
+    public void put(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+        doPut(store, path, data);
+    }
+
+    @Override
+    public void merge(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+        doMerge(store, path, data);
+    }
+
+    @Override
+    public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        doDelete( store, path);
+    }
+
+    @Override
+    public ListenableFuture<RpcResult<TransactionStatus>> commit() {
+        return doCommit();
+    }
+
+    @Override
+    public boolean cancel() {
+        return doCancel();
+    }
+}
\ No newline at end of file
index f1be5c6922ecda45cc75f343b3f6355e402e013d..6b519955accd308109657dcb44823e4bca3d595d 100644 (file)
@@ -14,6 +14,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
 
+import javax.annotation.Nullable;
+
 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;
@@ -42,7 +44,9 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
@@ -75,7 +79,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     public Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
             final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
-        return toNormalizedNode(toEntry(bindingPath, bindingObject));
+        return toNormalizedNode(toBindingEntry(bindingPath, bindingObject));
 
     }
 
@@ -87,17 +91,16 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
                 .toNormalized(legacyEntry);
         LOG.trace("Serialization of {}, Legacy Representation: {}, Normalized Representation: {}", binding,
                 legacyEntry, normalizedEntry);
-        if (Augmentation.class.isAssignableFrom(binding.getKey().getTargetType())) {
+        if (isAugmentation(binding.getKey().getTargetType())) {
 
             for (DataContainerChild<? extends PathArgument, ?> child : ((DataContainerNode<?>) normalizedEntry
                     .getValue()).getValue()) {
                 if (child instanceof AugmentationNode) {
                     ImmutableList<PathArgument> childArgs = ImmutableList.<PathArgument> builder()
-                            .addAll(normalizedEntry.getKey().getPath()).add(child.getIdentifier()).build();
-                    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
+                            .addAll(normalizedEntry.getKey().getPathArguments()).add(child.getIdentifier()).build();
+                    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(
                             childArgs);
-                    return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>(
-                            childPath, child);
+                    return toDOMEntry(childPath, child);
                 }
             }
 
@@ -117,9 +120,9 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
      */
     public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DeserializationException {
+                    throws DeserializationException {
 
-        PathArgument lastArgument = Iterables.getLast(normalized.getPath());
+        PathArgument lastArgument = Iterables.getLast(normalized.getPathArguments());
         // Used instance-identifier codec do not support serialization of last
         // path
         // argument if it is AugmentationIdentifier (behaviour expected by old
@@ -134,7 +137,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     private Optional<InstanceIdentifier<? extends DataObject>> toBindingAugmented(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DeserializationException {
+                    throws DeserializationException {
         Optional<InstanceIdentifier<? extends DataObject>> potential = toBindingImpl(normalized);
         // Shorthand check, if codec already supports deserialization
         // of AugmentationIdentifier we will return
@@ -143,7 +146,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         }
 
         int normalizedCount = getAugmentationCount(normalized);
-        AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPath());
+        AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPathArguments());
 
         // Here we employ small trick - Binding-aware Codec injects an pointer
         // to augmentation class
@@ -151,9 +154,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         // 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());
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = normalized.node(child);
             try {
                 if (isNotRepresentable(childPath)) {
                     LOG.trace("Path {} is not BI-representable, skipping it", childPath);
@@ -186,7 +187,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DeserializationException {
+                    throws DeserializationException {
         org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath;
 
         try {
@@ -216,21 +217,28 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     private DataNormalizationOperation<?> findNormalizationOperation(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DataNormalizationException {
+                    throws DataNormalizationException {
         DataNormalizationOperation<?> current = legacyToNormalized.getRootOperation();
-        for (PathArgument arg : normalized.getPath()) {
+        for (PathArgument arg : normalized.getPathArguments()) {
             current = current.getChild(arg);
         }
         return current;
     }
 
-    private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toEntry(
+    private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBindingEntry(
             final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> key,
             final DataObject value) {
         return new SimpleEntry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>(
                 key, value);
     }
 
+    private static final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toDOMEntry(
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier key,
+            final NormalizedNode<?, ?> value) {
+        return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>(
+                key, value);
+    }
+
     public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
             throws DeserializationException {
         CompositeNode legacy = null;
@@ -254,7 +262,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     public Optional<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
             final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
-            throws DeserializationException {
+                    throws DeserializationException {
         Optional<InstanceIdentifier<? extends DataObject>> potentialPath = toBinding(normalized.getKey());
         if (potentialPath.isPresent()) {
             InstanceIdentifier<? extends DataObject> bindingPath = potentialPath.get();
@@ -262,7 +270,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             if (bindingData == null) {
                 LOG.warn("Failed to deserialize {} to Binding format. Binding path is: {}", normalized, bindingPath);
             }
-            return Optional.of(toEntry(bindingPath, bindingData));
+            return Optional.of(toBindingEntry(bindingPath, bindingData));
         } else {
             return Optional.absent();
         }
@@ -304,15 +312,15 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) {
         int position = 0;
         int foundPosition = -1;
-        for (PathArgument arg : normalized.getPath()) {
+        for (PathArgument arg : normalized.getPathArguments()) {
             position++;
             if (arg instanceof AugmentationIdentifier) {
                 foundPosition = position;
             }
         }
         if (foundPosition > 0) {
-            return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(normalized.getPath().subList(0,
-                    foundPosition));
+            Iterable<PathArgument> shortened = Iterables.limit(normalized.getPathArguments(), foundPosition);
+            return org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(shortened);
         }
         return null;
     }
@@ -365,18 +373,18 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             try {
                 return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
                         new Supplier<Class>() {
-                            @Override
-                            public Class get() {
-                                Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
-                                        .getGenericReturnType());
-                                if (listResult instanceof Class
-                                        && DataObject.class.isAssignableFrom((Class) listResult)) {
-                                    return (Class<?>) listResult;
-                                }
-                                return null;
-                            }
-
-                        });
+                    @Override
+                    public Class get() {
+                        Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
+                                .getGenericReturnType());
+                        if (listResult instanceof Class
+                                && DataObject.class.isAssignableFrom((Class) listResult)) {
+                            return (Class<?>) listResult;
+                        }
+                        return null;
+                    }
+
+                });
             } catch (Exception e) {
                 LOG.debug("Could not get YANG modeled entity for {}", method, e);
                 return null;
@@ -404,7 +412,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
     }
 
     private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed) {
-        return Iterables.getLast(processed.getPath()) instanceof AugmentationIdentifier;
+        return Iterables.getLast(processed.getPathArguments()) instanceof AugmentationIdentifier;
     }
 
     private static int getAugmentationCount(final InstanceIdentifier<?> potential) {
@@ -420,11 +428,46 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
 
     private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier potential) {
         int count = 0;
-        for(PathArgument arg : potential.getPath()) {
+        for(PathArgument arg : potential.getPathArguments()) {
             if(arg instanceof AugmentationIdentifier) {
                 count++;
             }
         }
         return count;
     }
+
+    public Function<Optional<NormalizedNode<?, ?>>, Optional<DataObject>>  deserializeFunction(final InstanceIdentifier<?> path) {
+        return new DeserializeFunction(this, path);
+    }
+
+    private static class DeserializeFunction implements Function<Optional<NormalizedNode<?, ?>>, Optional<DataObject>> {
+
+        private final BindingToNormalizedNodeCodec codec;
+        private final InstanceIdentifier<?> path;
+
+        public DeserializeFunction(final BindingToNormalizedNodeCodec codec, final InstanceIdentifier<?> path) {
+            super();
+            this.codec = Preconditions.checkNotNull(codec, "Codec must not be null");
+            this.path = Preconditions.checkNotNull(path, "Path must not be null");
+        }
+
+        @Nullable
+        @Override
+        public Optional<DataObject> apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
+            if (normalizedNode.isPresent()) {
+                final DataObject dataObject;
+                try {
+                    dataObject = codec.toBinding(path, normalizedNode.get());
+                } catch (DeserializationException e) {
+                    LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e);
+                    throw new IllegalStateException("Failed to create dataobject", e);
+                }
+
+                if (dataObject != null) {
+                    return Optional.of(dataObject);
+                }
+            }
+            return Optional.absent();
+        }
+    }
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingTranslatedTransactionChain.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingTranslatedTransactionChain.java
new file mode 100644 (file)
index 0000000..2d8e51c
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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.binding.impl;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
+import org.opendaylight.yangtools.concepts.Delegator;
+
+import com.google.common.base.Preconditions;
+
+class BindingTranslatedTransactionChain implements BindingTransactionChain, Delegator<DOMTransactionChain> {
+
+    private final DOMTransactionChain delegate;
+
+    @GuardedBy("this")
+    private final Map<AsyncTransaction<?, ?>, AsyncTransaction<?, ?>> delegateTxToBindingTx = new WeakHashMap<>();
+    private final BindingToNormalizedNodeCodec codec;
+
+    public BindingTranslatedTransactionChain(final DOMDataBroker chainFactory,
+            final BindingToNormalizedNodeCodec codec, final TransactionChainListener listener) {
+        Preconditions.checkNotNull(chainFactory, "DOM Transaction chain factory must not be null");
+        this.delegate = chainFactory.createTransactionChain(new ListenerInvoker(listener));
+        this.codec = codec;
+    }
+
+    @Override
+    public DOMTransactionChain getDelegate() {
+        return delegate;
+    }
+
+    @Override
+    public ReadOnlyTransaction newReadOnlyTransaction() {
+        DOMDataReadOnlyTransaction delegateTx = delegate.newReadOnlyTransaction();
+        ReadOnlyTransaction bindingTx = new BindingDataReadTransactionImpl(delegateTx, codec);
+        putDelegateToBinding(delegateTx, bindingTx);
+        return bindingTx;
+    }
+
+    @Override
+    public ReadWriteTransaction newReadWriteTransaction() {
+        DOMDataReadWriteTransaction delegateTx = delegate.newReadWriteTransaction();
+        ReadWriteTransaction bindingTx = new BindingDataReadWriteTransactionImpl(delegateTx, codec);
+        putDelegateToBinding(delegateTx, bindingTx);
+        return bindingTx;
+    }
+
+    @Override
+    public WriteTransaction newWriteOnlyTransaction() {
+        DOMDataWriteTransaction delegateTx = delegate.newWriteOnlyTransaction();
+        WriteTransaction bindingTx = new BindingDataWriteTransactionImpl<>(delegateTx, codec);
+        putDelegateToBinding(delegateTx, bindingTx);
+        return bindingTx;
+    }
+
+    @Override
+    public void close() {
+        delegate.close();
+    }
+
+    private synchronized void putDelegateToBinding(final AsyncTransaction<?, ?> domTx,
+            final AsyncTransaction<?, ?> bindingTx) {
+        final Object previous = delegateTxToBindingTx.put(domTx, bindingTx);
+        Preconditions.checkState(previous == null, "DOM Transaction %s has already associated binding transation %s",domTx,previous);
+    }
+
+    private synchronized AsyncTransaction<?, ?> getBindingTransaction(final AsyncTransaction<?, ?> transaction) {
+        return delegateTxToBindingTx.get(transaction);
+    }
+
+    private final class ListenerInvoker implements TransactionChainListener {
+
+        private final TransactionChainListener listener;
+
+        public ListenerInvoker(final TransactionChainListener listener) {
+            this.listener = Preconditions.checkNotNull(listener, "Listener must not be null.");
+        }
+
+        @Override
+        public void onTransactionChainFailed(final TransactionChain<?, ?> chain,
+                final AsyncTransaction<?, ?> transaction, final Throwable cause) {
+            Preconditions.checkState(delegate.equals(chain),
+                    "Illegal state - listener for %s was invoked for incorrect chain %s.", delegate, chain);
+            AsyncTransaction<?, ?> bindingTx = getBindingTransaction(transaction);
+            listener.onTransactionChainFailed(chain, bindingTx, cause);
+        }
+
+        @Override
+        public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
+            Preconditions.checkState(delegate.equals(chain),
+                    "Illegal state - listener for %s was invoked for incorrect chain %s.", delegate, chain);
+            listener.onTransactionChainSuccessful(BindingTranslatedTransactionChain.this);
+        }
+    }
+
+}
index e08e9a4e0580556d038cbe01e6de2dc0ed064735..1c6447a4e741615b714657c9356dc6b756fe44c0 100644 (file)
@@ -18,7 +18,6 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 
-import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
@@ -35,6 +34,7 @@ import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -60,12 +60,11 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
     private static final Logger LOG = LoggerFactory.getLogger(ForwardedBackwardsCompatibleDataBroker.class);
 
     private final ConcurrentHashMap<InstanceIdentifier<?>, CommitHandlerRegistrationImpl> commitHandlers = new ConcurrentHashMap<>();
-    private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
     private final ListeningExecutorService executorService;
 
     public ForwardedBackwardsCompatibleDataBroker(final DOMDataBroker domDataBroker,
-            final BindingIndependentMappingService mappingService, final ListeningExecutorService executor) {
-        super(domDataBroker, mappingService);
+            final BindingIndependentMappingService mappingService, final SchemaService schemaService,final ListeningExecutorService executor) {
+        super(domDataBroker, mappingService,schemaService);
         executorService = executor;
         LOG.info("ForwardedBackwardsCompatibleBroker started.");
     }
@@ -113,11 +112,11 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
             final InstanceIdentifier<? extends DataObject> path, final DataChangeListener listener) {
 
 
-        BindingDataChangeListener asyncOperListener = new BackwardsCompatibleOperationalDataChangeInvoker(listener);
-        BindingDataChangeListener asyncCfgListener = new BackwardsCompatibleConfigurationDataChangeInvoker(listener);
+        org.opendaylight.controller.md.sal.binding.api.DataChangeListener asyncOperListener = new BackwardsCompatibleOperationalDataChangeInvoker(listener);
+        org.opendaylight.controller.md.sal.binding.api.DataChangeListener asyncCfgListener = new BackwardsCompatibleConfigurationDataChangeInvoker(listener);
 
-        ListenerRegistration<BindingDataChangeListener> cfgReg = registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, asyncCfgListener, DataChangeScope.SUBTREE);
-        ListenerRegistration<BindingDataChangeListener> operReg = registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, path, asyncOperListener, DataChangeScope.SUBTREE);
+        ListenerRegistration<org.opendaylight.controller.md.sal.binding.api.DataChangeListener> cfgReg = registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, asyncCfgListener, DataChangeScope.SUBTREE);
+        ListenerRegistration<org.opendaylight.controller.md.sal.binding.api.DataChangeListener> operReg = registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, path, asyncOperListener, DataChangeScope.SUBTREE);
 
         return new LegacyListenerRegistration(listener,cfgReg,operReg);
     }
@@ -129,12 +128,6 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
         throw new UnsupportedOperationException("Data reader contract is not supported.");
     }
 
-    @Override
-    public void close() throws Exception {
-        // TODO Auto-generated method stub
-
-    }
-
     public ListenableFuture<RpcResult<TransactionStatus>> commit(final ForwardedBackwardsCompatibleTransacion tx) {
 
         final List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> subTrans = new ArrayList<>();
@@ -193,7 +186,7 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
     }
 
     private class ForwardedBackwardsCompatibleTransacion extends
-            AbstractForwardedTransaction<DOMDataReadWriteTransaction> implements DataModificationTransaction {
+            AbstractReadWriteTransaction implements DataModificationTransaction {
 
         private final ListenerRegistry<DataTransactionListener> listeners = ListenerRegistry.create();
         private final Map<InstanceIdentifier<? extends DataObject>, DataObject> updated = new HashMap<>();
@@ -221,9 +214,9 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
         public void putOperationalData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
             boolean previouslyRemoved = posponedRemovedOperational.remove(path);
             if(previouslyRemoved) {
-                doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+                doPutWithEnsureParents(LogicalDatastoreType.OPERATIONAL, path, data);
             } else {
-                doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+                doMergeWithEnsureParents(LogicalDatastoreType.OPERATIONAL, path, data);
             }
         }
 
@@ -239,9 +232,9 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
             }
             updated.put(path, data);
             if(previouslyRemoved) {
-                doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+                doPutWithEnsureParents(LogicalDatastoreType.CONFIGURATION, path, data);
             } else {
-                doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+                doMergeWithEnsureParents(LogicalDatastoreType.CONFIGURATION, path, data);
             }
         }
 
@@ -315,11 +308,6 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
             }
         }
 
-        @Override
-        public Object getIdentifier() {
-            return getDelegate().getIdentifier();
-        }
-
         private void changeStatus(final TransactionStatus status) {
             LOG.trace("Transaction {} changed status to {}", getIdentifier(), status);
             this.status = status;
@@ -337,11 +325,11 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
         public ListenableFuture<RpcResult<TransactionStatus>> commit() {
 
             for(InstanceIdentifier<? extends DataObject> path : posponedRemovedConfiguration) {
-                doDelete(getDelegate(), LogicalDatastoreType.CONFIGURATION, path);
+                doDelete(LogicalDatastoreType.CONFIGURATION, path);
             }
 
             for(InstanceIdentifier<? extends DataObject> path : posponedRemovedOperational) {
-                doDelete(getDelegate(), LogicalDatastoreType.OPERATIONAL, path);
+                doDelete(LogicalDatastoreType.OPERATIONAL, path);
             }
 
             changeStatus(TransactionStatus.SUBMITED);
@@ -393,12 +381,12 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
     private static final class LegacyListenerRegistration implements ListenerRegistration<DataChangeListener> {
 
         private final DataChangeListener instance;
-        private final ListenerRegistration<BindingDataChangeListener> cfgReg;
-        private final ListenerRegistration<BindingDataChangeListener> operReg;
+        private final ListenerRegistration<org.opendaylight.controller.md.sal.binding.api.DataChangeListener> cfgReg;
+        private final ListenerRegistration<org.opendaylight.controller.md.sal.binding.api.DataChangeListener> operReg;
 
         public LegacyListenerRegistration(final DataChangeListener listener,
-                final ListenerRegistration<BindingDataChangeListener> cfgReg,
-                final ListenerRegistration<BindingDataChangeListener> operReg) {
+                final ListenerRegistration<org.opendaylight.controller.md.sal.binding.api.DataChangeListener> cfgReg,
+                final ListenerRegistration<org.opendaylight.controller.md.sal.binding.api.DataChangeListener> operReg) {
             this.instance = listener;
             this.cfgReg = cfgReg;
             this.operReg = operReg;
@@ -417,7 +405,7 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
 
     }
 
-    private static class BackwardsCompatibleOperationalDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
+    private static class BackwardsCompatibleOperationalDataChangeInvoker implements org.opendaylight.controller.md.sal.binding.api.DataChangeListener, Delegator<DataChangeListener> {
 
         private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
 
@@ -442,7 +430,7 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat
 
     }
 
-    private static class BackwardsCompatibleConfigurationDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
+    private static class BackwardsCompatibleConfigurationDataChangeInvoker implements org.opendaylight.controller.md.sal.binding.api.DataChangeListener, Delegator<DataChangeListener> {
         private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
 
         public BackwardsCompatibleConfigurationDataChangeInvoker(final DataChangeListener listener) {
index fb06b130ce9f00465f01aff7d9918db087ca8886..6359b60684ef45e18d2185d1231b14b165497724 100644 (file)
@@ -7,26 +7,17 @@
  */
 package org.opendaylight.controller.md.sal.binding.impl;
 
-import org.opendaylight.controller.md.sal.binding.api.BindingDataBroker;
-import org.opendaylight.controller.md.sal.binding.api.BindingDataReadTransaction;
-import org.opendaylight.controller.md.sal.binding.api.BindingDataReadWriteTransaction;
-import org.opendaylight.controller.md.sal.binding.api.BindingDataWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-
 /**
  * The DataBrokerImpl simply defers to the DOMDataBroker for all its operations.
  * All transactions and listener registrations are wrapped by the DataBrokerImpl
@@ -35,111 +26,32 @@ import com.google.common.util.concurrent.ListenableFuture;
  * Besides this the DataBrokerImpl and it's collaborators also cache data that
  * is already transformed from the binding independent to binding aware format
  *
- * TODO : All references in this class to CompositeNode should be switched to
- * NormalizedNode once the MappingService is updated
- *
+
  */
-public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements BindingDataBroker {
+public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements DataBroker {
 
-    public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService) {
-        super(domDataBroker, mappingService);
+    public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService, final SchemaService schemaService) {
+        super(domDataBroker, mappingService,schemaService);
     }
 
     @Override
-    public BindingDataReadTransaction newReadOnlyTransaction() {
+
+    public ReadOnlyTransaction newReadOnlyTransaction() {
         return new BindingDataReadTransactionImpl(getDelegate().newReadOnlyTransaction(),getCodec());
     }
 
     @Override
-    public BindingDataReadWriteTransaction newReadWriteTransaction() {
+    public ReadWriteTransaction newReadWriteTransaction() {
         return new BindingDataReadWriteTransactionImpl(getDelegate().newReadWriteTransaction(),getCodec());
     }
 
     @Override
-    public BindingDataWriteTransaction newWriteOnlyTransaction() {
-        return new BindingDataWriteTransactionImpl<DOMDataWriteTransaction>(getDelegate().newWriteOnlyTransaction(),getCodec());
-    }
-
-    private abstract class AbstractBindingTransaction<T extends AsyncTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>>
-            extends AbstractForwardedTransaction<T> implements AsyncTransaction<InstanceIdentifier<?>, DataObject> {
-
-        protected AbstractBindingTransaction(final T delegate, final BindingToNormalizedNodeCodec codec) {
-            super(delegate, codec);
-        }
-
-        @Override
-        public Object getIdentifier() {
-            return getDelegate().getIdentifier();
-        }
-
-        @Override
-        public void close() {
-            getDelegate().close();
-        }
-
+    public WriteTransaction newWriteOnlyTransaction() {
+        return new BindingDataWriteTransactionImpl<>(getDelegate().newWriteOnlyTransaction(),getCodec());
     }
 
-    private class BindingDataReadTransactionImpl extends AbstractBindingTransaction<DOMDataReadTransaction> implements
-            BindingDataReadTransaction {
-
-        protected BindingDataReadTransactionImpl(final DOMDataReadTransaction delegate,
-                final BindingToNormalizedNodeCodec codec) {
-            super(delegate, codec);
-        }
-
-        @Override
-        public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
-                final InstanceIdentifier<?> path) {
-            return doRead(getDelegate(), store, path);
-        }
-    }
-
-    private class BindingDataWriteTransactionImpl<T extends DOMDataWriteTransaction> extends
-            AbstractBindingTransaction<T> implements BindingDataWriteTransaction {
-
-        protected BindingDataWriteTransactionImpl(final T delegate, final BindingToNormalizedNodeCodec codec) {
-            super(delegate, codec);
-
-        }
-
-        @Override
-        public void cancel() {
-            doCancel(getDelegate());
-        }
-
-        @Override
-        public void put(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
-            doPut(getDelegate(), store, path, data);
-        }
-
-        @Override
-        public void merge(final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
-            doMerge(getDelegate(), store, path, data);
-        }
-
-        @Override
-        public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
-            doDelete(getDelegate(), store, path);
-        }
-
-        @Override
-        public ListenableFuture<RpcResult<TransactionStatus>> commit() {
-            return doCommit(getDelegate());
-        }
-    }
-
-    private class BindingDataReadWriteTransactionImpl extends
-            BindingDataWriteTransactionImpl<DOMDataReadWriteTransaction> implements BindingDataReadWriteTransaction {
-
-        protected BindingDataReadWriteTransactionImpl(final DOMDataReadWriteTransaction delegate,
-                final BindingToNormalizedNodeCodec codec) {
-            super(delegate, codec);
-        }
-
-        @Override
-        public ListenableFuture<Optional<DataObject>> read(final LogicalDatastoreType store,
-                final InstanceIdentifier<?> path) {
-            return doRead(getDelegate(), store, path);
-        }
+    @Override
+    public BindingTransactionChain createTransactionChain(final TransactionChainListener listener) {
+        return new BindingTranslatedTransactionChain(getDelegate(), getCodec(), listener);
     }
 }
index 3fef544f8115879aa5dc9df4c7d4ab1306d6ca1a..00c9f1eb91a14f7f1df97a73bc871cac9e918058 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.yangtools.yang.binding.util.BindingReflections
 import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils
 
 import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
+import org.opendaylight.yangtools.yang.binding.RpcService
 
 class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
 
@@ -28,7 +29,7 @@ class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
             val proxyName = iface.directProxyName;
             val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName)
             if(potentialClass != null) {
-                return potentialClass.newInstance;
+                return potentialClass.newInstance as RpcService;
             }
             val supertype = iface.asCtClass
             val createdCls = createClass(iface.directProxyName, supertype) [
@@ -53,7 +54,7 @@ class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
                     '''
                 ]
             ]
-            return createdCls.toClass(iface.classLoader).newInstance
+            return createdCls.toClass(iface.classLoader).newInstance as RpcService
         ]
     }
 
@@ -63,7 +64,7 @@ class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
             val routerName = iface.routerName;
             val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName)
             if(potentialClass != null) {
-                return potentialClass.newInstance;
+                return potentialClass.newInstance as RpcService;
             }
 
             val targetCls = createClass(iface.routerName, supertype) [
@@ -106,7 +107,7 @@ class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
                     '''
                 ]
             ]
-            return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance
+            return  targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as RpcService
         ];
     }
 
index 75d44db9d190df195e80381ce2611f50ccd5ef68..d810149c7077b663701d5385352f67da10ab7361 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.controller.sal.binding.impl;
 
-import com.google.common.collect.ImmutableClassToInstanceMap;
+import static com.google.common.base.Preconditions.checkState;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.util.AbstractBindingSalProviderInstance;
 import org.opendaylight.controller.md.sal.binding.util.BindingContextUtils;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
@@ -32,13 +34,13 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableClassToInstanceMap;
 
 public class RootBindingAwareBroker implements //
         Mutable, //
         Identifiable<String>, //
-        BindingAwareBroker, AutoCloseable,
-        RpcProviderRegistry {
+        BindingAwareBroker, AutoCloseable, RpcProviderRegistry {
 
     private final static Logger LOG = LoggerFactory.getLogger(RootBindingAwareBroker.class);
 
@@ -50,7 +52,9 @@ public class RootBindingAwareBroker implements //
 
     private NotificationProviderService notificationBroker;
 
-    private DataProviderService dataBroker;
+    private DataProviderService legacyDataBroker;
+
+    private DataBroker dataBroker;
 
     private MountPointManagerImpl mountManager;
 
@@ -58,7 +62,7 @@ public class RootBindingAwareBroker implements //
         return mountManager;
     }
 
-    public void setMountManager(MountPointManagerImpl mountManager) {
+    public void setMountManager(final MountPointManagerImpl mountManager) {
         this.mountManager = mountManager;
     }
 
@@ -66,11 +70,12 @@ public class RootBindingAwareBroker implements //
 
     private ImmutableClassToInstanceMap<BindingAwareService> supportedProviderServices;
 
-    public RootBindingAwareBroker(String instanceName) {
+    public RootBindingAwareBroker(final String instanceName) {
         this.identifier = instanceName;
         mountManager = new MountPointManagerImpl();
     }
 
+    @Override
     public String getIdentifier() {
         return identifier;
     }
@@ -80,7 +85,7 @@ public class RootBindingAwareBroker implements //
     }
 
     public DataProviderService getDataBroker() {
-        return this.dataBroker;
+        return this.legacyDataBroker;
     }
 
     public NotificationProviderService getNotificationBroker() {
@@ -95,16 +100,16 @@ public class RootBindingAwareBroker implements //
         return rpcBroker;
     }
 
-    public void setRpcBroker(RpcProviderRegistry rpcBroker) {
+    public void setRpcBroker(final RpcProviderRegistry rpcBroker) {
         this.rpcBroker = rpcBroker;
     }
 
-    public void setNotificationBroker(NotificationProviderService notificationBroker) {
+    public void setNotificationBroker(final NotificationProviderService notificationBroker) {
         this.notificationBroker = notificationBroker;
     }
 
-    public void setDataBroker(DataProviderService dataBroker) {
-        this.dataBroker = dataBroker;
+    public void setLegacyDataBroker(final DataProviderService dataBroker) {
+        this.legacyDataBroker = dataBroker;
     }
 
     public void start() {
@@ -113,29 +118,30 @@ public class RootBindingAwareBroker implements //
 
         controllerRoot = new RootSalInstance(getRpcProviderRegistry(), getNotificationBroker(), getDataBroker());
 
+        ImmutableClassToInstanceMap.Builder<BindingAwareService> consBuilder = ImmutableClassToInstanceMap.builder();
 
-        supportedConsumerServices = ImmutableClassToInstanceMap.<BindingAwareService> builder()
-                .put(NotificationService.class, getRoot()) //
-                .put(DataBrokerService.class, getRoot()) //
-                .put(RpcConsumerRegistry.class, getRoot()) //
-                .put(MountService.class, mountManager).build();
-
+        consBuilder.put(NotificationService.class, getRoot());
+        consBuilder.put(DataBrokerService.class, getRoot());
+        consBuilder.put(RpcConsumerRegistry.class, getRoot());
+        if(dataBroker != null) {
+            consBuilder.put(DataBroker.class, dataBroker);
+        }
+        consBuilder.put(MountService.class, mountManager).build();
+        supportedConsumerServices = consBuilder.build();
         supportedProviderServices = ImmutableClassToInstanceMap.<BindingAwareService> builder()
-                .putAll(supportedConsumerServices)
-                .put(NotificationProviderService.class, getRoot()) //
-                .put(DataProviderService.class, getRoot()) //
-                .put(RpcProviderRegistry.class, getRoot()) //
+                .putAll(supportedConsumerServices).put(NotificationProviderService.class, getRoot())
+                .put(DataProviderService.class, getRoot()).put(RpcProviderRegistry.class, getRoot())
                 .put(MountProviderService.class, mountManager).build();
     }
 
     @Override
-    public ConsumerContext registerConsumer(BindingAwareConsumer consumer, BundleContext ctx) {
+    public ConsumerContext registerConsumer(final BindingAwareConsumer consumer, final BundleContext ctx) {
         checkState(supportedConsumerServices != null, "Broker is not initialized.");
         return BindingContextUtils.createConsumerContextAndInitialize(consumer, supportedConsumerServices);
     }
 
     @Override
-    public ProviderContext registerProvider(BindingAwareProvider provider, BundleContext ctx) {
+    public ProviderContext registerProvider(final BindingAwareProvider provider, final BundleContext ctx) {
         checkState(supportedProviderServices != null, "Broker is not initialized.");
         return BindingContextUtils.createProviderContextAndInitialize(provider, supportedProviderServices);
     }
@@ -146,34 +152,38 @@ public class RootBindingAwareBroker implements //
     }
 
     @Override
-    public <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type, T implementation)
-            throws IllegalStateException {
+    public <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(final Class<T> type,
+            final T implementation) throws IllegalStateException {
         return getRoot().addRoutedRpcImplementation(type, implementation);
     }
 
     @Override
-    public <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
+    public <T extends RpcService> RpcRegistration<T> addRpcImplementation(final Class<T> type, final T implementation)
             throws IllegalStateException {
         return getRoot().addRpcImplementation(type, implementation);
     }
 
     @Override
-    public <T extends RpcService> T getRpcService(Class<T> module) {
+    public <T extends RpcService> T getRpcService(final Class<T> module) {
         return getRoot().getRpcService(module);
     }
+
     @Override
     public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
-            L arg0) {
+            final L arg0) {
         return getRoot().registerRouteChangeListener(arg0);
     }
 
-
     public class RootSalInstance extends
             AbstractBindingSalProviderInstance<DataProviderService, NotificationProviderService, RpcProviderRegistry> {
 
-        public RootSalInstance(RpcProviderRegistry rpcRegistry, NotificationProviderService notificationBroker,
-                DataProviderService dataBroker) {
+        public RootSalInstance(final RpcProviderRegistry rpcRegistry,
+                final NotificationProviderService notificationBroker, final DataProviderService dataBroker) {
             super(rpcRegistry, notificationBroker, dataBroker);
         }
     }
+
+    public void setDataBroker(final DataBroker asyncDataBroker) {
+        dataBroker = asyncDataBroker;
+    }
 }
index 428025a58df58180085c4811f441f7f5a0e5d702..cee4b1efb3a3107e27fa5325dd6d3f92cc937609 100644 (file)
@@ -42,6 +42,12 @@ module opendaylight-sal-binding-broker-impl {
         config:provided-service sal:binding-data-consumer-broker;
         config:java-name-prefix ForwardedCompatibleDataBrokerImpl;
     }
+    
+    identity binding-forwarded-data-broker {
+        base config:module-type;
+        config:provided-service sal:binding-async-data-broker;
+        config:java-name-prefix BindingAsyncDataBrokerImpl;
+    }
 
     identity binding-rpc-broker {
         base config:module-type;
@@ -62,6 +68,26 @@ module opendaylight-sal-binding-broker-impl {
         config:java-name-prefix RuntimeMapping;
     }
 
+    grouping dom-forwarding-component {
+        container dom-async-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity dom:dom-broker-osgi-registry;
+                    }
+                }
+            }
+
+        container binding-mapping-service {
+            uses config:service-ref {
+                refine type {
+                    mandatory true;
+                    config:required-identity binding-dom-mapping-service;
+                }
+            }
+        }
+    }
+
     augment "/config:modules/config:module/config:configuration" {
         case binding-broker-impl {
             when "/config:modules/config:module/config:type = 'binding-broker-impl'";
@@ -79,7 +105,7 @@ module opendaylight-sal-binding-broker-impl {
             container data-broker {
                 uses config:service-ref {
                     refine type {
-                        mandatory true;
+                        mandatory false;
                         config:required-identity sal:binding-data-broker;
                     }
                 }
@@ -93,6 +119,15 @@ module opendaylight-sal-binding-broker-impl {
                     }
                 }
             }
+
+            container root-data-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory false;
+                        config:required-identity sal:binding-async-data-broker;
+                    }
+                }
+            }
         }
     }
 
@@ -123,22 +158,15 @@ module opendaylight-sal-binding-broker-impl {
         case binding-data-compatible-broker {
             when "/config:modules/config:module/config:type = 'binding-data-compatible-broker'";
 
-            container dom-async-broker {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity dom:dom-broker-osgi-registry;
-                    }
-                }
-            }
-
-            container binding-mapping-service {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity binding-dom-mapping-service;
-                    }
-                }
+            uses dom-forwarding-component;
+        }
+    }
+    
+    augment "/config:modules/config:module/config:configuration" {
+        case binding-forwarded-data-broker {
+            when "/config:modules/config:module/config:type = 'binding-forwarded-data-broker'";
+            container binding-forwarded-data-broker {
+                uses dom-forwarding-component;
             }
         }
     }
index ae65c8889a52d15dc5ce7d275ae84140c1fe2f66..1ea56381ef1cf9a4b248d2be2795d6c290f81c0d 100644 (file)
@@ -48,7 +48,6 @@ import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -57,7 +56,6 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.reflections.Reflections;
 import org.reflections.scanners.ResourcesScanner;
@@ -68,9 +66,10 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.ClassToInstanceMap;
 import com.google.common.collect.ImmutableClassToInstanceMap;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.MutableClassToInstanceMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
-public class BindingTestContext implements AutoCloseable, SchemaContextProvider {
+public class BindingTestContext implements AutoCloseable {
 
     public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
             .builder().toInstance();
@@ -101,22 +100,19 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
 
     private MountPointManagerImpl biMountImpl;
 
-    private SchemaContext schemaContext;
+
 
     private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
 
     private BackwardsCompatibleDataBroker biCompatibleBroker;
 
-    private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
-
     private DataProviderService baData;
 
     private DOMDataBroker newDOMDataBroker;
 
-    @Override
-    public SchemaContext getSchemaContext() {
-        return schemaContext;
-    }
+    private final MockSchemaService mockSchemaService = new MockSchemaService();
+
+
 
     public DOMDataBroker getDomAsyncDataBroker() {
         return newDOMDataBroker;
@@ -128,6 +124,7 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
         this.startWithSchema = startWithSchema;
     }
 
+    @Deprecated
     public void startDomDataStore() {
         checkState(dataStore == null, "DataStore already started.");
         checkState(biDataImpl != null, "Dom Data Broker not present");
@@ -140,7 +137,7 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
         } else {
             dataStore = schemaAwareDataStore;
         }
-
+        mockSchemaService.registerSchemaServiceListener(schemaAwareDataStore);
         biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
         biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
         biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
@@ -164,11 +161,10 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
 
         newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor);
 
-        biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker);
+        biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker,mockSchemaService);
 
-        schemaListeners.add(configStore);
-        schemaListeners.add(operStore);
-        schemaListeners.add(biCompatibleBroker);
+        mockSchemaService.registerSchemaServiceListener(configStore);
+        mockSchemaService.registerSchemaServiceListener(operStore);
         biDataLegacyBroker = biCompatibleBroker;
     }
 
@@ -188,7 +184,7 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
         baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
         baBrokerImpl.getMountManager().setNotificationExecutor(executor);
         baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
-        baBrokerImpl.setDataBroker(baData);
+        baBrokerImpl.setLegacyDataBroker(baData);
         baBrokerImpl.setNotificationBroker(baNotifyImpl);
         baBrokerImpl.start();
     }
@@ -268,20 +264,11 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
     public void startBindingToDomMappingService() {
         checkState(classPool != null, "ClassPool needs to be present");
         mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
+        mockSchemaService.registerSchemaServiceListener(mappingServiceImpl);
     }
 
     public void updateYangSchema(final String[] files) {
-        schemaContext = getContext(files);
-
-        if (schemaAwareDataStore != null) {
-            schemaAwareDataStore.onGlobalContextUpdated(schemaContext);
-        }
-        if (mappingServiceImpl != null) {
-            mappingServiceImpl.onGlobalContextUpdated(schemaContext);
-        }
-        for(SchemaContextListener listener : schemaListeners) {
-            listener.onGlobalContextUpdated(schemaContext);
-        }
+        mockSchemaService.changeSchema(getContext(files));
     }
 
     public static String[] getAllYangFilesOnClasspath() {
@@ -340,8 +327,7 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
     }
 
     public void startNewBindingDataBroker() {
-        ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl, executor);
-        schemaListeners.add(forwarded);
+        ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl,mockSchemaService, executor);
         baData = forwarded;
     }
 
@@ -352,8 +338,10 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
 
     private void startDomBroker() {
         checkState(executor != null);
-        biBrokerImpl = new BrokerImpl();
-        biBrokerImpl.setRouter(new SchemaAwareRpcBroker("/", this));
+
+        SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", mockSchemaService);
+        ClassToInstanceMap<BrokerService> services = MutableClassToInstanceMap.create();
+        biBrokerImpl = new BrokerImpl(router,services);
 
     }
 
@@ -429,4 +417,6 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
     public MountProvisionService getDomMountProviderService() {
         return biMountImpl;
     }
+
+
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java
new file mode 100644 (file)
index 0000000..c8acbcd
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.binding.test.util;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+
+@SuppressWarnings("deprecation")
+public final class MockSchemaService implements SchemaService, SchemaContextProvider {
+
+    private SchemaContext schemaContext;
+
+    ListenerRegistry<SchemaServiceListener> listeners = ListenerRegistry.create();
+
+    @Override
+    public void addModule(final Module module) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public synchronized SchemaContext getGlobalContext() {
+        return schemaContext;
+    }
+
+    @Override
+    public synchronized SchemaContext getSessionContext() {
+        return schemaContext;
+    }
+
+    @Override
+    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(
+            final SchemaServiceListener listener) {
+        return listeners.register(listener);
+    }
+
+    @Override
+    public void removeModule(final Module module) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public synchronized SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    public synchronized void changeSchema(final SchemaContext newContext) {
+        schemaContext = newContext;
+        for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+            listener.getInstance().onGlobalContextUpdated(schemaContext);
+        }
+    }
+}
\ No newline at end of file
index 38f0da3ccc92711dc46a56865a4afb4e03a176c5..8636ff613bb2c480e7dd62367ef2174a73ceed73 100644 (file)
@@ -22,6 +22,11 @@ module opendaylight-md-sal-binding {
         base "config:service-type";
         config:java-class "org.opendaylight.controller.sal.binding.api.data.DataProviderService";
     }
+    
+    identity binding-async-data-broker {
+        base "config:service-type";
+        config:java-class "org.opendaylight.controller.md.sal.binding.api.DataBroker";
+    }
 
     identity binding-data-consumer-broker {
         base "config:service-type";
index d1354f897fdcd45133c3ae17c5045a1ddf046095..fd5c5be18dc787c2bc6ae2237df3ce848b930ee7 100644 (file)
@@ -48,7 +48,6 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
-      <version>1.7.2</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
index 800c1b4cc426e1ef09c04983f594ecb059d036d1..667887ac805f3c8ea538df89da2d22d147b62ade 100644 (file)
@@ -20,7 +20,7 @@ import java.util.concurrent.ExecutionException;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.Lists;
@@ -139,7 +139,7 @@ public class ListProcessingAndOrderingTest extends AbstractDataServiceTest {
     private NormalizedNode<?, ?> resolveDataAsserted(
             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath) {
 
-        try (DOMDataReadTransaction readTx = testContext.getDomAsyncDataBroker().newReadOnlyTransaction()){
+        try (DOMDataReadOnlyTransaction readTx = testContext.getDomAsyncDataBroker().newReadOnlyTransaction()){
             ListenableFuture<Optional<NormalizedNode<?, ?>>> data = readTx.read(LogicalDatastoreType.OPERATIONAL, domPath);
             Optional<NormalizedNode<?, ?>> potential = data.get();
             assertTrue(potential.isPresent());
index 70847aabea0bdeb3670352f2a44c17c8aca3b703..b8bb891e790f7e905edc071c04e61608d4f277c1 100644 (file)
@@ -9,11 +9,9 @@
   <artifactId>sal-binding-it</artifactId>
 
   <properties>
-    <exam.version>3.0.0</exam.version>
     <sonar.jacoco.itReportPath>../sal-binding-broker/target/jacoco-it.exec</sonar.jacoco.itReportPath>
     <!-- Sonar jacoco plugin to get integration test coverage info -->
     <sonar.jacoco.reportPath>../sal-binding-broker/target/jacoco.exec</sonar.jacoco.reportPath>
-    <url.version>1.5.0</url.version>
   </properties>
 
   <dependencies>
@@ -80,7 +78,6 @@
     <dependency>
       <groupId>org.opendaylight.yangtools.thirdparty</groupId>
       <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-      <version>4.0</version>
     </dependency>
     <!--Compile scopes for all testing dependencies are intentional-->
     <!--This way, all testing dependencies can be transitively used by other integration test modules-->
@@ -90,7 +87,6 @@
     <dependency>
       <groupId>org.opendaylight.yangtools.thirdparty</groupId>
       <artifactId>xtend-lib-osgi</artifactId>
-      <version>2.4.3</version>
     </dependency>
     <dependency>
       <groupId>org.openexi</groupId>
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.14.1</version>
         <configuration>
           <reuseForks>false</reuseForks>
         </configuration>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
-        <version>1.2.4</version>
         <executions>
           <execution>
             <id>generate-config</id>
index a15c711e2d2eb88c0a5647baaaa4bdc168a91cac..5ede600d9777917a0df963c01b5a08128057f722 100644 (file)
@@ -119,7 +119,7 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), // //
 
 
-
+                mavenBundle(CONTROLLER, "sal-inmemory-datastore").versionAsInProject(), // /
                 mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), // //
                 mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
 
index 37ef257224d30ad749a6030557fab85f7fb734c6..63a921d6f309db37a0a438bbadbafdaadb528485 100644 (file)
@@ -20,7 +20,6 @@
                 </capability>
                 <capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&amp;revision=2010-09-24
                 </capability>
-                <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability>
                 <capability>urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&amp;revision=2010-09-24
                 </capability>
                 <capability>
index 7d7e56dae0ac824d4cacf84f8750a893de549283..53abd39cde85d6af6f24b02108cb890ae690491c 100644 (file)
@@ -14,7 +14,6 @@ import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.Notification;
@@ -72,13 +71,13 @@ public abstract class AbstractBindingSalConsumerInstance<D extends DataBrokerSer
     }
 
     @Override
-    public <T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(
+    public <T extends Notification> ListenerRegistration<NotificationListener<T>> registerNotificationListener(
             Class<T> notificationType, NotificationListener<T> listener) {
         return getNotificationBrokerChecked().registerNotificationListener(notificationType, listener);
     }
 
     @Override
-    public Registration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(
+    public ListenerRegistration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(
             org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
         return getNotificationBrokerChecked().registerNotificationListener(listener);
     }
index 87bbfd3d065a374e729c5f4e894bc4f40ddb17f9..3a68092f07e27f0ffe56dc090c01a0e04b37d3fd 100644 (file)
@@ -10,6 +10,49 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ *
+ * Base interface that provides access to a conceptual data tree store and also provides the ability to
+ * subscribe for changes to data under a given branch of the tree.
+ *
+ * <p>
+ * All operations on the data tree are performed via one of the transactions:
+ * <ul>
+ * <li>Read-Only - allocated using {@link #newReadOnlyTransaction()}
+ * <li>Write-Only - allocated using {@link #newWriteOnlyTransaction()}
+ * <li>Read-Write - allocated using {@link #newReadWriteTransaction()}
+ * </ul>
+ *
+ * <p>
+ * These transactions provide a stable isolated view of data tree, which is
+ * guaranteed to be not affected by other concurrent transactions, until
+ * transaction is committed.
+ *
+ * <p>
+ * For a detailed explanation of how transaction are isolated and how transaction-local
+ * changes are committed to global data tree, see
+ * {@link AsyncReadTransaction}, {@link AsyncWriteTransaction},
+ * {@link AsyncReadWriteTransaction} and {@link AsyncWriteTransaction#commit()}.
+ *
+ *
+ * <p>
+ * It is strongly recommended to use the type of transaction, which
+ * provides only the minimal capabilities you need. This allows for
+ * optimizations at the data broker / data store level. For example,
+ * implementations may optimize the transaction for reading if they know ahead
+ * of time that you only need to read data - such as not keeping additional meta-data,
+ * which may be required for write transactions.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncDataBroker<P extends Path<P>, D, L extends AsyncDataChangeListener<P, D>> extends //
         AsyncDataTransactionFactory<P, D> {
 
@@ -17,52 +60,150 @@ public interface AsyncDataBroker<P extends Path<P>, D, L extends AsyncDataChange
      *
      * Scope of Data Change
      *
+     * <p>
      * Represents scope of data change (addition, replacement, deletion).
      *
-     * The terminology for types is reused from LDAP
+     * The terminology for scope types is reused from LDAP.
+     *
+     * <h2>Examples</h2>
+     *
+     * Following is an example model with comments describing what notifications
+     * you would receive based on the scope you specify, when you are
+     * registering for changes on container a.
      *
-     * @see http://www.idevelopment.info/data/LDAP/LDAP_Resources/SEARCH_Setting_the_SCOPE_Parameter.shtml
+     * <pre>
+     * container a              // scope BASE, ONE, SUBTREE
+     *    leaf "foo"            // scope ONE, SUBTREE
+     *    container             // scope ONE, SUBTREE
+     *       leaf  "bar"        // scope SUBTREE
+     *    list list             // scope ONE, SUBTREE
+     *      list [a]            // scope SUBTREE
+     *        id "a"            // scope SUBTREE
+     *      list [b]            // scope SUBTREE
+     *        id "b"            // scope SUBTREE
+     * </pre>
+     *
+     * Following is an example model with comments describing what notifications
+     * you would receive based on the scope you specify, when you are
+     * registering for changes on list list (without specifying concrete item in
+     * the list).
+     *
+     * <pre>
+     *  list list               // scope BASE, ONE, SUBTREE
+     *      list [a]            // scope ONE, SUBTREE
+     *        id "a"            // scope SUBTREE
+     *      list [b]            // scope ONE, SUBTREE
+     *        id "b"            // scope SUBTREE
+     * </pre>
+     *
+     *
+     * @see http://www.idevelopment.info/data/LDAP/LDAP_Resources/
+     *      SEARCH_Setting_the_SCOPE_Parameter.shtml
      */
     public enum DataChangeScope {
 
-       /**
-        * Represents only a direct change of the node, such as replacement of node,
-        * addition or deletion.
-        *
-        */
-       BASE,
-       /**
-        * Represent a change (addition,replacement,deletion)
-        * of the node or one of it's direct childs.
-        *
-        */
-       ONE,
-       /**
-        * Represents a change of the node or any of it's child nodes.
-        *
-        */
-       SUBTREE
+        /**
+         * Represents only a direct change of the node, such as replacement of a
+         * node, addition or deletion.
+         *
+         */
+        BASE,
+        /**
+         * Represent a change (addition,replacement,deletion) of the node or one
+         * of its direct children.
+         *
+         * This scope is superset of {@link #BASE}.
+         *
+         */
+        ONE,
+        /**
+         * Represents a change of the node or any of or any of its child nodes,
+         * direct and nested.
+         *
+         * This scope is superset of {@link #ONE} and {@link #BASE}.
+         *
+         */
+        SUBTREE
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public AsyncReadTransaction<P, D> newReadOnlyTransaction();
+    public AsyncReadOnlyTransaction<P, D> newReadOnlyTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public AsyncReadWriteTransaction<P,D> newReadWriteTransaction();
+    public AsyncReadWriteTransaction<P, D> newReadWriteTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public AsyncWriteTransaction<P, D> newWriteOnlyTransaction();
 
     /**
-     * Registers {@link DataChangeListener} for Data Change callbacks
-     * which will be triggered on which will be triggered on the store
+     * Registers a {@link AsyncDataChangeListener} to receive
+     * notifications when data changes under a given path in the conceptual data
+     * tree.
+     * <p>
+     * You are able to register for notifications  for any node or subtree
+     * which can be reached via the supplied path.
+     * <p>
+     * If path type <code>P</code> allows it, you may specify paths up to the leaf nodes
+     * then it is possible to listen on leaf nodes.
+     * <p>
+     * You are able to register for data change notifications for a subtree even
+     * if it does not exist. You will receive notification once that node is
+     * created.
+     * <p>
+     * If there is any preexisting data in data tree on path for which you are
+     * registering, you will receive initial data change event, which will
+     * contain all preexisting data, marked as created.
+     *
+     * <p>
+     * You are also able to specify the scope of the changes you want to be
+     * notified.
+     * <p>
+     * Supported scopes are:
+     * <ul>
+     * <li>{@link DataChangeScope#BASE} - notification events will only be
+     * triggered when a node referenced by path is created, removed or replaced.
+     * <li>{@link DataChangeScope#ONE} - notifications events will only be
+     * triggered when a node referenced by path is created, removed or replaced,
+     * or any or any of its immediate children are created, updated or removed.
+     * <li>{@link DataChangeScope#SUBTREE} - notification events will be
+     * triggered when a node referenced by the path is created, removed
+     * or replaced or any of the children in its subtree are created, removed
+     * or replaced.
+     * </ul>
+     * See {@link DataChangeScope} for examples.
+     * <p>
+     * This method returns a {@link ListenerRegistration} object. To
+     * "unregister" your listener for changes call the "close" method on this
+     * returned object.
+     * <p>
+     * You MUST call close when you no longer need to receive notifications
+     * (such as during shutdown or for example if your bundle is shutting down).
      *
-     * @param store Logical store in which listener is registered.
-     * @param path Path (subtree identifier) on which client listener will be invoked.
-     * @param listener Instance of listener which should be invoked on
-     * @param triggeringScope Scope of change which triggers callback.
-     * @return Listener registration of the listener, call {@link ListenerRegistration#close()}
-     *         to stop delivery of change events.
+     * @param store
+     *            Logical Data Store - Logical Datastore you want to listen for
+     *            changes in. For example
+     *            {@link LogicalDatastoreType#OPERATIONAL} or
+     *            {@link LogicalDatastoreType#CONFIGURATION}
+     * @param path
+     *            Path (subtree identifier) on which client listener will be
+     *            invoked.
+     * @param listener
+     *            Instance of listener which should be invoked on
+     * @param triggeringScope
+     *            Scope of change which triggers callback.
+     * @return Listener registration object, which may be used to unregister
+     *         your listener using {@link ListenerRegistration#close()} to stop
+     *         delivery of change events.
      */
-    ListenerRegistration<L> registerDataChangeListener(LogicalDatastoreType store, P path, L listener, DataChangeScope triggeringScope);
+    ListenerRegistration<L> registerDataChangeListener(LogicalDatastoreType store, P path, L listener,
+            DataChangeScope triggeringScope);
 }
index f612e51747aa4cb5e066cb00b6fd85bea74ed0a3..29c9bae31f76e2b1a1269116c2b3438cfa572172 100644 (file)
@@ -13,63 +13,128 @@ import java.util.Set;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.concepts.Path;
 
-public interface AsyncDataChangeEvent<P extends Path<P>,D> extends Immutable {
+/**
+ *
+ * An event which contains a capture of changes in a data subtree
+ *
+ * <p>
+ * Represents a notification indicating that some data at or under a particular
+ * path has changed. The notification contains a capture of the changes in the data
+ * subtree. This event is triggered by successful application of modifications
+ * from a transaction on the global data tree. Use the
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * method to register a listener for data change events.
+ *
+ * <p>
+ * A listener will only receive notifications for changes to data under the path
+ * they register for. See
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * to learn more about registration scopes.
+ *
+ * <p>
+ * The entire subtree under the path will be provided via instance methods of Data
+ * Change Event even if just a leaf node changes.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
+public interface AsyncDataChangeEvent<P extends Path<P>, D> extends Immutable {
     /**
-     * Returns a immutable map of paths and newly created objects
+     * Returns a map of paths and newly created objects, which were introduced by
+     * this change into conceptual data tree, if no new objects were introduced
+     * this map will be empty.
+     *<p>
+     * This map contains all data tree nodes (and paths to them) which were created
+     * and are in  the scope of listener registration. The data tree nodes
+     * contain their whole subtree with their current state.
      *
      * @return map of paths and newly created objects
      */
     Map<P, D> getCreatedData();
 
     /**
-     * Returns a immutable map of paths and respective updated objects after update.
-     *
-     * Original state of the object is in
-     * {@link #getOriginalData()}
+     * Returns a map of paths and objects which were updated by this change in the
+     * conceptual data tree if no existing objects were updated
+     * this map will be empty.
+     *<p>
+     * This map contains all data tree nodes (and paths to them) which were updated
+     * and are in the scope of listener registration. The data tree nodes
+     * contain their whole subtree with their current state.
+     *<p>
+     * A Node is considered updated if it contents were replaced or one of its
+     * children was created, removed or updated.
+     *<p>
+     * Original state of the updated data tree nodes is in
+     * {@link #getOriginalData()} stored with same path.
      *
      * @return map of paths and newly created objects
      */
     Map<P, D> getUpdatedData();
 
     /**
-     * Returns a immutable set of removed paths.
-     *
-     * Original state of the object is in
-     * {@link #getOriginalData()}
+     * Returns an immutable set of removed paths.
+     *<p>
+     * This set contains the paths to the data tree nodes which are in the scope
+     * of the listener registration that have been removed.
+     *<p>
+     * Original state of the removed data tree nodes is in
+     * {@link #getOriginalData()} stored with same path.
      *
      * @return set of removed paths
      */
     Set<P> getRemovedPaths();
 
     /**
-     * Return a immutable map of paths and original state of updated and removed objects.
+     * Returns an immutable map of updated or removed paths and their original
+     * states prior to this change.
      *
-     * This map is populated if at changed path was previous object, and captures
-     * state of previous object.
+     *<p>
+     * This map contains the original version of the data tree nodes (and paths
+     * to them), which are in the scope of the listener registration.
      *
      * @return map of paths and original state of updated and removed objects.
      */
     Map<P, ? extends D> getOriginalData();
 
     /**
-     * Returns a  immutable stable view of data state, which
-     * captures state of data store before the reported change.
+     * Returns an immutable stable view of data state, which captures the state of
+     * data store before the reported change.
      *
+     *<p>
+     * The view is rooted at the point where the listener, to which the event is
+     * being delivered, was registered.
+     *<p>
+     * If listener used a wildcarded path (if supported by path type) during
+     * registration for change listeners this method returns null, and original
+     * state can be accessed only via {@link #getOriginalData()}
      *
-     * The view is rooted at the point where the listener, to which the event is being delivered, was registered.
-     *
-     * @return Stable view of data before the change happened, rooted at the listener registration path.
+     * @return Stable view of data before the change happened, rooted at the
+     *         listener registration path.
      *
      */
     D getOriginalSubtree();
 
     /**
-     * Returns a immutable stable view of data, which captures state of data store
-     * after the reported change.
-     *
-     * The view is rooted at the point where the listener, to which the event is being delivered, was registered.
+     * Returns an immutable stable view of data, which captures the state of data
+     * store after the reported change.
+     *<p>
+     * The view is rooted at the point where the listener, to which the event is
+     * being delivered, was registered.
+     *<p>
+     * If listener used a wildcarded path (if supported by path type) during
+     * registration for change listeners this method returns null, and state
+     * can be accessed only via {@link #getCreatedData()},
+     * {@link #getUpdatedData()}, {@link #getRemovedPaths()}
      *
-     * @return Stable view of data after the change happened, rooted at the listener registration path.
+     * @return Stable view of data after the change happened, rooted at the
+     *         listener registration path.
      */
     D getUpdatedSubtree();
 }
index 49f07bc52b4f8aecefab507121d8d91984f1f8d3..dca5200d392687e25493876f945e347d3e394bf4 100644 (file)
@@ -11,13 +11,42 @@ import java.util.EventListener;
 
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ * Listener of data change events on particular subtree.
+ *
+ * <p>
+ * User-supplied implementations of this listener interface MUST register via
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * in order to start receiving data change events, which capture state changes
+ * in a subtree.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is intended to be implemented
+ * by users of MD-SAL.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncDataChangeListener<P extends Path<P>, D> extends EventListener {
     /**
-     * Note that this method may be invoked from a shared thread pool, so
+     *
+     * Invoked when there is data change for the particular path, which was used to
+     * register this listener.
+     * <p>
+     * This method may be also invoked during registration of the listener if
+     * there is any preexisting data in the conceptual data tree for supplied path.
+     * This initial event will contain all preexisting data as created.
+     *
+     * <p>
+     * <b>Note</b> that this method may be invoked from a shared thread pool, so
      * implementations SHOULD NOT perform CPU-intensive operations and they
      * definitely MUST NOT invoke any potentially blocking operations.
      *
-     * @param change Data Change Event being delivered.
+     * @param change
+     *            Data Change Event being delivered.
      */
     void onDataChanged(AsyncDataChangeEvent<P, D> change);
 }
index 732fed0f3f482466ee3a4acb682b73f6826ea8ea..a558b96b2d56fa26658741d8ee11ac63f3e735a3 100644 (file)
@@ -9,12 +9,110 @@ package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ * A factory which allocates new transactions to operate on the data
+ * tree.
+ *
+ * <p>
+ * <b>Note:</b> This interface is not intended to be used directly, but rather
+ * via subinterfaces which introduces additional semantics to allocated
+ * transactions.
+ * <ul>
+ * <li> {@link AsyncDataBroker}
+ * <li> {@link TransactionChain}
+ * </ul>
+ *
+ * <p>
+ * All operations on the data tree are performed via one of the transactions:
+ * <ul>
+ * <li>Read-Only - allocated using {@link #newReadOnlyTransaction()}
+ * <li>Write-Only - allocated using {@link #newWriteOnlyTransaction()}
+ * <li>Read-Write - allocated using {@link #newReadWriteTransaction()}
+ * </ul>
+ *
+ * <p>
+ * These transactions provides a stable isolated view of the data tree, which is
+ * guaranteed to be not affected by other concurrent transactions, until
+ * transaction is committed.
+ *
+ * <p>
+ * For a detailed explanation of how transaction are isolated and how transaction-local
+ * changes are committed to global data tree, see
+ * {@link AsyncReadTransaction}, {@link AsyncWriteTransaction},
+ * {@link AsyncReadWriteTransaction} and {@link AsyncWriteTransaction#commit()}.
+ *
+ * <p>
+ * It is strongly recommended to use the type of transaction, which
+ * provides only the minimal capabilities you need. This allows for
+ * optimizations at the data broker / data store level. For example,
+ * implementations may optimize the transaction for reading if they know ahead
+ * of time that you only need to read data - such as not keeping additional meta-data,
+ * which may be required for write transactions.
+ *<p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @see AsyncDataBroker
+ * @see TransactionChain
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncDataTransactionFactory<P extends Path<P>, D> {
 
-    AsyncReadTransaction<P, D> newReadOnlyTransaction();
+    /**
+     * Allocates a new read-only transaction which provides an immutable snapshot of
+     * the data tree.
+     *<p>
+     * The view of data tree is an immutable snapshot of current data tree state when
+     * transaction was allocated.
+     *
+     * @return new read-only transaction
+     */
+    AsyncReadOnlyTransaction<P, D> newReadOnlyTransaction();
 
+    /**
+     * Allocates new read-write transaction which provides a mutable view of the data
+     * tree.
+     *
+     * <p>
+     * Preconditions for mutation of data tree are captured from the snapshot of
+     * data tree state, when the transaction is allocated. If data was
+     * changed during transaction in an incompatible way then the commit of this transaction
+     * will fail. See {@link AsyncWriteTransaction#commit()} for more
+     * details about conflicting and not-conflicting changes and
+     * failure scenarios.
+     *
+     * @return new read-write transaction
+     */
     AsyncReadWriteTransaction<P, D> newReadWriteTransaction();
 
-    AsyncWriteTransaction<P,D> newWriteOnlyTransaction();
+    /**
+     * Allocates new write-only transaction based on latest state of data
+     * tree.
+     *
+     * <p>
+     * Preconditions for mutation of data tree are captured from the snapshot of
+     * data tree state, when the transaction is allocated. If data was
+     * changed during transaction in an incompatible way then the commit of this transaction
+     * will fail. See {@link AsyncWriteTransaction#commit()} for more
+     * details about conflicting and not-conflicting changes and
+     * failure scenarios.
+     *
+     * <p>
+     * Since this transaction does not provide a view of the data it SHOULD BE
+     * used only by callers which are exclusive writers (exporters of data)
+     * to the subtree they modify. This prevents optimistic
+     * lock failures as described in {@link AsyncWriteTransaction#commit()}.
+     * <p>
+     * Exclusivity of writers to particular subtree SHOULD BE enforced by
+     * external locking mechanism.
+     *
+     * @return new write-only transaction
+     */
+    AsyncWriteTransaction<P, D> newWriteOnlyTransaction();
 
 }
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadOnlyTransaction.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadOnlyTransaction.java
new file mode 100644 (file)
index 0000000..4beb5c6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.common.api.data;
+
+import org.opendaylight.yangtools.concepts.Path;
+
+/**
+ * Read-only transaction, which provides stable view of data
+ * and is {@link AutoCloseable} resource.
+ *
+ * @see AsyncReadTransaction
+ *
+* @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
+public interface AsyncReadOnlyTransaction<P extends Path<P>, D> extends AsyncReadTransaction<P, D>, AutoCloseable {
+
+    /**
+     * Closes this transaction and releases all resources associated with it.
+     *
+     */
+    @Override
+    public void close();
+}
index 7744f71888fe0ac6017bea1513962e00915da57e..e1cd4a712a0d9804ac1846a8e8bf4ad6f23dc8ca 100644 (file)
@@ -12,12 +12,61 @@ import org.opendaylight.yangtools.concepts.Path;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 
+/**
+ *
+ * Provides a stateful read view of the data tree.
+ *
+ * <p>
+ * View of the data tree is a stable point-in-time snapshot of the current data tree state when
+ * the transaction was created. It's state and underlying data tree
+ * is not affected by other concurrently running transactions.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * <h2>Transaction isolation example</h2>
+ * Lets assume initial state of data tree for <code>PATH</code> is <code>A</code>.
+ *
+ * <pre>
+ * txRead = broker.newReadOnlyTransaction();   // read Transaction is snapshot of data
+ * txWrite = broker.newReadWriteTransactoin(); // concurrent write transaction
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // will return Optional containing A
+ * txWrite = broker.put(OPERATIONAL,PATH,B);   // writes B to PATH
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // still returns Optional containing A
+ *
+ * txWrite.commit().get();                     // data tree is updated, PATH contains B
+ * txRead.read(OPERATIONAL,PATH).get();        // still returns Optional containing A
+ *
+ * txAfterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * txAfterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B;
+ * </pre>
+ *
+ * <p>
+ * <b>Note:</b> example contains blocking calls on future only to illustrate
+ * that action happened after other asynchronous action. Use of blocking call
+ * {@link ListenableFuture#get()} is discouraged for most uses and you should
+ * use
+ * {@link com.google.common.util.concurrent.Futures#addCallback(ListenableFuture, com.google.common.util.concurrent.FutureCallback)}
+ * or other functions from {@link com.google.common.util.concurrent.Futures} to
+ * register more specific listeners.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncReadTransaction<P extends Path<P>, D> extends AsyncTransaction<P, D> {
 
     /**
      *
-     * Reads data from provided logical data store located at provided path
-     *
+     * Reads data from provided logical data store located at the provided path.
+     *<p>
+     * If the target is a subtree, then the whole subtree is read (and will be
+     * accessible from the returned data object).
      *
      * @param store
      *            Logical data store from which read should occur.
@@ -26,10 +75,11 @@ public interface AsyncReadTransaction<P extends Path<P>, D> extends AsyncTransac
      *            read
      * @return Listenable Future which contains read result
      *         <ul>
-     *         <li>If data at supplied path exists the {@link Future#get()}
-     *         returns Optional object containing data
+     *         <li>If data at supplied path exists the
+     *         {@link ListeblaFuture#get()} returns Optional object containing
+     *         data once read is done.
      *         <li>If data at supplied path does not exists the
-     *         {@link Future#get()} returns {@link Optional#absent()}.
+     *         {@link ListenbleFuture#get()} returns {@link Optional#absent()}.
      *         </ul>
      */
     ListenableFuture<Optional<D>> read(LogicalDatastoreType store, P path);
index ce740bf41d9d798bb69bf42c573f4a6a98ecbaa9..16b4ed4fe2ed14d7cf7db8e5e88621df801d9f1c 100644 (file)
@@ -10,12 +10,128 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.Path;
 
 /**
- * Transaction enabling client to have combined transaction,
- * which provides read and write capabilities.
+ * Transaction enabling a client to have a combined read/write capabilities.
  *
+ * <p>
+ * The initial state of the write transaction is stable snapshot of current data tree
+ * state captured when transaction was created and it's state and underlying
+ * data tree are not affected by other concurrently running transactions.
  *
- * @param <P> Path Type
- * @param <D> Data Type
+ * <p>
+ * Write transactions are isolated from other concurrent write transactions. All
+ * writes are local to the transaction and represents only a proposal of state
+ * change for data tree and it is not visible to any other concurrently running
+ * transactions.
+ *
+ * <p>
+ * Applications publish the changes proposed in the transaction by calling {@link #commit}
+ * on the transaction. This seals the transaction
+ * (preventing any further writes using this transaction) and submits it to be
+ * processed and applied to global conceptual data tree.
+ *
+ * <p>
+ * The transaction commit may fail due to a concurrent transaction modifying and committing data in
+ * an incompatible way. See {@link #commit()} for more concrete commit failure examples.
+ *
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * <h2>Examples</h2>
+ *
+ * <h3>Transaction local state</h3>
+ *
+ * Let assume initial state of data tree for <code>PATH</code> is <code>A</code>
+ * .
+ *
+ * <pre>
+ * txWrite = broker.newReadWriteTransaction(); // concurrent write transaction
+ *
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional containing A
+ * txWrite.put(OPERATIONAL,PATH,B);            // writes B to PATH
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional Containing B
+ *
+ * txWrite.commit().get();                     // data tree is updated, PATH contains B
+ *
+ * tx1afterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * tx1afterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B
+ * </pre>
+ *
+ * As you could see read-write transaction provides capabilities as
+ * {@link AsyncWriteTransaction} but also allows for reading proposed changes as
+ * if they already happened.
+ *
+ * <h3>Transaction isolation (read transaction, read-write transaction)</h3> Let
+ * assume initial state of data tree for <code>PATH</code> is <code>A</code>.
+ *
+ * <pre>
+ * txRead = broker.newReadOnlyTransaction();   // read Transaction is snapshot of data
+ * txWrite = broker.newReadWriteTransaction(); // concurrent write transaction
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // will return Optional containing A
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional containing A
+ *
+ * txWrite.put(OPERATIONAL,PATH,B);            // writes B to PATH
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional Containing B
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // concurrent read transaction still returns
+ *                                             // Optional containing A
+ *
+ * txWrite.commit().get();                     // data tree is updated, PATH contains B
+ * txRead.read(OPERATIONAL,PATH).get();        // still returns Optional containing A
+ *
+ * tx1afterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * tx1afterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B
+ * </pre>
+ *
+ * <h3>Transaction isolation (2 concurrent read-write transactions)</h3> Let
+ * assume initial state of data tree for <code>PATH</code> is <code>A</code>.
+ *
+ * <pre>
+ * tx1 = broker.newReadWriteTransaction(); // read Transaction is snapshot of data
+ * tx2 = broker.newReadWriteTransaction(); // concurrent write transaction
+ *
+ * tx1.read(OPERATIONAL,PATH).get();       // will return Optional containing A
+ * tx2.read(OPERATIONAL,PATH).get()        // will return Optional containing A
+ *
+ * tx2.put(OPERATIONAL,PATH,B);            // writes B to PATH
+ * tx2.read(OPERATIONAL,PATH).get()        // will return Optional Containing B
+ *
+ * tx1.read(OPERATIONAL,PATH).get();       // tx1 read-write transaction still sees Optional
+ *                                         // containing A since is isolated from tx2
+ * tx1.put(OPERATIONAL,PATH,C);            // writes C to PATH
+ * tx1.read(OPERATIONAL,PATH).get()        // will return Optional Containing C
+ *
+ * tx2.read(OPERATIONAL,PATH).get()        // tx2 read-write transaction still sees Optional
+ *                                         // containing B since is isolated from tx1
+ *
+ * tx2.commit().get();                     // data tree is updated, PATH contains B
+ * tx1.read(OPERATIONAL,PATH).get();       // still returns Optional containing C since is isolated from tx2
+ *
+ * tx1afterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * tx1afterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B
+ *
+ * tx1.commit()                            // Will fail with OptimisticLockFailedException
+ *                                         // which means concurrent transaction changed the same PATH
+ *
+ * </pre>
+ *
+ * <p>
+ * <b>Note:</b> examples contains blocking calls on future only to illustrate
+ * that action happened after other asynchronous action. Use of blocking call
+ * {@link com.google.common.util.concurrent.ListenableFuture#get()} is discouraged for most uses and you should
+ * use
+ * {@link com.google.common.util.concurrent.Futures#addCallback(com.google.common.util.concurrent.ListenableFuture, com.google.common.util.concurrent.FutureCallback)}
+ * or other functions from {@link com.google.common.util.concurrent.Futures} to
+ * register more specific listeners.
+ *
+ * @see AsyncReadTransaction
+ * @see AsyncWriteTransaction
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
  */
 public interface AsyncReadWriteTransaction<P extends Path<P>, D> extends AsyncReadTransaction<P, D>,
         AsyncWriteTransaction<P, D> {
index 23ca275ef20ef24a710b39d5f06ff96fa9ca00ce..08ddfe689819702e5805bb8a78f5dbee6eb2f4ee 100644 (file)
@@ -13,21 +13,26 @@ import org.opendaylight.yangtools.concepts.Path;
 
 /**
  *
- * @author
+ * A common parent for all transactions which operate on a conceptual data tree.
+ *
+ * See derived transaction types for more concrete behavior:
+ * <ul>
+ * <li>{@link AsyncReadTransaction} - Read capabilities, user is able to read data from data tree</li>
+ * <li>{@link AsyncWriteTransaction} - Write capabilities, user is able to propose changes to data tree</li>
+ * <li>{@link AsyncReadWriteTransaction} - Read and Write capabilities, user is able to read state and to propose changes of state.</li>
+ * </ul>
+ *
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL.
  *
  * @param <P> Type of path (subtree identifier), which represents location in tree
  * @param <D> Type of data (payload), which represents data payload
  */
 public interface AsyncTransaction<P extends Path<P>,D> extends //
-    Identifiable<Object>,
-    AutoCloseable {
+    Identifiable<Object> {
 
     @Override
     public Object getIdentifier();
 
-    /**
-     * Closes transaction and releases all resources associated with it.
-     */
-    @Override
-    public void close();
+
 }
index 82c48d2ddb27e657c12cb9c8f56f49997923b370..f7eae27320107ef6a90696ff73f2cf40b3c99fde 100644 (file)
@@ -13,56 +13,124 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
-public interface AsyncWriteTransaction<P extends Path<P>, D>  extends AsyncTransaction<P, D> {
+/**
+ * Write transaction provides mutation capabilities for a data tree.
+ *
+ * <p>
+ * Initial state of write transaction is a stable snapshot of the current data tree.
+ * The state is captured when the transaction is created and its state and underlying
+ * data tree are not affected by other concurrently running transactions.
+ * <p>
+ * Write transactions are isolated from other concurrent write transactions. All
+ * writes are local to the transaction and represent only a proposal of state
+ * change for the data tree and it is not visible to any other concurrently running
+ * transaction.
+ * <p>
+ * Applications publish the changes proposed in the transaction by calling {@link #commit}
+ * on the transaction. This seals the transaction
+ * (preventing any further writes using this transaction) and submits it to be
+ * processed and applied to global conceptual data tree.
+ * <p>
+ * The transaction commit may fail due to a concurrent transaction modifying and committing data in
+ * an incompatible way. See {@link #commit()} for more concrete commit failure examples.
+ *
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
+public interface AsyncWriteTransaction<P extends Path<P>, D> extends AsyncTransaction<P, D> {
     /**
-     * Cancels transaction.
+     * Cancels the transaction.
+     *
+     * Transactions can only be cancelled if it's status is
+     * {@link TransactionStatus#NEW} or {@link TransactionStatus#SUBMITED}
      *
-     * Transaction could be only cancelled if it's status
-     * is {@link TransactionStatus#NEW} or {@link TransactionStatus#SUBMITED}
+     * Invoking cancel() on {@link TransactionStatus#FAILED} or
+     * {@link TransactionStatus#CANCELED} will have no effect, and transaction
+     * is considered cancelled.
      *
-     * Invoking cancel() on {@link TransactionStatus#FAILED} or {@link TransactionStatus#CANCELED}
-     * will have no effect.
+     * Invoking cancel() on finished transaction  (future returned by {@link #commit()}
+     * already completed with {@link TransactionStatus#COMMITED}) will always
+     * fail (return false).
      *
-     * @throws IllegalStateException If transaction status is {@link TransactionStatus#COMMITED}
+     * @return <tt>false</tt> if the task could not be cancelled,
+     * typically because it has already completed normally;
+     * <tt>true</tt> otherwise
      *
      */
-    public void cancel();
+    public boolean cancel();
 
     /**
-     * Store a piece of data at specified path. This acts as a add / replace operation,
-     * which is to say that whole subtree will be replaced by specified path.
+     * Store a piece of data at specified path. This acts as an add / replace
+     * operation, which is to say that whole subtree will be replaced by
+     * specified path. Performing the following put operations:
+     *
+     * <pre>
+     * 1) container { list [ a ] }
+     * 2) container { list [ b ] }
+     * </pre>
+     *
+     * will result in the following data being present:
+     *
+     * <pre>
+     * container { list [ b ] }
+     * </pre>
      *
-     * If you need add or merge of current object with specified use {@link #merge(LogicalDatastoreType, Path, Object)}
      *
-     * @param store Logical data store which should be modified
-     * @param path Data object path
-     * @param data Data object to be written to specified path
-     * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW}
+     * If you need to make sure that a parent object exists, but you do not want modify
+     * its preexisting state by using put, consider using
+     * {@link #merge(LogicalDatastoreType, Path, Object)}
+     *
+     * @param store
+     *            Logical data store which should be modified
+     * @param path
+     *            Data object path
+     * @param data
+     *            Data object to be written to specified path
+     * @throws IllegalStateException
+     *             if the transaction is no longer {@link TransactionStatus#NEW}
      */
     public void put(LogicalDatastoreType store, P path, D data);
 
     /**
-     * Store a piece of data at specified path. This acts as a merge operation,
+     * Store a piece of data at the specified path. This acts as a merge operation,
      * which is to say that any pre-existing data which is not explicitly
      * overwritten will be preserved. This means that if you store a container,
-     * its child lists will be merged. Performing the following put operations:
+     * its child lists will be merged. Performing the following merge
+     * operations:
      *
+     * <pre>
      * 1) container { list [ a ] }
      * 2) container { list [ b ] }
+     * </pre>
      *
      * will result in the following data being present:
      *
+     * <pre>
      * container { list [ a, b ] }
+     * </pre>
      *
-     * This also means that storing the container will preserve any augmentations
-     * which have been attached to it.
-     *
-     * If you require an explicit replace operation, use {@link #put(LogicalDatastoreType, Path, Object)} instead.
+     * This also means that storing the container will preserve any
+     * augmentations which have been attached to it.
+     *<p>
+     * If you require an explicit replace operation, use
+     * {@link #put(LogicalDatastoreType, Path, Object)} instead.
      *
-     * @param store Logical data store which should be modified
-     * @param path Data object path
-     * @param data Data object to be written to specified path
-     * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW}
+     * @param store
+     *            Logical data store which should be modified
+     * @param path
+     *            Data object path
+     * @param data
+     *            Data object to be written to specified path
+     * @throws IllegalStateException
+     *             if the transaction is no longer {@link TransactionStatus#NEW}
      */
     public void merge(LogicalDatastoreType store, P path, D data);
 
@@ -70,51 +138,168 @@ public interface AsyncWriteTransaction<P extends Path<P>, D>  extends AsyncTrans
      * Remove a piece of data from specified path. This operation does not fail
      * if the specified path does not exist.
      *
-     * @param store Logical data store which should be modified
-     * @param path Data object path
-     * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW}
+     * @param store
+     *            Logical data store which should be modified
+     * @param path
+     *            Data object path
+     * @throws IllegalStateException
+     *             if the transaction is no longer {@link TransactionStatus#NEW}
      */
     public void delete(LogicalDatastoreType store, P path);
 
     /**
+     * Submits transaction to be applied to update logical data tree.
+     * <p>
+     * This call logically seals the transaction, which prevents the client from
+     * further changing data tree using this transaction. Any subsequent calls to
+     * {@link #put(LogicalDatastoreType, Path, Object)},
+     * {@link #merge(LogicalDatastoreType, Path, Object)} or
+     * {@link #delete(LogicalDatastoreType, Path)} will fail with
+     * {@link IllegalStateException}.
      *
-     * Closes transaction and resources allocated to the transaction.
-     *
-     * This call does not change Transaction status. Client SHOULD
-     * explicitly {@link #commit()} or {@link #cancel()} transaction.
-     *
-     * @throws IllegalStateException if the transaction has not been
-     *         updated by invoking {@link #commit()} or {@link #cancel()}.
-     */
-    @Override
-    public void close();
-
-    /**
-     * Initiates a commit of modification. This call logically seals the
-     * transaction, preventing any the client from interacting with the
-     * data stores. The transaction is marked as {@link TransactionStatus#SUBMITED}
-     * and enqueued into the data store backed for processing.
+     * The transaction is marked as {@link TransactionStatus#SUBMITED} and
+     * enqueued into the data store backed for processing.
      *
      * <p>
-     * The successful commit changes the state of the system and may affect
-     * several components.
+     * Whether or not the commit is successful is determined by versioning
+     * of data tree and validation of registered commit participants
+     * {@link AsyncConfigurationCommitHandler}
+     * if transaction changes {@link LogicalDatastoreType#CONFIGURATION} data tree.
+     *<p>
+     * The effects of successful commit of data depends on
+     * other data change listeners {@link AsyncDataChangeListener} and
+     * {@link AsyncConfigurationCommitHandler}, which was registered to the
+     * same {@link AsyncDataBroker}, to which this transaction belongs.
      *
+     * <h2>Failure scenarios</h2>
      * <p>
-     * The effects of successful commit of data are described in the
-     * specifications and YANG models describing the Provider components of
-     * controller. It is assumed that Consumer has an understanding of this
-     * changes.
-     *
-     * @see DataCommitHandler for further information how two-phase commit is
-     *      processed.
-     * @param store Identifier of the store, where commit should occur.
+     * Transaction may fail because of multiple reasons, such as
+     * <ul>
+     * <li>Another transaction finished earlier and modified the same node in
+     * non-compatible way (see below). In this case the returned future will fail with
+     * {@link OptimisticLockFailedException}. It is the responsibility of the
+     * caller to create a new transaction and submit the same modification again in
+     * order to update data tree.</li>
+     * <li>Data change introduced by this transaction did not pass validation by
+     * commit handlers or data was incorrectly structured. Returned future will
+     * fail with {@link DataValidationFailedException}. User should not retry to
+     * create new transaction with same data, since it probably will fail again.
+     * </li>
+     * </ul>
+     *
+     * <h3>Change compatibility</h3>
+     *
+     * There are several sets of changes which could be considered incompatible
+     * between two transactions which are derived from same initial state.
+     * Rules for conflict detection applies recursively for each subtree
+     * level.
+     *
+     * <h4>Change compatibility of leafs, leaf-list items</h4>
+     *
+     * Following table shows  state changes and failures between two concurrent transactions,
+     * which are based on same initial state, Tx 1 completes successfully
+     * before Tx 2 is submitted.
+     *
+     * <table>
+     * <tr><th>Initial state</th><th>Tx 1</th><th>Tx 2</th><th>Result</th></tr>
+     * <tr><td>Empty</td><td>put(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, state is A=1</td></tr>
+     * <tr><td>Empty</td><td>put(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     *
+     * <tr><td>Empty</td><td>merge(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, state is A=1</td></tr>
+     * <tr><td>Empty</td><td>merge(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     *
+     *
+     * <tr><td>A=0</td><td>put(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, A=1</td></tr>
+     * <tr><td>A=0</td><td>put(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     * <tr><td>A=0</td><td>merge(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, A=1</td></tr>
+     * <tr><td>A=0</td><td>merge(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     *
+     * <tr><td>A=0</td><td>delete(A)</td><td>put(A,2)</td><td>Tx 2 will fail, A does not exists</td></tr>
+     * <tr><td>A=0</td><td>delete(A)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     * </table>
+     *
+     * <h4>Change compatibility of subtrees</h4>
+     *
+     * Following table shows  state changes and failures between two concurrent transactions,
+     * which are based on same initial state, Tx 1 completes successfully
+     * before Tx 2 is submitted.
+     *
+     * <table>
+     * <tr><th>Initial state</th><th>Tx 1</th><th>Tx 2</th><th>Result</th></tr>
+     *
+     * <tr><td>Empty</td><td>put(TOP,[])</td><td>put(TOP,[])</td><td>Tx 2 will fail, state is TOP=[]</td></tr>
+     * <tr><td>Empty</td><td>put(TOP,[])</td><td>merge(TOP,[])</td><td>TOP=[]</td></tr>
+     *
+     * <tr><td>Empty</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>Empty</td><td>put(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>TOP=[FOO=1,BAR=1]</td></tr>
+     *
+     * <tr><td>Empty</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>Empty</td><td>merge(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>TOP=[FOO=1,BAR=1]</td></tr>
+     *
+     * <tr><td>TOP=[]</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>put(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is empty store</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[BAR=1]</td></tr>
+     *
+     * <tr><td>TOP=[]</td><td>put(TOP/FOO,1)</td><td>put(TOP/BAR,1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>put(TOP/FOO,1)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP/FOO,1)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP/FOO,1)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>put(TOP/BAR,1)</td><td>Tx 2 will fail, state is empty store</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>merge(TOP/BAR,1]</td><td>Tx 2 will fail, state is empty store</td></tr>
+     *
+     * <tr><td>TOP=[FOO=1]</td><td>put(TOP/FOO,2)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>put(TOP/FOO,2)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>merge(TOP/FOO,2)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>merge(TOP/FOO,2)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>delete(TOP/FOO)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>delete(TOP/FOO)</td><td>merge(TOP/BAR,1]</td><td>state is TOP=[BAR=1]</td></tr>
+     * </table>
+     *
+     *
+     * <h3>Examples of failure scenarios</h3>
+     *
+     * <h4>Conflict of two transactions</h4>
+     *
+     * This example illustrates two concurrent transactions, which derived from
+     * same initial state of data tree and proposes conflicting modifications.
+     *
+     * <pre>
+     * txA = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
+     * txB = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
+     *
+     * txA.put(CONFIGURATION, PATH, A);    // writes to PATH value A
+     * txB.put(CONFIGURATION, PATH, B)     // writes to PATH value B
+     *
+     * ListenableFuture futureA = txA.commit(); // transaction A is sealed and committed
+     * ListenebleFuture futureB = txB.commit(); // transaction B is sealed and committed
+     * </pre>
+     *
+     * Commit of transaction A will be processed asynchronously and data tree
+     * will be updated to contain value <code>A</code> for <code>PATH</code>.
+     * Returned {@link ListenableFuture} will successfully complete once
+     * state is applied to data tree.
+     *
+     * Commit of Transaction B will fail, because previous transaction also
+     * modified path in a concurrent way. The state introduced by transaction B
+     * will not be applied. Returned {@link ListenableFuture} object will fail
+     * with {@link OptimisticLockFailedException} exception, which indicates to
+     * client that concurrent transaction prevented the submitted transaction from being
+     * applied.
+     *
      * @return Result of the Commit, containing success information or list of
      *         encountered errors, if commit was not successful. The Future
      *         blocks until {@link TransactionStatus#COMMITED} is reached.
-     *         Future will fail with {@link TransactionCommitFailedException}
-     *         if Commit of this transaction failed.
+     *         Future will fail with {@link TransactionCommitFailedException} if
+     *         Commit of this transaction failed. TODO: Usability: Consider
+     *         change from ListenableFuture to
+     *         {@link com.google.common.util.concurrent.CheckedFuture} which
+     *         will throw {@link TransactionCommitFailedException}.
      *
-     * @throws IllegalStateException if the transaction is not {@link TransactionStatus#NEW}
+     * @throws IllegalStateException
+     *             if the transaction is not {@link TransactionStatus#NEW}
      */
     public ListenableFuture<RpcResult<TransactionStatus>> commit();
 
index 15d1daa1bbe882393f863e892728490c212f5e71..5e5ea0c1388da6b4ca85718a53fcef43feb8fb31 100644 (file)
@@ -10,6 +10,15 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ *
+ *
+ *
+ * @param <P>
+ * @param <D>
+ * @deprecated Replaced by {@link AsyncDataChangeEvent}
+ */
+@Deprecated
 public interface DataChangeEvent<P extends Path<P>,D> extends DataChange<P, D>, Immutable {
 
     /**
index 669baa8d9e96a6601bfe7cbe49cb99d2ffb00233..21006173f205603d481211db5a733475e50a7ee5 100644 (file)
@@ -10,7 +10,12 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import java.util.EventListener;
 
 import org.opendaylight.yangtools.concepts.Path;
-
+/**
+ *
+ *
+ * @deprecated Replaced by {@link AsyncDataChangeEvent}
+ */
+@Deprecated
 public interface DataChangeListener<P extends Path<P>, D> extends EventListener {
     /**
      * Note that this method may be invoked from a shared thread pool, so
index 0c4c6d179ff84faf955fb6989d8ca900cbb8722e..222dba8eafc8e1be5bec4aab39ede6ca9187685d 100644 (file)
@@ -10,6 +10,11 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ *
+ * @deprecated Replaced by {@link AsyncDataBroker}
+ */
+@Deprecated
 public interface DataChangePublisher<P extends Path<P>, D, L extends DataChangeListener<P,D>> {
 
     ListenerRegistration<L> registerDataChangeListener(P path, L listener);
index 22e95197bb4c2fb9c3886492cf7635cacf18c7d2..a9f02a8ee5ed13cac55a436311f1b556225703c0 100644 (file)
@@ -79,7 +79,9 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  *
  * @param <P> Class representing a path
  * @param <D> Superclass from which all data objects are derived from.
+ * @deprecated Replaced by {@link AsyncConfigurationCommitHandler}
  */
+@Deprecated
 public interface DataCommitHandler<P extends Path<P>, D> {
 
 
index 86f1f9b13875ba4015e6bb5dbb111f693ba07b57..224751c37dbd8dabebe44da114b8d1055253877e 100644 (file)
@@ -10,6 +10,16 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.concepts.Registration;
 
+/**
+ *
+ *
+ * @deprecated THis was intended as Registration object, normal use of {@link org.opendaylight.yangtools.concepts.ObjectRegistration}
+ * is suffiecient, since {@link #getPath()} was implementation leak.
+ *
+ * @param <P>
+ * @param <D>
+ */
+@Deprecated
 public interface DataCommitHandlerRegistration<P extends Path<P>,D> extends Registration<DataCommitHandler<P, D>>{
 
     P getPath();
index 22c5fa0c1d25eb4a71e19b2b271a5a777dada2e3..630078dcedea1da1a45a279d3f2ed3e313858a69 100644 (file)
@@ -12,7 +12,11 @@ import java.util.concurrent.Future;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-
+/**
+ *
+ * @deprecated Replaced by {@link AsyncWriteTransaction}
+ */
+@Deprecated
 public interface DataModification<P extends Path<P>, D> extends DataChange<P, D>, DataReader<P, D> {
     /**
      * Returns transaction identifier
index 34f6fe970dd2e0105e6a21d32ca7049815ea87e7..6a370b8cd168be3f196b779523e3a8cd8bb03ef9 100644 (file)
@@ -8,7 +8,11 @@
 package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.yangtools.concepts.Path;
-
+/**
+ *
+ * @deprecated Replaced by {@link AsyncDataTransactionFactory}
+ */
+@Deprecated
 public interface DataModificationTransactionFactory<P extends Path<P> ,D> {
 
     DataModification<P, D> beginTransaction();
index dae9a1144b966a2e3c5e61884c1281e09a6229f3..fdeda2800bbd447ac028a028172347e5a30ce043 100644 (file)
@@ -9,6 +9,12 @@ package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ *
+ *
+ * @deprecated Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore contract.
+ */
+@Deprecated
 public interface DataProvider<P extends Path<P>, D> extends DataReader<P, D> {
 
 }
index da7efebdfeb1f7f02eda505d48a1f83be6a79b89..bd80a5389316f754a202af7c363c2332f7951859 100644 (file)
@@ -12,7 +12,12 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.concepts.Registration;
 
-
+/**
+ *
+ *
+ * @deprecated replaced by {@link AsyncDataBroker} and {@link AsyncConfigurationCommitCoordinator}
+ */
+@Deprecated
 public interface DataProvisionService<P extends Path<P> , D> {
 
     public Registration<DataCommitHandler<P, D>> registerCommitHandler(P path, DataCommitHandler<P, D> commitHandler);
index 14731d688c964adaf264d8909a4c3e90ccc4484e..2f657b8e5049dc196fbb5a04d3ddcc5f0a5a244a 100644 (file)
@@ -17,7 +17,9 @@ import org.opendaylight.yangtools.concepts.Path;
  *
  * @param <P> Path Type
  * @param <D> Data Type
+ * @deprecated Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore contract.
  */
+@Deprecated
 public interface DataReader<P extends Path<P> ,D> {
 
     /**
index 3520ba1819b42fb0ce37ae3548631cd80753334b..5688dd0988968b52a2957cd9998b0f98c8995e4a 100644 (file)
@@ -9,6 +9,11 @@ package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ *
+ * @deprecated Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore Contract.
+ */
+@Deprecated
 public interface DataStore<P extends Path<P>, D> extends //
         DataReader<P, D>, //
         DataModificationTransactionFactory<P, D> {
index e7e0eb0ff87e424973de4b9c9d6fdf9111ccae4c..940559ef895bf9cec406eee2fbe73a7617da581a 100644 (file)
@@ -27,7 +27,7 @@ public interface TransactionChain<P extends Path<P>, D> extends AutoCloseable, A
      * @throws TransactionChainClosedException if the chain has been closed.
      */
     @Override
-    public AsyncReadTransaction<P, D> newReadOnlyTransaction();
+    public AsyncReadOnlyTransaction<P, D> newReadOnlyTransaction();
 
 
     /**
index 5f84ec579d7dd25bdc9580f785aca6d300c35a0a..0c04b936b668847d6914cefe522190751f10f733 100644 (file)
@@ -9,9 +9,36 @@ package org.opendaylight.controller.md.sal.common.api.routing;
 
 import java.util.Map;
 import java.util.Set;
-
+/**
+ * Event representing change in RPC routing table.
+ *
+ *
+ * @param <C> Type, which is used to represent Routing context.
+ * @param <P> Type of data tree path, which is used to identify route.
+ */
 public interface RouteChange<C,P> {
 
+    /**
+     *
+     * Returns a map of removed routes in associated routing contexts.
+     * <p>
+     * This map represents routes, which were withdrawn from broker local
+     * routing table and broker may need to forward RPC to other broker
+     * in order to process RPC request.
+     *
+     * @return Map of contexts and removed routes
+     */
     Map<C,Set<P>> getRemovals();
+    /**
+    *
+    * Returns a map of announced routes in associated routing contexts.
+    *
+    * This map represents routes, which were announced by broker
+    * and are present in broker's local routing table. This routes
+    * are processed by implementations which are registered
+    * to originating broker.
+    *
+    * @return Map of contexts and announced routes
+    */
     Map<C,Set<P>> getAnnouncements();
 }
index 62206013f816fea5a85885e1f5696d6b93603a4f..b3b6fe6ee93ba44a30abaf32028044c7c89d006f 100644 (file)
@@ -8,8 +8,23 @@
 package org.opendaylight.controller.md.sal.common.api.routing;
 
 import java.util.EventListener;
-
+/**
+ *
+ * Listener which is interested in receiving RouteChangeEvents
+ * for its local broker.
+ * <p>
+ * Listener is registerd via {@link RouteChangePublisher#registerRouteChangeListener(RouteChangeListener)}
+ *
+ *
+ * @param <C> Type, which is used to represent Routing context.
+ * @param <P> Type of data tree path, which is used to identify route.
+ */
 public interface RouteChangeListener<C,P> extends EventListener {
 
+    /**
+     * Callback which is invoked if there is an rpc routing table change.
+     *
+     * @param change Event representing change in local RPC routing table.
+     */
     void onRouteChange(RouteChange<C, P> change);
 }
index 7bf61fab0b726cd9ebc4f3fdcac428c447f74b26..dc6b6dd3b7d89c3d23a3ed6bf7e2157bd49bbc4c 100644 (file)
@@ -9,6 +9,12 @@ package org.opendaylight.controller.md.sal.common.api.routing;
 
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 
+/**
+ * Publishes changes in local RPC routing table to registered listener.
+ *
+ * @param <C> Type, which is used to represent Routing context.
+ * @param <P> Type of data tree path, which is used to identify route.
+ */
 public interface RouteChangePublisher<C,P> {
 
     <L extends RouteChangeListener<C,P>> ListenerRegistration<L> registerRouteChangeListener(L listener);
index 6ce7b5a5c7f990360ff1d5cb3d01e63989fc42da..6fe8d6921730fc55e4fe3900ea66823ee2b644ed 100644 (file)
@@ -10,9 +10,31 @@ package org.opendaylight.controller.md.sal.common.api.routing;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.concepts.Registration;
 
+/**
+ * Base interface for a routed RPC RPC implementation registration.
+ *
+ * @param <C> the context type used for routing
+ * @param <P> the path identifier type
+ * @param <S> the RPC implementation type
+ */
 public interface RoutedRegistration<C, P extends Path<P>, S> extends Registration<S> {
 
+    /**
+     * Registers the RPC implementation associated with this registration for the given path
+     * identifier and context.
+     *
+     * @param context the context used for routing RPCs to this implementation.
+     * @param path the path identifier for which to register.
+     */
     void registerPath(C context, P path);
+
+    /**
+     * Unregisters the RPC implementation associated with this registration for the given path
+     * identifier and context.
+     *
+     * @param context the context used for routing RPCs to this implementation.
+     * @param path the path identifier for which to unregister.
+     */
     void unregisterPath(C context, P path);
 
     @Override
index 6b387b5a61cd206559e2cb11e43e53e3fe0d9ff5..82bd716c59c69c67a054e3a54cd554a85d9a3eac 100644 (file)
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-parser-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
index a7c6b0c66fe4e688a9d868a89b7c761e64c962fc..2b9694bed71d87dfb8d48e04024b94f619e5c049 100644 (file)
@@ -10,6 +10,11 @@ package org.opendaylight.controller.md.sal.common.impl.util.compat;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -28,12 +33,15 @@ 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.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
@@ -45,11 +53,6 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
 public abstract class DataNormalizationOperation<T extends PathArgument> implements Identifiable<T> {
 
     private final T identifier;
@@ -155,7 +158,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
     }
 
     private static abstract class CompositeNodeNormalizationOperation<T extends PathArgument> extends
-            DataNormalizationOperation<T> {
+    DataNormalizationOperation<T> {
 
         protected CompositeNodeNormalizationOperation(final T identifier) {
             super(identifier);
@@ -217,7 +220,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
     }
 
     private static abstract class DataContainerNormalizationOperation<T extends PathArgument> extends
-            CompositeNodeNormalizationOperation<T> {
+    CompositeNodeNormalizationOperation<T> {
 
         private final DataNodeContainer schema;
         private final Map<QName, DataNormalizationOperation<?>> byQName;
@@ -275,7 +278,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
     }
 
     private static final class ListItemNormalization extends
-            DataContainerNormalizationOperation<NodeIdentifierWithPredicates> {
+    DataContainerNormalizationOperation<NodeIdentifierWithPredicates> {
 
         private final List<QName> keyDefinition;
 
@@ -355,7 +358,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
     }
 
     private static abstract class MixinNormalizationOp<T extends PathArgument> extends
-            CompositeNodeNormalizationOperation<T> {
+    CompositeNodeNormalizationOperation<T> {
 
         protected MixinNormalizationOp(final T identifier) {
             super(identifier);
@@ -612,6 +615,42 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
     }
 
+    private static class AnyXmlNormalization extends DataNormalizationOperation<NodeIdentifier> {
+
+        protected AnyXmlNormalization( final NodeIdentifier identifier ) {
+            super( identifier );
+        }
+
+        @Override
+        public DataNormalizationOperation<?> getChild( final PathArgument child ) throws DataNormalizationException {
+            return null;
+        }
+
+        @Override
+        public DataNormalizationOperation<?> getChild( final QName child ) throws DataNormalizationException {
+            return null;
+        }
+
+        @Override
+        public NormalizedNode<?, ?> normalize( final Node<?> legacyData ) {
+            NormalizedNodeAttrBuilder<NodeIdentifier, Node<?>, AnyXmlNode> builder =
+                    Builders.anyXmlBuilder().withNodeIdentifier(
+                            new NodeIdentifier( legacyData.getNodeType() ) );
+            builder.withValue(legacyData);
+            return builder.build();
+        }
+
+        @Override
+        public boolean isLeaf() {
+            return false;
+        }
+
+        @Override
+        public NormalizedNode<?, ?> createDefault( final PathArgument currentArg ) {
+            return null;
+        }
+    }
+
     private static final Optional<DataSchemaNode> findChildSchemaNode(final DataNodeContainer parent,final QName child) {
         DataSchemaNode potential = parent.getDataChildByName(child);
         if (potential == null) {
@@ -657,7 +696,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         for (DataSchemaNode child : augmentation.getChildNodes()) {
             potentialChildren.add(child.getQName());
         }
-        return new AugmentationIdentifier(null, potentialChildren.build());
+        return new AugmentationIdentifier(potentialChildren.build());
     }
 
     private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) {
@@ -712,6 +751,8 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
             return new ChoiceNodeNormalization((org.opendaylight.yangtools.yang.model.api.ChoiceNode) potential);
         } else if (potential instanceof LeafListSchemaNode) {
             return fromLeafListSchemaNode((LeafListSchemaNode) potential);
+        } else if (potential instanceof AnyXmlSchemaNode) {
+            return new AnyXmlNormalization( new NodeIdentifier(potential.getQName() ) );
         }
         return null;
     }
index f30c8ddcaabf5c8c7cff69744b9ee3e8f936ebf8..113d3dc9f762ec1f0f2f6d4c7307ae3f04e0d19b 100644 (file)
@@ -9,6 +9,12 @@ package org.opendaylight.controller.md.sal.common.impl.util.compat;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
 import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -21,6 +27,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationI
 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.api.schema.AnyXmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -31,12 +38,6 @@ import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicates;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
 public class DataNormalizer {
 
     private final DataNormalizationOperation<?> operation;
@@ -49,7 +50,7 @@ public class DataNormalizer {
         ImmutableList.Builder<PathArgument> normalizedArgs = ImmutableList.builder();
 
         DataNormalizationOperation<?> currentOp = operation;
-        Iterator<PathArgument> arguments = legacy.getPath().iterator();
+        Iterator<PathArgument> arguments = legacy.getPathArguments().iterator();
 
         try {
             while (arguments.hasNext()) {
@@ -68,7 +69,7 @@ public class DataNormalizer {
             throw new IllegalArgumentException(String.format("Failed to normalize path %s", legacy), e);
         }
 
-        return new InstanceIdentifier(normalizedArgs.build());
+        return InstanceIdentifier.create(normalizedArgs.build());
     }
 
     public Map.Entry<InstanceIdentifier, NormalizedNode<?, ?>> toNormalized(
@@ -82,7 +83,7 @@ public class DataNormalizer {
         InstanceIdentifier normalizedPath = toNormalized(legacyPath);
 
         DataNormalizationOperation<?> currentOp = operation;
-        for (PathArgument arg : normalizedPath.getPath()) {
+        for (PathArgument arg : normalizedPath.getPathArguments()) {
             try {
                 currentOp = currentOp.getChild(arg);
             } catch (DataNormalizationException e) {
@@ -104,9 +105,7 @@ public class DataNormalizer {
 
             if (potentialOp.getIdentifier() instanceof AugmentationIdentifier) {
                 currentOp = potentialOp;
-                ArrayList<PathArgument> reworkedArgs = new ArrayList<>(normalizedPath.getPath());
-                reworkedArgs.add(potentialOp.getIdentifier());
-                normalizedPath = new InstanceIdentifier(reworkedArgs);
+                normalizedPath = normalizedPath.node(potentialOp.getIdentifier());
             }
         }
 
@@ -118,15 +117,14 @@ public class DataNormalizer {
 
     public InstanceIdentifier toLegacy(final InstanceIdentifier normalized) throws DataNormalizationException {
         ImmutableList.Builder<PathArgument> legacyArgs = ImmutableList.builder();
-        PathArgument previous = null;
         DataNormalizationOperation<?> currentOp = operation;
-        for (PathArgument normalizedArg : normalized.getPath()) {
+        for (PathArgument normalizedArg : normalized.getPathArguments()) {
             currentOp = currentOp.getChild(normalizedArg);
             if(!currentOp.isMixin()) {
                 legacyArgs.add(normalizedArg);
             }
         }
-        return new InstanceIdentifier(legacyArgs.build());
+        return InstanceIdentifier.create(legacyArgs.build());
     }
 
     public CompositeNode toLegacy(final InstanceIdentifier normalizedPath, final NormalizedNode<?, ?> normalizedData) {
@@ -134,6 +132,9 @@ public class DataNormalizer {
         // DataContainerNode<?>,"Node object %s, %s should be of type DataContainerNode",normalizedPath,normalizedData);
         if (normalizedData instanceof DataContainerNode<?>) {
             return toLegacyFromDataContainer((DataContainerNode<?>) normalizedData);
+        } else if (normalizedData instanceof AnyXmlNode) {
+            Node<?> value = ((AnyXmlNode) normalizedData).getValue();
+            return value instanceof CompositeNode ? (CompositeNode)value : null;
         }
         return null;
     }
@@ -150,6 +151,8 @@ public class DataNormalizer {
 
         if (node instanceof DataContainerNode<?>) {
             return toLegacyFromDataContainer((DataContainerNode<?>) node);
+        } else if (node instanceof AnyXmlNode) {
+            return ((AnyXmlNode) node).getValue();
         }
         return toLegacySimple(node);
 
diff --git a/opendaylight/md-sal/sal-common-impl/src/test/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizerTest.java b/opendaylight/md-sal/sal-common-impl/src/test/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizerTest.java
new file mode 100644 (file)
index 0000000..dcb90a8
--- /dev/null
@@ -0,0 +1,835 @@
+/*
+ * 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.md.sal.common.impl.util.compat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.junit.Test;
+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.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.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+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.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.api.schema.UnkeyedListNode;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class DataNormalizerTest {
+
+    static class NormalizedNodeData {
+        PathArgument nodeID;
+        Class<?> nodeClass;
+        Object nodeData; // List for a container, value Object for a leaf
+
+        NormalizedNodeData(final PathArgument nodeID, final Class<?> nodeClass, final Object nodeData) {
+            this.nodeID = nodeID;
+            this.nodeClass = nodeClass;
+            this.nodeData = nodeData;
+        }
+    }
+
+    static class LegacyNodeData {
+        QName nodeKey;
+        Object nodeData; // List for a CompositeNode, value Object for a
+        // SimpeNode
+
+        LegacyNodeData(final QName nodeKey, final Object nodeData) {
+            this.nodeKey = nodeKey;
+            this.nodeData = nodeData;
+        }
+
+        @Override
+        public String toString() {
+            return nodeKey.toString();
+        }
+    }
+
+    static final QName TEST_QNAME = QName.create(
+            "urn:opendaylight:params:xml:ns:yang:controller:md:sal:normalization:test", "2014-03-13", "test");
+    static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+    static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+    static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
+    static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
+    static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
+    static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
+
+    static final InstanceIdentifier TEST_PATH = InstanceIdentifier.of(TEST_QNAME);
+    static final InstanceIdentifier OUTER_LIST_PATH = InstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME)
+            .build();
+    static final QName ONE_QNAME = QName.create(TEST_QNAME, "one");
+    static final QName TWO_QNAME = QName.create(TEST_QNAME, "two");
+    static final QName THREE_QNAME = QName.create(TEST_QNAME, "three");
+
+    static final QName ANY_XML_DATA_QNAME = QName.create(TEST_QNAME, "any-xml-data");
+    static final QName OUTER_CONTAINER_QNAME = QName.create(TEST_QNAME, "outer-container");
+    static final QName AUGMENTED_LEAF_QNAME = QName.create(TEST_QNAME, "augmented-leaf");
+    static final QName UNKEYED_LIST_QNAME = QName.create(TEST_QNAME, "unkeyed-list");
+    static final QName UNORDERED_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "unordered-leaf-list");
+    static final QName ORDERED_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "ordered-leaf-list");
+
+    static final Short OUTER_LIST_ID = (short) 10;
+
+    static final InstanceIdentifier OUTER_LIST_PATH_LEGACY = InstanceIdentifier.builder(TEST_QNAME)
+            .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID).build();
+
+    static final InstanceIdentifier LEAF_TWO_PATH_LEGACY = InstanceIdentifier.builder(OUTER_LIST_PATH_LEGACY)
+            .node(TWO_QNAME).build();
+
+    static final QName ANY_XML_LEAF_QNAME = QName.create(TEST_QNAME, "leaf");;
+    static final QName ANY_XML_INNER_QNAME = QName.create(TEST_QNAME, "inner");
+    static final QName ANY_XML_INNER_LEAF_QNAME = QName.create(TEST_QNAME, "inner-leaf");
+
+    SchemaContext createTestContext() {
+        YangParserImpl parser = new YangParserImpl();
+        Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(DataNormalizerTest.class
+                .getResourceAsStream("/normalization-test.yang")));
+        return parser.resolveSchemaContext(modules);
+    }
+
+    @Test
+    public void testToNormalizedInstanceIdentifier() {
+        SchemaContext testCtx = createTestContext();
+        DataNormalizer normalizer = new DataNormalizer(testCtx);
+
+        InstanceIdentifier normalizedPath = normalizer.toNormalized(LEAF_TWO_PATH_LEGACY);
+
+        verifyNormalizedInstanceIdentifier(normalizedPath, TEST_QNAME, OUTER_LIST_QNAME, new Object[] {
+                OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID }, OUTER_CHOICE_QNAME, TWO_QNAME);
+    }
+
+    private void verifyNormalizedInstanceIdentifier(final InstanceIdentifier actual, final Object... expPath) {
+
+        assertNotNull("Actual InstanceIdentifier is null", actual);
+        assertEquals("InstanceIdentifier path length", expPath.length, Iterables.size(actual.getPathArguments()));
+
+        for (int i = 0; i < expPath.length; i++) {
+            PathArgument actualArg = Iterables.get(actual.getPathArguments(), i);
+            if (expPath[i] instanceof Object[]) { // NodeIdentifierWithPredicates
+                Object[] exp = (Object[]) expPath[i];
+                assertEquals("Actual path arg " + (i + 1) + " class", NodeIdentifierWithPredicates.class,
+                        actualArg.getClass());
+                NodeIdentifierWithPredicates actualNode = (NodeIdentifierWithPredicates) actualArg;
+                assertEquals("Actual path arg " + (i + 1) + " node type", exp[0], actualNode.getNodeType());
+                assertEquals("Actual path arg " + (i + 1) + " key values map size", 1, actualNode.getKeyValues().size());
+                Entry<QName, Object> keyValuesEntry = actualNode.getKeyValues().entrySet().iterator().next();
+                assertEquals("Actual path arg " + (i + 1) + " key values map key", exp[1], keyValuesEntry.getKey());
+                assertEquals("Actual path arg " + (i + 1) + " key values map value", exp[2], keyValuesEntry.getValue());
+            } else if (expPath[i] instanceof Set) { // AugmentationIdentifier
+                assertEquals("Actual path arg " + (i + 1) + " class", AugmentationIdentifier.class,
+                        actualArg.getClass());
+                AugmentationIdentifier actualNode = (AugmentationIdentifier) actualArg;
+                assertEquals("Actual path arg " + (i + 1) + " PossibleChildNames", expPath[i],
+                        actualNode.getPossibleChildNames());
+            } else {
+                assertEquals("Actual path arg " + (i + 1) + " node type", expPath[i], actualArg.getNodeType());
+            }
+        }
+    }
+
+    @Test
+    public void testToLegacyInstanceIdentifier() throws DataNormalizationException {
+
+        DataNormalizer normalizer = new DataNormalizer(createTestContext());
+
+        InstanceIdentifier normalized = InstanceIdentifier.builder().node(TEST_QNAME).node(OUTER_LIST_QNAME)
+                .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID).node(OUTER_CHOICE_QNAME).node(TWO_QNAME)
+                .build();
+
+        InstanceIdentifier legacy = normalizer.toLegacy(normalized);
+
+        assertEquals("Legacy InstanceIdentifier", LEAF_TWO_PATH_LEGACY, legacy);
+    }
+
+    @Test
+    public void testToLegacyNormalizedNode() {
+
+        ChoiceNode choiceNode1 = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_CHOICE_QNAME))
+                .withChild(ImmutableNodes.leafNode(TWO_QNAME, "two"))
+                .withChild(ImmutableNodes.leafNode(THREE_QNAME, "three")).build();
+
+        MapEntryNode innerListEntryNode1 = Builders.mapEntryBuilder()
+                .withNodeIdentifier(new NodeIdentifierWithPredicates(INNER_LIST_QNAME, NAME_QNAME, "inner-name1"))
+                .withChild(ImmutableNodes.leafNode(NAME_QNAME, "inner-name1"))
+                .withChild(ImmutableNodes.leafNode(VALUE_QNAME, "inner-value1")).build();
+
+        MapEntryNode innerListEntryNode2 = Builders.mapEntryBuilder()
+                .withNodeIdentifier(new NodeIdentifierWithPredicates(INNER_LIST_QNAME, NAME_QNAME, "inner-name2"))
+                .withChild(ImmutableNodes.leafNode(NAME_QNAME, "inner-name2"))
+                .withChild(ImmutableNodes.leafNode(VALUE_QNAME, "inner-value2")).build();
+
+        OrderedMapNode innerListNode = Builders.orderedMapBuilder()
+                .withNodeIdentifier(new NodeIdentifier(INNER_LIST_QNAME)).withChild(innerListEntryNode1)
+                .withChild(innerListEntryNode2).build();
+
+        Short outerListID1 = Short.valueOf((short) 10);
+        MapEntryNode outerListEntryNode1 = Builders.mapEntryBuilder()
+                .withNodeIdentifier(new NodeIdentifierWithPredicates(OUTER_LIST_QNAME, ID_QNAME, outerListID1))
+                .withChild(ImmutableNodes.leafNode(ID_QNAME, outerListID1)).withChild(choiceNode1)
+                .withChild(innerListNode).build();
+
+        ChoiceNode choiceNode2 = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_CHOICE_QNAME))
+                .withChild(ImmutableNodes.leafNode(ONE_QNAME, "one")).build();
+
+        Short outerListID2 = Short.valueOf((short) 20);
+        MapEntryNode outerListEntryNode2 = Builders.mapEntryBuilder()
+                .withNodeIdentifier(new NodeIdentifierWithPredicates(OUTER_LIST_QNAME, ID_QNAME, outerListID2))
+                .withChild(ImmutableNodes.leafNode(ID_QNAME, outerListID2)).withChild(choiceNode2).build();
+
+        MapNode outerListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_LIST_QNAME))
+                .withChild(outerListEntryNode1).withChild(outerListEntryNode2).build();
+
+        UnkeyedListEntryNode unkeyedListEntryNode1 = Builders.unkeyedListEntryBuilder()
+                .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME))
+                .withChild(ImmutableNodes.leafNode(NAME_QNAME, "unkeyed1")).build();
+
+        UnkeyedListEntryNode unkeyedListEntryNode2 = Builders.unkeyedListEntryBuilder()
+                .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME))
+                .withChild(ImmutableNodes.leafNode(NAME_QNAME, "unkeyed2")).build();
+
+        UnkeyedListNode unkeyedListNode = Builders.unkeyedListBuilder()
+                .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME)).withChild(unkeyedListEntryNode1)
+                .withChild(unkeyedListEntryNode2).build();
+
+        ContainerNode testContainerNode = Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(outerListNode).withChild(unkeyedListNode)
+                .build();
+
+        Node<?> legacyNode = DataNormalizer.toLegacy(testContainerNode);
+
+        verifyLegacyNode(
+                legacyNode,
+                expectCompositeNode(
+                        TEST_QNAME,
+                        expectCompositeNode(
+                                OUTER_LIST_QNAME,
+                                expectSimpleNode(ID_QNAME, outerListID1),
+                                expectSimpleNode(TWO_QNAME, "two"),
+                                expectSimpleNode(THREE_QNAME, "three"),
+
+                                expectCompositeNode(INNER_LIST_QNAME, expectSimpleNode(NAME_QNAME, "inner-name1"),
+                                        expectSimpleNode(VALUE_QNAME, "inner-value1")),
+
+                                        expectCompositeNode(INNER_LIST_QNAME, expectSimpleNode(NAME_QNAME, "inner-name2"),
+                                                expectSimpleNode(VALUE_QNAME, "inner-value2"))),
+                                                expectCompositeNode(OUTER_LIST_QNAME, expectSimpleNode(ID_QNAME, outerListID2),
+                                                        expectSimpleNode(ONE_QNAME, "one")),
+                                                        expectCompositeNode(UNKEYED_LIST_QNAME, expectSimpleNode(NAME_QNAME, "unkeyed1")),
+                                                        expectCompositeNode(UNKEYED_LIST_QNAME, expectSimpleNode(NAME_QNAME, "unkeyed2"))));
+
+        // Conversion of Mixin type nodes is not supported.
+
+        assertNull("Expected null returned for Mixin type node", DataNormalizer.toLegacy(outerListNode));
+    }
+
+    /**
+     * Following data are constructed: <any-xml-data> <inner>
+     * <inner-leaf>inner-leaf-value</inner-leaf> </inner>
+     * <leaf>leaf-value</leaf> <any-xml-data>
+     */
+    @Test
+    public void testToLegacyNormalizedNodeWithAnyXml() {
+
+        Node<?> innerLeafChild = NodeFactory.createImmutableSimpleNode(ANY_XML_INNER_LEAF_QNAME, null,
+                "inner-leaf-value");
+        CompositeNode innerContainer = NodeFactory.createImmutableCompositeNode(ANY_XML_INNER_QNAME, null,
+                Collections.<Node<?>> singletonList(innerLeafChild));
+
+        Node<?> leafChild = NodeFactory.createImmutableSimpleNode(ANY_XML_LEAF_QNAME, null, "leaf-value");
+        CompositeNode anyXmlNodeValue = NodeFactory.createImmutableCompositeNode(ANY_XML_DATA_QNAME, null,
+                Arrays.asList(leafChild, innerContainer));
+
+        AnyXmlNode testAnyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
+                .withValue(anyXmlNodeValue).build();
+
+        ContainerNode testContainerNode = Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(testAnyXmlNode).build();
+
+        DataNormalizer normalizer = new DataNormalizer(createTestContext());
+        Node<?> legacyNode = normalizer.toLegacy(InstanceIdentifier.builder(TEST_QNAME).build(), testContainerNode);
+
+        verifyLegacyNode(
+                legacyNode,
+                expectCompositeNode(
+                        TEST_QNAME,
+                        expectCompositeNode(
+                                ANY_XML_DATA_QNAME,
+                                expectSimpleNode(ANY_XML_LEAF_QNAME, "leaf-value"),
+                                expectCompositeNode(ANY_XML_INNER_QNAME,
+                                        expectSimpleNode(ANY_XML_INNER_LEAF_QNAME, "inner-leaf-value")))));
+    }
+
+    @Test
+    public void testToLegacyNormalizedNodeWithLeafLists() {
+
+        CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
+        testBuilder.setQName(TEST_QNAME);
+
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafSetBuilder = Builders.leafSetBuilder()
+                .withNodeIdentifier(new NodeIdentifier(UNORDERED_LEAF_LIST_QNAME));
+        for (int i = 1; i <= 3; i++) {
+            leafSetBuilder.withChildValue("unordered-value" + i);
+        }
+
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> orderedLeafSetBuilder = Builders.orderedLeafSetBuilder()
+                .withNodeIdentifier(new NodeIdentifier(ORDERED_LEAF_LIST_QNAME));
+        for (int i = 3; i > 0; i--) {
+            orderedLeafSetBuilder.withChildValue("ordered-value" + i);
+        }
+
+        ContainerNode testContainerNode = Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(leafSetBuilder.build())
+                .withChild(orderedLeafSetBuilder.build()).build();
+
+        DataNormalizer normalizer = new DataNormalizer(createTestContext());
+
+        Node<?> legacyNode = normalizer.toLegacy(InstanceIdentifier.builder(TEST_QNAME).build(), testContainerNode);
+
+        verifyLegacyNode(
+                legacyNode,
+                expectCompositeNode(TEST_QNAME, expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value1"),
+                        expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value2"),
+                        expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value3"),
+                        expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value3"),
+                        expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value2"),
+                        expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value1")));
+    }
+
+    @Test
+    public void testToLegacyNormalizedNodeWithAugmentation() {
+
+        AugmentationNode augmentationNode = Builders.augmentationBuilder()
+                .withNodeIdentifier(new AugmentationIdentifier(Sets.newHashSet(AUGMENTED_LEAF_QNAME)))
+                .withChild(ImmutableNodes.leafNode(AUGMENTED_LEAF_QNAME, "augmented-value")).build();
+
+        ContainerNode outerContainerNode = Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(OUTER_CONTAINER_QNAME)).withChild(augmentationNode).build();
+
+        ContainerNode testContainerNode = Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(outerContainerNode).build();
+
+        DataNormalizer normalizer = new DataNormalizer(createTestContext());
+
+        Node<?> legacyNode = normalizer.toLegacy(InstanceIdentifier.builder(TEST_QNAME).build(), testContainerNode);
+
+        verifyLegacyNode(
+                legacyNode,
+                expectCompositeNode(
+                        TEST_QNAME,
+                        expectCompositeNode(OUTER_CONTAINER_QNAME,
+                                expectSimpleNode(AUGMENTED_LEAF_QNAME, "augmented-value"))));
+    }
+
+    private boolean isOrdered(final QName nodeName) {
+        return ORDERED_LEAF_LIST_QNAME.equals(nodeName) || INNER_LIST_QNAME.equals(nodeName);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void verifyLegacyNode(final Node<?> actual, final LegacyNodeData expNodeData) {
+
+        assertNotNull("Actual Node is null", actual);
+        assertTrue("Expected CompositeNode instance", actual instanceof CompositeNode);
+        CompositeNode actualCN = (CompositeNode) actual;
+        assertEquals("Node key", expNodeData.nodeKey, actualCN.getKey());
+
+        List<LegacyNodeData> expChildData = Lists.newArrayList();
+        List<LegacyNodeData> unorderdChildData = Lists.newArrayList();
+        for (LegacyNodeData data : (List<LegacyNodeData>) expNodeData.nodeData) {
+            if (isOrdered(data.nodeKey)) {
+                expChildData.add(data);
+            } else {
+                unorderdChildData.add(data);
+            }
+        }
+
+        Collections.sort(unorderdChildData, new Comparator<LegacyNodeData>() {
+            @Override
+            public int compare(final LegacyNodeData arg1, final LegacyNodeData arg2) {
+                if (!(arg1.nodeData instanceof List) && !(arg2.nodeData instanceof List)) {
+                    // if neither is a list, just compare them
+                    String str1 = arg1.nodeKey.getLocalName() + arg1.nodeData;
+                    String str2 = arg2.nodeKey.getLocalName() + arg2.nodeData;
+                    return str1.compareTo(str2);
+                } else if (arg1.nodeData instanceof List && arg2.nodeData instanceof List) {
+                    // if both are lists, first check their local name
+                    String str1 = arg1.nodeKey.getLocalName();
+                    String str2 = arg2.nodeKey.getLocalName();
+                    if (!str1.equals(str2)) {
+                        return str1.compareTo(str2);
+                    } else {
+                        // if local names are the same, then look at the list contents
+                        List<LegacyNodeData> l1 = (List<LegacyNodeData>) arg1.nodeData;
+                        List<LegacyNodeData> l2 = (List<LegacyNodeData>) arg2.nodeData;
+
+                        if (l1.size() != l2.size()) {
+                            // if the sizes are different, use that
+                            return l2.size() - l1.size();
+                        } else {
+                            // lastly sort and recursively check the list contents
+                            Collections.sort(l1, this);
+                            Collections.sort(l2, this);
+
+                            for (int i = 0 ; i < l1.size() ; i++) {
+                                int diff = this.compare(l1.get(i), l2.get(i));
+                                if (diff != 0) {
+                                    return diff;
+                                }
+                            }
+                            return 0;
+                        }
+                    }
+                } else if( arg1.nodeData instanceof List ) {
+                    return -1;
+                } else{
+                    return 1;
+                }
+            }
+        });
+
+        expChildData.addAll(unorderdChildData);
+
+        List<Node<?>> actualChildNodes = Lists.newArrayList();
+        List<Node<?>> unorderedChildNodes = Lists.newArrayList();
+        for (Node<?> node : actualCN.getValue()) {
+            if (isOrdered(node.getKey())) {
+                actualChildNodes.add(node);
+            } else {
+                unorderedChildNodes.add(node);
+            }
+        }
+
+        Collections.sort(unorderedChildNodes, new Comparator<Node<?>>() {
+            @Override
+            public int compare(final Node<?> n1, final Node<?> n2) {
+                if (n1 instanceof SimpleNode && n2 instanceof SimpleNode) {
+                    // if they're SimpleNodes just compare their strings
+                    String str1 = n1.getKey().getLocalName() + ((SimpleNode<?>)n1).getValue();
+                    String str2 = n2.getKey().getLocalName() + ((SimpleNode<?>)n2).getValue();
+                    return str1.compareTo(str2);
+                } else if (n1 instanceof CompositeNode && n2 instanceof CompositeNode) {
+                    // if they're CompositeNodes, things are more interesting
+                    String str1 = n1.getKey().getLocalName();
+                    String str2 = n2.getKey().getLocalName();
+                    if (!str1.equals(str2)) {
+                        // if their local names differ, return that difference
+                        return str1.compareTo(str2);
+                    } else {
+                        // otherwise, we need to look at their contents
+                        ArrayList<Node<?>> l1 = new ArrayList<Node<?>>( ((CompositeNode)n1).getValue() );
+                        ArrayList<Node<?>> l2 = new ArrayList<Node<?>>( ((CompositeNode)n2).getValue() );
+
+                        if (l1.size() != l2.size()) {
+                            // if they have different numbers of things in them return that
+                            return l2.size() - l1.size();
+                        } else {
+                            // otherwise, compare the individual elements, first sort them
+                            Collections.sort(l1, this);
+                            Collections.sort(l2, this);
+
+                            // then compare them individually
+                            for(int i = 0 ; i < l2.size() ; i++) {
+                                int diff = this.compare(l1.get(i), l2.get(i));
+                                if(diff != 0){
+                                    return diff;
+                                }
+                            }
+                            return 0;
+                        }
+                    }
+                } else if (n1 instanceof CompositeNode && n2 instanceof SimpleNode) {
+                    return -1;
+                } else if (n2 instanceof CompositeNode && n1 instanceof SimpleNode) {
+                    return 1;
+                } else {
+                    assertTrue("Expected either SimpleNodes CompositeNodes", false);
+                    return 0;
+                }
+            }
+        });
+
+        actualChildNodes.addAll(unorderedChildNodes);
+
+        for (Node<?> actualChild : actualChildNodes) {
+            LegacyNodeData expData = expChildData.isEmpty() ? null : expChildData.remove(0);
+            assertNotNull("Unexpected child node with key " + actualChild.getKey(), expData);
+            assertEquals("Child node QName", expData.nodeKey, actualChild.getKey());
+
+            if (expData.nodeData instanceof List) { // List represents a
+                // composite node
+                verifyLegacyNode(actualChild, expData);
+            } else { // else a simple node
+                assertTrue("Expected SimpleNode instance", actualChild instanceof SimpleNode);
+                assertEquals("Child node value with key " + actualChild.getKey(), expData.nodeData,
+                        ((SimpleNode<?>) actualChild).getValue());
+            }
+        }
+
+        if (!expChildData.isEmpty()) {
+            fail("Missing child nodes: " + expChildData);
+        }
+    }
+
+    private LegacyNodeData expectCompositeNode(final QName key, final LegacyNodeData... childData) {
+        return new LegacyNodeData(key, Lists.newArrayList(childData));
+    }
+
+    private LegacyNodeData expectSimpleNode(final QName key, final Object value) {
+        return new LegacyNodeData(key, value);
+    }
+
+    @Test
+    public void testToNormalizedCompositeNode() {
+        SchemaContext testCtx = createTestContext();
+        DataNormalizer normalizer = new DataNormalizer(testCtx);
+
+        CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
+        testBuilder.setQName(TEST_QNAME);
+
+        CompositeNodeBuilder<ImmutableCompositeNode> outerListBuilder = ImmutableCompositeNode.builder();
+        outerListBuilder.setQName(OUTER_LIST_QNAME);
+        outerListBuilder.addLeaf(ID_QNAME, 10);
+        outerListBuilder.addLeaf(ONE_QNAME, "one");
+
+        for (int i = 3; i > 0; i--) {
+            CompositeNodeBuilder<ImmutableCompositeNode> innerListBuilder = ImmutableCompositeNode.builder();
+            innerListBuilder.setQName(INNER_LIST_QNAME);
+            innerListBuilder.addLeaf(NAME_QNAME, "inner-name" + i);
+            innerListBuilder.addLeaf(VALUE_QNAME, "inner-value" + i);
+            outerListBuilder.add(innerListBuilder.toInstance());
+        }
+
+        testBuilder.add(outerListBuilder.toInstance());
+
+        outerListBuilder = ImmutableCompositeNode.builder();
+        outerListBuilder.setQName(OUTER_LIST_QNAME);
+        outerListBuilder.addLeaf(ID_QNAME, 20);
+        outerListBuilder.addLeaf(TWO_QNAME, "two");
+        outerListBuilder.addLeaf(THREE_QNAME, "three");
+        testBuilder.add(outerListBuilder.toInstance());
+
+        for (int i = 1; i <= 2; i++) {
+            CompositeNodeBuilder<ImmutableCompositeNode> unkeyedListBuilder = ImmutableCompositeNode.builder();
+            unkeyedListBuilder.setQName(UNKEYED_LIST_QNAME);
+            unkeyedListBuilder.addLeaf(NAME_QNAME, "unkeyed-name" + i);
+            testBuilder.add(unkeyedListBuilder.toInstance());
+        }
+
+        Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
+                .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
+                        ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
+
+        verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
+
+        verifyNormalizedNode(
+                normalizedNodeEntry.getValue(),
+                expectContainerNode(
+                        TEST_QNAME,
+                        expectMapNode(
+                                OUTER_LIST_QNAME,
+                                expectMapEntryNode(
+                                        OUTER_LIST_QNAME,
+                                        ID_QNAME,
+                                        10,
+                                        expectLeafNode(ID_QNAME, 10),
+                                        expectChoiceNode(OUTER_CHOICE_QNAME, expectLeafNode(ONE_QNAME, "one")),
+                                        expectOrderedMapNode(
+                                                INNER_LIST_QNAME,
+                                                expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name3",
+                                                        expectLeafNode(NAME_QNAME, "inner-name3"),
+                                                        expectLeafNode(VALUE_QNAME, "inner-value3")),
+                                                        expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name2",
+                                                                expectLeafNode(NAME_QNAME, "inner-name2"),
+                                                                expectLeafNode(VALUE_QNAME, "inner-value2")),
+                                                                expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name1",
+                                                                        expectLeafNode(NAME_QNAME, "inner-name1"),
+                                                                        expectLeafNode(VALUE_QNAME, "inner-value1")))),
+                                                                        expectMapEntryNode(
+                                                                                OUTER_LIST_QNAME,
+                                                                                ID_QNAME,
+                                                                                20,
+                                                                                expectLeafNode(ID_QNAME, 20),
+                                                                                expectChoiceNode(OUTER_CHOICE_QNAME, expectLeafNode(TWO_QNAME, "two"),
+                                                                                        expectLeafNode(THREE_QNAME, "three")))),
+                                                                                        expectUnkeyedListNode(
+                                                                                                UNKEYED_LIST_QNAME,
+                                                                                                expectUnkeyedListEntryNode(UNKEYED_LIST_QNAME,
+                                                                                                        expectLeafNode(NAME_QNAME, "unkeyed-name1")),
+                                                                                                        expectUnkeyedListEntryNode(UNKEYED_LIST_QNAME,
+                                                                                                                expectLeafNode(NAME_QNAME, "unkeyed-name2")))));
+    }
+
+    @Test
+    public void testToNormalizedCompositeNodeWithAnyXml() {
+        SchemaContext testCtx = createTestContext();
+        DataNormalizer normalizer = new DataNormalizer(testCtx);
+
+        CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
+        testBuilder.setQName(TEST_QNAME);
+
+        CompositeNodeBuilder<ImmutableCompositeNode> anyXmlBuilder = ImmutableCompositeNode.builder();
+        anyXmlBuilder.setQName(ANY_XML_DATA_QNAME);
+        anyXmlBuilder.addLeaf(ANY_XML_LEAF_QNAME, "leaf-value");
+
+        CompositeNodeBuilder<ImmutableCompositeNode> innerBuilder = ImmutableCompositeNode.builder();
+        innerBuilder.setQName(ANY_XML_INNER_QNAME);
+        innerBuilder.addLeaf(ANY_XML_INNER_LEAF_QNAME, "inner-leaf-value");
+
+        anyXmlBuilder.add(innerBuilder.toInstance());
+        CompositeNode anyXmlLegacy = anyXmlBuilder.toInstance();
+        testBuilder.add(anyXmlLegacy);
+
+        Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
+                .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
+                        ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
+
+        verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
+
+        verifyNormalizedNode(normalizedNodeEntry.getValue(),
+                expectContainerNode(TEST_QNAME, expectAnyXmlNode(ANY_XML_DATA_QNAME, anyXmlLegacy)));
+    }
+
+    @Test
+    public void testToNormalizedCompositeNodeWithAugmentation() {
+        SchemaContext testCtx = createTestContext();
+        DataNormalizer normalizer = new DataNormalizer(testCtx);
+
+        CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
+        testBuilder.setQName(TEST_QNAME);
+
+        CompositeNodeBuilder<ImmutableCompositeNode> outerContBuilder = ImmutableCompositeNode.builder();
+        outerContBuilder.setQName(OUTER_CONTAINER_QNAME);
+        outerContBuilder.addLeaf(AUGMENTED_LEAF_QNAME, "augmented-value");
+
+        testBuilder.add(outerContBuilder.toInstance());
+
+        Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
+                .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
+                        ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
+
+        verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
+
+        NormalizedNodeData expAugmentation = expectAugmentation(AUGMENTED_LEAF_QNAME,
+                expectLeafNode(AUGMENTED_LEAF_QNAME, "augmented-value"));
+
+        verifyNormalizedNode(normalizedNodeEntry.getValue(),
+                expectContainerNode(TEST_QNAME, expectContainerNode(OUTER_CONTAINER_QNAME, expAugmentation)));
+
+        normalizedNodeEntry = normalizer.toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(
+                InstanceIdentifier.create(Lists.newArrayList(new NodeIdentifier(TEST_QNAME), new NodeIdentifier(
+                        OUTER_CONTAINER_QNAME))), outerContBuilder.toInstance()));
+
+        verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME, OUTER_CONTAINER_QNAME,
+                Sets.newHashSet(AUGMENTED_LEAF_QNAME));
+
+        verifyNormalizedNode(normalizedNodeEntry.getValue(), expAugmentation);
+    }
+
+    @Test
+    public void testToNormalizedCompositeNodeWithLeafLists() {
+        SchemaContext testCtx = createTestContext();
+        DataNormalizer normalizer = new DataNormalizer(testCtx);
+
+        CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
+        testBuilder.setQName(TEST_QNAME);
+
+        for (int i = 1; i <= 3; i++) {
+            testBuilder.addLeaf(UNORDERED_LEAF_LIST_QNAME, "unordered-value" + i);
+        }
+
+        for (int i = 3; i > 0; i--) {
+            testBuilder.addLeaf(ORDERED_LEAF_LIST_QNAME, "ordered-value" + i);
+        }
+
+        Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
+                .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
+                        ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
+
+        verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
+
+        verifyNormalizedNode(
+                normalizedNodeEntry.getValue(),
+                expectContainerNode(
+                        TEST_QNAME,
+                        expectLeafSetNode(UNORDERED_LEAF_LIST_QNAME,
+                                expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value1"),
+                                expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value2"),
+                                expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value3")),
+                                expectOrderedLeafSetNode(ORDERED_LEAF_LIST_QNAME,
+                                        expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value3"),
+                                        expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value2"),
+                                        expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value1"))));
+    }
+
+    @SuppressWarnings("unchecked")
+    private void verifyNormalizedNode(final NormalizedNode<?, ?> actual, final NormalizedNodeData expNodeData) {
+
+        Class<?> expNodeClass = expNodeData.nodeClass;
+        PathArgument expNodeID = expNodeData.nodeID;
+
+        assertNotNull("Actual NormalizedNode is null", actual);
+        assertTrue("NormalizedNode instance " + actual.getClass() + " is not derived from " + expNodeClass,
+                expNodeClass.isAssignableFrom(actual.getClass()));
+        assertEquals("NormalizedNode identifier", expNodeID, actual.getIdentifier());
+
+        if (expNodeData.nodeData instanceof List) {
+            Map<PathArgument, Integer> orderingMap = null;
+            if (expNodeClass.equals(OrderedMapNode.class) || expNodeClass.equals(OrderedLeafSetNode.class)) {
+                orderingMap = Maps.newHashMap();
+            }
+
+            int i = 1;
+            Map<PathArgument, NormalizedNodeData> expChildDataMap = Maps.newHashMap();
+            List<NormalizedNodeData> expChildDataList = (List<NormalizedNodeData>) expNodeData.nodeData;
+            for (NormalizedNodeData data : expChildDataList) {
+                expChildDataMap.put(data.nodeID, data);
+
+                if (orderingMap != null) {
+                    orderingMap.put(data.nodeID, i++);
+                }
+            }
+
+            assertNotNull("Actual value is null for node " + actual.getIdentifier(), actual.getValue());
+            assertTrue("Expected value instance Iterable for node " + actual.getIdentifier(),
+                    Iterable.class.isAssignableFrom(actual.getValue().getClass()));
+
+            i = 1;
+            for (NormalizedNode<?, ?> actualChild : (Iterable<NormalizedNode<?, ?>>) actual.getValue()) {
+                NormalizedNodeData expChildData = expNodeClass.equals(UnkeyedListNode.class) ? expChildDataList
+                        .remove(0) : expChildDataMap.remove(actualChild.getIdentifier());
+
+                        assertNotNull(
+                                "Unexpected child node " + actualChild.getClass() + " with identifier "
+                                        + actualChild.getIdentifier() + " for parent node " + actual.getClass()
+                                        + " with identifier " + actual.getIdentifier(), expChildData);
+
+                        if (orderingMap != null) {
+                            assertEquals("Order index for child node " + actualChild.getIdentifier(),
+                                    orderingMap.get(actualChild.getIdentifier()), Integer.valueOf(i));
+                        }
+
+                        verifyNormalizedNode(actualChild, expChildData);
+                        i++;
+            }
+
+            if (expNodeClass.equals(UnkeyedListNode.class)) {
+                if (expChildDataList.size() > 0) {
+                    fail("Missing " + expChildDataList.size() + " child nodes for parent " + actual.getIdentifier());
+                }
+            } else {
+                if (!expChildDataMap.isEmpty()) {
+                    fail("Missing child nodes for parent " + actual.getIdentifier() + ": " + expChildDataMap.keySet());
+                }
+            }
+        } else {
+            assertEquals("Leaf value for node " + actual.getIdentifier(), expNodeData.nodeData, actual.getValue());
+        }
+    }
+
+    private NormalizedNodeData expectOrderedLeafSetNode(final QName nodeName, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), OrderedLeafSetNode.class,
+                Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectLeafSetNode(final QName nodeName, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), LeafSetNode.class, Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectLeafSetEntryNode(final QName nodeName, final Object value) {
+        return new NormalizedNodeData(new NodeWithValue(nodeName, value), LeafSetEntryNode.class, value);
+    }
+
+    private NormalizedNodeData expectUnkeyedListNode(final QName nodeName, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), UnkeyedListNode.class,
+                Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectUnkeyedListEntryNode(final QName nodeName, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), UnkeyedListEntryNode.class,
+                Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectAugmentation(final QName augmentedNodeName, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new AugmentationIdentifier(Sets.newHashSet(augmentedNodeName)),
+                AugmentationNode.class, Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectAnyXmlNode(final QName nodeName, final Object value) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), AnyXmlNode.class, value);
+    }
+
+    private NormalizedNodeData expectContainerNode(final QName nodeName, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), ContainerNode.class, Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectChoiceNode(final QName nodeName, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), ChoiceNode.class, Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectLeafNode(final QName nodeName, final Object value) {
+        return new NormalizedNodeData(new NodeIdentifier(nodeName), LeafNode.class, value);
+
+    }
+
+    private NormalizedNodeData expectMapEntryNode(final QName nodeName, final QName key, final Object value,
+            final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifierWithPredicates(nodeName, key, value), MapEntryNode.class,
+                Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectMapNode(final QName key, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(key), MapNode.class, Lists.newArrayList(childData));
+    }
+
+    private NormalizedNodeData expectOrderedMapNode(final QName key, final NormalizedNodeData... childData) {
+        return new NormalizedNodeData(new NodeIdentifier(key), OrderedMapNode.class, Lists.newArrayList(childData));
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-impl/src/test/resources/normalization-test.yang b/opendaylight/md-sal/sal-common-impl/src/test/resources/normalization-test.yang
new file mode 100644 (file)
index 0000000..6df5306
--- /dev/null
@@ -0,0 +1,74 @@
+module normalization-test {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:normalization:test";
+    prefix "norm-test";
+
+    revision "2014-03-13" {
+        description "Initial revision.";
+    }
+
+    grouping outer-grouping {
+    }
+
+    container test {
+        list outer-list {
+            key id;
+            leaf id {
+                type uint16;
+            }
+            choice outer-choice {
+                case one {
+                    leaf one {
+                        type string;
+                    }
+                }
+                case two-three {
+                    leaf two {
+                        type string;
+                    }
+                    leaf three {
+                        type string;
+                    }
+               }
+           }
+           list inner-list {
+                key name;
+                ordered-by user;
+
+                leaf name {
+                    type string;
+                }
+                leaf value {
+                    type string;
+                }
+            }
+        }
+
+        list unkeyed-list {
+            leaf name {
+                type string;
+            }
+        }
+
+        leaf-list unordered-leaf-list {
+            type string;
+        }
+
+        leaf-list ordered-leaf-list {
+            ordered-by user;
+            type string;
+        }
+
+        container outer-container {
+        }
+
+        anyxml any-xml-data;
+    }
+
+    augment /norm-test:test/norm-test:outer-container {
+
+        leaf augmented-leaf {
+           type string;
+        }
+    }
+}
\ No newline at end of file
index e7fcd83328f86c425e7a95092da1b3cc5f36bc47..ea686d966ffa63b60e1cf3cb839db2f2eb034f1e 100644 (file)
       <artifactId>akka-remote_${scala.version}</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>com.typesafe.akka</groupId>
+      <artifactId>akka-testkit_${scala.version}</artifactId>
+    </dependency>
+
     <!-- SAL Dependencies -->
 
     <dependency>
       <artifactId>sal-binding-config</artifactId>
     </dependency>
 
+    <!--
+      Adding a temporary dependency on the sal-broker-impl so that we can use InMemoryDOMDataStore
+
+      InMemoryDOMDataStore needs to be moved into its own module and be wired up using config subsystem before
+      this bundle can use it
+    -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-broker-impl</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-api</artifactId>
       <artifactId>org.osgi.core</artifactId>
     </dependency>
 
-    <!-- AKKA Dependencies -->
     <dependency>
       <groupId>org.scala-lang</groupId>
       <artifactId>scala-library</artifactId>
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListener.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListener.java
new file mode 100644 (file)
index 0000000..ba09d04
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+
+public class DataChangeListener extends UntypedActor {
+    @Override public void onReceive(Object message) throws Exception {
+        throw new UnsupportedOperationException("onReceive");
+    }
+
+    public static Props props() {
+        return Props.create(new Creator<DataChangeListener>() {
+            @Override
+            public DataChangeListener create() throws Exception {
+                return new DataChangeListener();
+            }
+
+        });
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxy.java
new file mode 100644 (file)
index 0000000..8423b98
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorSelection;
+import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * DataChangeListenerProxy represents a single remote DataChangeListener
+ */
+public class DataChangeListenerProxy implements AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>{
+    private final ActorSelection dataChangeListenerActor;
+
+    public DataChangeListenerProxy(ActorSelection dataChangeListenerActor) {
+        this.dataChangeListenerActor = dataChangeListenerActor;
+    }
+
+    @Override public void onDataChanged(
+        AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
+        dataChangeListenerActor.tell(new DataChanged(change), null);
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistration.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistration.java
new file mode 100644 (file)
index 0000000..e90d53c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistration;
+import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistrationReply;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class DataChangeListenerRegistration extends UntypedActor{
+
+  private final org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> registration;
+
+  public DataChangeListenerRegistration(
+      org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> registration) {
+    this.registration = registration;
+  }
+
+  @Override
+  public void onReceive(Object message) throws Exception {
+    if(message instanceof CloseDataChangeListenerRegistration){
+      closeListenerRegistration((CloseDataChangeListenerRegistration) message);
+    }
+  }
+
+  public static Props props(final org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> registration){
+    return Props.create(new Creator<DataChangeListenerRegistration>(){
+
+      @Override
+      public DataChangeListenerRegistration create() throws Exception {
+        return new DataChangeListenerRegistration(registration);
+      }
+    });
+  }
+
+  private void closeListenerRegistration(CloseDataChangeListenerRegistration message){
+    registration.close();
+    getSender().tell(new CloseDataChangeListenerRegistrationReply(), getSelf());
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxy.java
new file mode 100644 (file)
index 0000000..89cc969
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorSelection;
+import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistration;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * ListenerRegistrationProxy acts as a proxy for a ListenerRegistration that was done on a remote shard
+ * <p>
+ * Registering a DataChangeListener on the Data Store creates a new instance of the ListenerRegistrationProxy
+ * The ListenerRegistrationProxy talks to a remote ListenerRegistration actor.
+ * </p>
+ */
+public class DataChangeListenerRegistrationProxy implements ListenerRegistration {
+    private final ActorSelection listenerRegistrationActor;
+    private final AsyncDataChangeListener listener;
+
+    public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
+    DataChangeListenerRegistrationProxy(
+        ActorSelection listenerRegistrationActor,
+        L listener) {
+        this.listenerRegistrationActor = listenerRegistrationActor;
+        this.listener = listener;
+    }
+
+    @Override
+    public Object getInstance() {
+        return listener;
+    }
+
+    @Override
+    public void close() {
+        listenerRegistrationActor.tell(new CloseDataChangeListenerRegistration(), null);
+    }
+}
index 1bc554f3ed653c3a50012044178e4a247489785a..4964b92ab75a0d3d7f85c5404c22e0df7c80fbff 100644 (file)
@@ -1,5 +1,19 @@
+/*
+ * 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.cluster.datastore;
 
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
@@ -10,34 +24,75 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  *
  */
-public class DistributedDataStore implements DOMStore {
+public class DistributedDataStore implements DOMStore, SchemaContextListener {
+
+    private static final Logger
+        LOG = LoggerFactory.getLogger(DistributedDataStore.class);
+
+
+    private final String type;
+    private final ActorContext actorContext;
+
+    public DistributedDataStore(ActorSystem actorSystem, String type) {
+        this(new ActorContext(actorSystem, actorSystem.actorOf(ShardManager.props(type))), type);
+    }
+
+    public DistributedDataStore(ActorContext actorContext, String type) {
+        this.type = type;
+        this.actorContext = actorContext;
+    }
+
 
     @Override
-    public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(InstanceIdentifier path, L listener, AsyncDataBroker.DataChangeScope scope) {
-        return new ListenerRegistrationProxy();
+    public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
+        InstanceIdentifier path, L listener,
+        AsyncDataBroker.DataChangeScope scope) {
+
+        ActorRef dataChangeListenerActor = actorContext.getActorSystem().actorOf(
+            DataChangeListener.props());
+
+        Object result = actorContext.executeShardOperation(Shard.DEFAULT_NAME,
+            new RegisterChangeListener(path, dataChangeListenerActor.path(),
+                AsyncDataBroker.DataChangeScope.BASE),
+            ActorContext.ASK_DURATION
+        );
+
+        RegisterChangeListenerReply reply = (RegisterChangeListenerReply) result;
+        return new DataChangeListenerRegistrationProxy(actorContext.actorSelection(reply.getListenerRegistrationPath()), listener);
     }
 
+
+
     @Override
     public DOMStoreTransactionChain createTransactionChain() {
-        return new TransactionChainProxy();
+        return new TransactionChainProxy(actorContext);
     }
 
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        return new TransactionProxy();
+        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_ONLY);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        return new TransactionProxy();
+        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.WRITE_ONLY);
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        return new TransactionProxy();
+        return new TransactionProxy(actorContext, TransactionProxy.TransactionType.READ_WRITE);
+    }
+
+    @Override public void onGlobalContextUpdated(SchemaContext schemaContext) {
+        actorContext.getShardManager().tell(
+            new UpdateSchemaContext(schemaContext), null);
     }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ListenerRegistrationProxy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ListenerRegistrationProxy.java
deleted file mode 100644 (file)
index 19e7f19..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.opendaylight.controller.cluster.datastore;
-
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-
-/**
- * ListenerRegistrationProxy acts as a proxy for a ListenerRegistration that was done on a remote shard
- *
- * Registering a DataChangeListener on the Data Store creates a new instance of the ListenerRegistrationProxy
- * The ListenerRegistrationProxy talks to a remote ListenerRegistration actor.
- */
-public class ListenerRegistrationProxy implements ListenerRegistration {
-    @Override
-    public Object getInstance() {
-        throw new UnsupportedOperationException("getInstance");
-    }
-
-    @Override
-    public void close() {
-        throw new UnsupportedOperationException("close");
-    }
-}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
new file mode 100644 (file)
index 0000000..b4ad089
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
+import akka.actor.Props;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.japi.Creator;
+import akka.persistence.Persistent;
+import akka.persistence.UntypedProcessor;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.opendaylight.controller.cluster.datastore.messages.CommitTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.ForwardedCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.controller.cluster.datastore.modification.Modification;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+/**
+ * A Shard represents a portion of the logical data tree <br/>
+ * <p>
+ * Our Shard uses InMemoryDataStore as it's internal representation and delegates all requests it
+ * </p>
+ */
+public class Shard extends UntypedProcessor {
+
+    public static final String DEFAULT_NAME = "default";
+
+    private final ListeningExecutorService storeExecutor =
+        MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2));
+
+    private final InMemoryDOMDataStore store;
+
+    private final Map<Modification, DOMStoreThreePhaseCommitCohort>
+        modificationToCohort = new HashMap<>();
+
+    private final LoggingAdapter log =
+        Logging.getLogger(getContext().system(), this);
+
+    private Shard(String name) {
+        store = new InMemoryDOMDataStore(name, storeExecutor);
+    }
+
+    public static Props props(final String name) {
+        return Props.create(new Creator<Shard>() {
+
+            @Override
+            public Shard create() throws Exception {
+                return new Shard(name);
+            }
+
+        });
+    }
+
+    @Override
+    public void onReceive(Object message) throws Exception {
+        if (message instanceof CreateTransactionChain) {
+            createTransactionChain();
+        } else if (message instanceof RegisterChangeListener) {
+            registerChangeListener((RegisterChangeListener) message);
+        } else if (message instanceof UpdateSchemaContext) {
+            updateSchemaContext((UpdateSchemaContext) message);
+        } else if (message instanceof ForwardedCommitTransaction) {
+            handleForwardedCommit((ForwardedCommitTransaction) message);
+        } else if (message instanceof Persistent) {
+            commit((Persistent) message);
+        }
+    }
+
+    private void commit(Persistent message) {
+        Modification modification = (Modification) message.payload();
+        DOMStoreThreePhaseCommitCohort cohort =
+            modificationToCohort.remove(modification);
+        if (cohort == null) {
+            log.error(
+                "Could not find cohort for modification : " + modification);
+            return;
+        }
+        final ListenableFuture<Void> future = cohort.commit();
+        final ActorRef sender = getSender();
+        final ActorRef self = getSelf();
+        future.addListener(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    future.get();
+                    sender.tell(new CommitTransactionReply(), self);
+                } catch (InterruptedException | ExecutionException e) {
+                    log.error(e, "An exception happened when committing");
+                }
+            }
+        }, getContext().dispatcher());
+    }
+
+    private void handleForwardedCommit(ForwardedCommitTransaction message) {
+        log.info("received forwarded transaction");
+        modificationToCohort
+            .put(message.getModification(), message.getCohort());
+        getSelf().forward(Persistent.create(message.getModification()),
+            getContext());
+    }
+
+    private void updateSchemaContext(UpdateSchemaContext message) {
+        store.onGlobalContextUpdated(message.getSchemaContext());
+    }
+
+    private void registerChangeListener(
+        RegisterChangeListener registerChangeListener) {
+
+        ActorSelection dataChangeListenerPath = getContext()
+            .system().actorSelection(registerChangeListener.getDataChangeListenerPath());
+
+        AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>
+            listener = new DataChangeListenerProxy(dataChangeListenerPath);
+
+        org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
+            registration =
+            store.registerChangeListener(registerChangeListener.getPath(),
+                listener, registerChangeListener.getScope());
+        ActorRef listenerRegistration =
+            getContext().actorOf(
+                DataChangeListenerRegistration.props(registration));
+        getSender()
+            .tell(new RegisterChangeListenerReply(listenerRegistration.path()),
+                getSelf());
+    }
+
+    private void createTransactionChain() {
+        DOMStoreTransactionChain chain = store.createTransactionChain();
+        ActorRef transactionChain =
+            getContext().actorOf(ShardTransactionChain.props(chain));
+        getSender()
+            .tell(new CreateTransactionChainReply(transactionChain.path()),
+                getSelf());
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
new file mode 100644 (file)
index 0000000..4e2369d
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorPath;
+import akka.actor.ActorRef;
+import akka.actor.Address;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.japi.Creator;
+import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
+import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The ShardManager has the following jobs,
+ * <p>
+ * <li> Create all the local shard replicas that belong on this cluster member
+ * <li> Find the primary replica for any given shard
+ * <li> Engage in shard replica elections which decide which replica should be the primary
+ * </p>
+ * <p/>
+ * <h3>>Creation of Shard replicas</h3
+ * <p>
+ * When the ShardManager is constructed it reads the cluster configuration to find out which shard replicas
+ * belong on this member. It finds out the name of the current cluster member from the Akka Clustering Service.
+ * </p>
+ * <p/>
+ * <h3> Replica Elections </h3>
+ * <p/>
+ * <p>
+ * The Shard Manager uses multiple cues to initiate election.
+ * <li> When a member of the cluster dies
+ * <li> When a local shard replica dies
+ * <li> When a local shard replica comes alive
+ * </p>
+ */
+public class ShardManager extends UntypedActor {
+
+  // Stores a mapping between a shard name and the address of the current primary
+  private final Map<String, Address> shardNameToPrimaryAddress = new HashMap<>();
+
+  // Stores a mapping between a member name and the address of the member
+  private final Map<String, Address> memberNameToAddress = new HashMap<>();
+
+  // Stores a mapping between the shard name and all the members on which a replica of that shard are available
+  private final Map<String, List<String>> shardNameToMembers = new HashMap<>();
+
+  private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+  private final ActorPath defaultShardPath;
+
+  /**
+   *
+   * @param type defines the kind of data that goes into shards created by this shard manager. Examples of type would be
+   *             configuration or operational
+   */
+  private ShardManager(String type){
+    ActorRef actor = getContext().actorOf(Shard.props(Shard.DEFAULT_NAME + "-" + type));
+    defaultShardPath = actor.path();
+  }
+
+  public static Props props(final String type){
+    return Props.create(new Creator<ShardManager>(){
+
+      @Override
+      public ShardManager create() throws Exception {
+        return new ShardManager(type);
+      }
+    });
+  }
+
+  @Override
+  public void onReceive(Object message) throws Exception {
+    if (message instanceof FindPrimary) {
+      FindPrimary msg = ((FindPrimary) message);
+      String shardName = msg.getShardName();
+      if(Shard.DEFAULT_NAME.equals(shardName)){
+        getSender().tell(new PrimaryFound(defaultShardPath.toString()), getSelf());
+      } else {
+        getSender().tell(new PrimaryNotFound(shardName), getSelf());
+      }
+    } else if(message instanceof UpdateSchemaContext){
+        // FIXME : Notify all local shards of a context change
+        getContext().system().actorSelection(defaultShardPath).forward(message, getContext());
+    }
+  }
+
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java
new file mode 100644 (file)
index 0000000..75744ca
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.japi.Creator;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
+import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
+import org.opendaylight.controller.cluster.datastore.modification.DeleteModification;
+import org.opendaylight.controller.cluster.datastore.modification.ImmutableCompositeModification;
+import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
+import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
+import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * The ShardTransaction Actor represents a remote transaction
+ *<p>
+ * The ShardTransaction Actor delegates all actions to DOMDataReadWriteTransaction
+ *</p>
+ *<p>
+ * Even though the DOMStore and the DOMStoreTransactionChain implement multiple types of transactions
+ * the ShardTransaction Actor only works with read-write transactions. This is just to keep the logic simple. At this
+ * time there are no known advantages for creating a read-only or write-only transaction which may change over time
+ * at which point we can optimize things in the distributed store as well.
+ *</p>
+ *<p>
+ * Handles Messages <br/>
+ * ---------------- <br/>
+ * <li> {@link org.opendaylight.controller.cluster.datastore.messages.ReadData}
+ * <li> {@link org.opendaylight.controller.cluster.datastore.messages.WriteData}
+ * <li> {@link org.opendaylight.controller.cluster.datastore.messages.MergeData}
+ * <li> {@link org.opendaylight.controller.cluster.datastore.messages.DeleteData}
+ * <li> {@link org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction}
+ * <li> {@link org.opendaylight.controller.cluster.datastore.messages.CloseTransaction}
+ * </p>
+ */
+public class ShardTransaction extends UntypedActor {
+
+  private final ActorRef shardActor;
+
+  private final DOMStoreReadWriteTransaction transaction;
+
+  private final MutableCompositeModification modification = new MutableCompositeModification();
+
+  private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+  public ShardTransaction(DOMStoreReadWriteTransaction transaction, ActorRef shardActor) {
+    this.transaction = transaction;
+    this.shardActor = shardActor;
+  }
+
+
+  public static Props props(final DOMStoreReadWriteTransaction transaction, final ActorRef shardActor){
+    return Props.create(new Creator<ShardTransaction>(){
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardTransaction(transaction, shardActor);
+      }
+    });
+  }
+
+  @Override
+  public void onReceive(Object message) throws Exception {
+    if(message instanceof ReadData){
+      readData((ReadData) message);
+    } else if(message instanceof WriteData){
+      writeData((WriteData) message);
+    } else if(message instanceof MergeData){
+      mergeData((MergeData) message);
+    } else if(message instanceof DeleteData){
+      deleteData((DeleteData) message);
+    } else if(message instanceof ReadyTransaction){
+      readyTransaction((ReadyTransaction) message);
+    } else if(message instanceof CloseTransaction){
+      closeTransaction((CloseTransaction) message);
+    } else if(message instanceof GetCompositedModification){
+      // This is here for testing only
+      getSender().tell(new GetCompositeModificationReply(new ImmutableCompositeModification(modification)), getSelf());
+    }
+  }
+
+  private void readData(ReadData message) {
+    final ActorRef sender = getSender();
+    final ActorRef self = getSelf();
+    final InstanceIdentifier path = message.getPath();
+    final ListenableFuture<Optional<NormalizedNode<?, ?>>> future = transaction.read(path);
+
+    future.addListener(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          Optional<NormalizedNode<?, ?>> optional = future.get();
+          if(optional.isPresent()){
+            sender.tell(new ReadDataReply(optional.get()), self);
+          } else {
+            //TODO : Need to decide what to do here
+          }
+        } catch (InterruptedException | ExecutionException e) {
+          log.error(e, "An exception happened when reading data from path : " + path.toString());
+        }
+
+      }
+    }, getContext().dispatcher());
+  }
+
+
+  private void writeData(WriteData message){
+    modification.addModification(new WriteModification(message.getPath(), message.getData()));
+    transaction.write(message.getPath(), message.getData());
+    getSender().tell(new WriteDataReply(), getSelf());
+  }
+
+  private void mergeData(MergeData message){
+    modification.addModification(new MergeModification(message.getPath(), message.getData()));
+    transaction.merge(message.getPath(), message.getData());
+    getSender().tell(new MergeDataReply(), getSelf());
+  }
+
+  private void deleteData(DeleteData message){
+    modification.addModification(new DeleteModification(message.getPath()));
+    transaction.delete(message.getPath());
+    getSender().tell(new DeleteDataReply(), getSelf());
+  }
+
+  private void readyTransaction(ReadyTransaction message){
+    DOMStoreThreePhaseCommitCohort cohort = transaction.ready();
+    ActorRef cohortActor = getContext().actorOf(ThreePhaseCommitCohort.props(cohort, shardActor, modification));
+    getSender().tell(new ReadyTransactionReply(cohortActor.path()), getSelf());
+
+  }
+
+  private void closeTransaction(CloseTransaction message){
+    transaction.close();
+    getSender().tell(new CloseTransactionReply(), getSelf());
+  }
+
+
+  // These classes are in here for test purposes only
+
+  static class GetCompositedModification {
+
+  }
+
+  static class GetCompositeModificationReply {
+    private final CompositeModification modification;
+
+
+    GetCompositeModificationReply(CompositeModification modification) {
+      this.modification = modification;
+    }
+
+
+    public CompositeModification getModification() {
+      return modification;
+    }
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java
new file mode 100644 (file)
index 0000000..79aaa86
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+
+/**
+ * The ShardTransactionChain Actor represents a remote TransactionChain
+ */
+public class ShardTransactionChain extends UntypedActor{
+
+  private final DOMStoreTransactionChain chain;
+
+  public ShardTransactionChain(DOMStoreTransactionChain chain) {
+    this.chain = chain;
+  }
+
+  @Override
+  public void onReceive(Object message) throws Exception {
+    if(message instanceof CreateTransaction){
+      DOMStoreReadWriteTransaction transaction = chain.newReadWriteTransaction();
+      ActorRef transactionActor = getContext().actorOf(ShardTransaction.props(transaction, getContext().parent()));
+      getSender().tell(new CreateTransactionReply(transactionActor.path()), getSelf());
+    } else if (message instanceof CloseTransactionChain){
+      chain.close();
+      getSender().tell(new CloseTransactionChainReply(), getSelf());
+    }
+  }
+
+  public static Props props(final DOMStoreTransactionChain chain){
+    return Props.create(new Creator<ShardTransactionChain>(){
+
+      @Override
+      public ShardTransactionChain create() throws Exception {
+        return new ShardTransactionChain(chain);
+      }
+    });
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.java
new file mode 100644 (file)
index 0000000..61baf1a
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.japi.Creator;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.cluster.datastore.messages.AbortTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.AbortTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.CommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.ForwardedCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransactionReply;
+import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+
+import java.util.concurrent.ExecutionException;
+
+public class ThreePhaseCommitCohort extends UntypedActor{
+  private final DOMStoreThreePhaseCommitCohort cohort;
+  private final ActorRef shardActor;
+  private final CompositeModification modification;
+
+  public ThreePhaseCommitCohort(DOMStoreThreePhaseCommitCohort cohort, ActorRef shardActor, CompositeModification modification) {
+    this.cohort = cohort;
+    this.shardActor = shardActor;
+    this.modification = modification;
+  }
+
+  private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+  public static Props props(final DOMStoreThreePhaseCommitCohort cohort, final ActorRef shardActor, final CompositeModification modification) {
+    return Props.create(new Creator<ThreePhaseCommitCohort>(){
+      @Override
+      public ThreePhaseCommitCohort create() throws Exception {
+        return new ThreePhaseCommitCohort(cohort, shardActor, modification);
+      }
+    });
+  }
+
+  @Override
+  public void onReceive(Object message) throws Exception {
+    if(message instanceof CanCommitTransaction){
+      canCommit((CanCommitTransaction) message);
+    } else if(message instanceof PreCommitTransaction) {
+      preCommit((PreCommitTransaction) message);
+    } else if(message instanceof CommitTransaction){
+      commit((CommitTransaction) message);
+    } else if (message instanceof AbortTransaction){
+      abort((AbortTransaction) message);
+    }
+  }
+
+  private void abort(AbortTransaction message) {
+    final ListenableFuture<Void> future = cohort.abort();
+    final ActorRef sender = getSender();
+    final ActorRef self = getSelf();
+
+    future.addListener(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          future.get();
+          sender.tell(new AbortTransactionReply(), self);
+        } catch (InterruptedException | ExecutionException e) {
+          log.error(e, "An exception happened when aborting");
+        }
+      }
+    }, getContext().dispatcher());
+  }
+
+  private void commit(CommitTransaction message) {
+    // Forward the commit to the shard
+    log.info("Commit transaction now + " + shardActor);
+    shardActor.forward(new ForwardedCommitTransaction(cohort, modification), getContext());
+
+  }
+
+  private void preCommit(PreCommitTransaction message) {
+    final ListenableFuture<Void> future = cohort.preCommit();
+    final ActorRef sender = getSender();
+    final ActorRef self = getSelf();
+
+    future.addListener(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          future.get();
+          sender.tell(new PreCommitTransactionReply(), self);
+        } catch (InterruptedException | ExecutionException e) {
+          log.error(e, "An exception happened when preCommitting");
+        }
+      }
+    }, getContext().dispatcher());
+
+  }
+
+  private void canCommit(CanCommitTransaction message) {
+    final ListenableFuture<Boolean> future = cohort.canCommit();
+    final ActorRef sender = getSender();
+    final ActorRef self = getSelf();
+
+    future.addListener(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          Boolean canCommit = future.get();
+          sender.tell(new CanCommitTransactionReply(canCommit), self);
+        } catch (InterruptedException | ExecutionException e) {
+          log.error(e, "An exception happened when aborting");
+        }
+      }
+    }, getContext().dispatcher());
+
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxy.java
new file mode 100644 (file)
index 0000000..197b3b7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorPath;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * ThreePhaseCommitCohortProxy represents a set of remote cohort proxies
+ */
+public class ThreePhaseCommitCohortProxy implements
+    DOMStoreThreePhaseCommitCohort{
+
+    private final List<ActorPath> cohortPaths;
+
+    public ThreePhaseCommitCohortProxy(List<ActorPath> cohortPaths) {
+
+        this.cohortPaths = cohortPaths;
+    }
+
+    @Override public ListenableFuture<Boolean> canCommit() {
+        throw new UnsupportedOperationException("canCommit");
+    }
+
+    @Override public ListenableFuture<Void> preCommit() {
+        throw new UnsupportedOperationException("preCommit");
+    }
+
+    @Override public ListenableFuture<Void> abort() {
+        throw new UnsupportedOperationException("abort");
+    }
+
+    @Override public ListenableFuture<Void> commit() {
+        throw new UnsupportedOperationException("commit");
+    }
+
+    public List<ActorPath> getCohortPaths() {
+        return Collections.unmodifiableList(this.cohortPaths);
+    }
+}
index 20a74e30dab07258b4a4122d56d0b7f6c7630f1d..837ffc1b51dd8c5b2a80a3cf2f71a1076406648d 100644 (file)
@@ -1,5 +1,14 @@
+/*
+ * 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.cluster.datastore;
 
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
@@ -9,23 +18,32 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
  * TransactionChainProxy acts as a proxy for a DOMStoreTransactionChain created on a remote shard
  */
 public class TransactionChainProxy implements DOMStoreTransactionChain{
+    private final ActorContext actorContext;
+
+    public TransactionChainProxy(ActorContext actorContext) {
+        this.actorContext = actorContext;
+    }
+
     @Override
     public DOMStoreReadTransaction newReadOnlyTransaction() {
-        throw new UnsupportedOperationException("newReadOnlyTransaction");
+        return new TransactionProxy(actorContext,
+            TransactionProxy.TransactionType.READ_ONLY);
     }
 
     @Override
     public DOMStoreReadWriteTransaction newReadWriteTransaction() {
-        throw new UnsupportedOperationException("newReadWriteTransaction");
+        return new TransactionProxy(actorContext,
+            TransactionProxy.TransactionType.WRITE_ONLY);
     }
 
     @Override
     public DOMStoreWriteTransaction newWriteOnlyTransaction() {
-        throw new UnsupportedOperationException("newWriteOnlyTransaction");
+        return new TransactionProxy(actorContext,
+            TransactionProxy.TransactionType.READ_WRITE);
     }
 
     @Override
     public void close() {
-        throw new UnsupportedOperationException("close");
+        throw new UnsupportedOperationException("close - not sure what to do here?");
     }
 }
index c9a630445b615a56c11afcd255cda5f924510ec2..32bb7d0951964975b850c8a1a685ce7d95c03f47 100644 (file)
+/*
+ * 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.cluster.datastore;
 
+import akka.actor.ActorPath;
+import akka.actor.ActorSelection;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListenableFutureTask;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicLong;
+
 /**
  * TransactionProxy acts as a proxy for one or more transactions that were created on a remote shard
- *
+ * <p>
  * Creating a transaction on the consumer side will create one instance of a transaction proxy. If during
  * the transaction reads and writes are done on data that belongs to different shards then a separate transaction will
  * be created on each of those shards by the TransactionProxy
- *
+ *</p>
+ * <p>
  * The TransactionProxy does not make any guarantees about atomicity or order in which the transactions on the various
  * shards will be executed.
- *
+ * </p>
  */
 public class TransactionProxy implements DOMStoreReadWriteTransaction {
+
+    public enum TransactionType {
+        READ_ONLY,
+        WRITE_ONLY,
+        READ_WRITE
+    }
+
+    private static final AtomicLong counter = new AtomicLong();
+
+    private final TransactionType readOnly;
+    private final ActorContext actorContext;
+    private final Map<String, ActorSelection> remoteTransactionPaths = new HashMap<>();
+    private final String identifier;
+
+    public TransactionProxy(
+        ActorContext actorContext,
+        TransactionType readOnly) {
+
+        this.identifier = "transaction-" + counter.getAndIncrement();
+        this.readOnly = readOnly;
+        this.actorContext = actorContext;
+
+        Object response = actorContext.executeShardOperation(Shard.DEFAULT_NAME, new CreateTransaction(), ActorContext.ASK_DURATION);
+        if(response instanceof CreateTransactionReply){
+            CreateTransactionReply reply = (CreateTransactionReply) response;
+            remoteTransactionPaths.put(Shard.DEFAULT_NAME, actorContext.actorSelection(reply.getTransactionPath()));
+        }
+    }
+
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("read");
+    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
+        final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
+
+        Callable<Optional<NormalizedNode<?,?>>> call = new Callable() {
+
+            @Override public Optional<NormalizedNode<?,?>> call() throws Exception {
+                Object response = actorContext
+                    .executeRemoteOperation(remoteTransaction, new ReadData(path),
+                        ActorContext.ASK_DURATION);
+                if(response instanceof ReadDataReply){
+                    ReadDataReply reply = (ReadDataReply) response;
+                    //FIXME : A cast should not be required here ???
+                    return (Optional<NormalizedNode<?, ?>>) Optional.of(reply.getNormalizedNode());
+                }
+
+                return Optional.absent();
+            }
+        };
+
+        ListenableFutureTask<Optional<NormalizedNode<?, ?>>>
+            future = ListenableFutureTask.create(call);
+
+        //FIXME : Use a thread pool here
+        Executors.newSingleThreadExecutor().submit(future);
+
+        return future;
     }
 
     @Override
     public void write(InstanceIdentifier path, NormalizedNode<?, ?> data) {
-        throw new UnsupportedOperationException("write");
+        final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
+        remoteTransaction.tell(new WriteData(path, data), null);
     }
 
     @Override
     public void merge(InstanceIdentifier path, NormalizedNode<?, ?> data) {
-        throw new UnsupportedOperationException("merge");
+        final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
+        remoteTransaction.tell(new MergeData(path, data), null);
     }
 
     @Override
     public void delete(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("delete");
+        final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
+        remoteTransaction.tell(new DeleteData(path), null);
     }
 
     @Override
     public DOMStoreThreePhaseCommitCohort ready() {
-        throw new UnsupportedOperationException("ready");
+        List<ActorPath> cohortPaths = new ArrayList<>();
+
+        for(ActorSelection remoteTransaction : remoteTransactionPaths.values()) {
+            Object result = actorContext.executeRemoteOperation(remoteTransaction,
+                new ReadyTransaction(),
+                ActorContext.ASK_DURATION
+            );
+
+            if(result instanceof ReadyTransactionReply){
+                ReadyTransactionReply reply = (ReadyTransactionReply) result;
+                cohortPaths.add(reply.getCohortPath());
+            }
+        }
+
+        return new ThreePhaseCommitCohortProxy(cohortPaths);
     }
 
     @Override
     public Object getIdentifier() {
-        throw new UnsupportedOperationException("getIdentifier");
+        return this.identifier;
     }
 
     @Override
     public void close() {
-        throw new UnsupportedOperationException("close");
+        for(ActorSelection remoteTransaction : remoteTransactionPaths.values()) {
+            remoteTransaction.tell(new CloseTransaction(), null);
+        }
+    }
+
+    private ActorSelection remoteTransactionFromIdentifier(InstanceIdentifier path){
+        String shardName = shardNameFromIdentifier(path);
+        return remoteTransactionPaths.get(shardName);
+    }
+
+    private String shardNameFromIdentifier(InstanceIdentifier path){
+        return Shard.DEFAULT_NAME;
     }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/AbortTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/AbortTransaction.java
new file mode 100644 (file)
index 0000000..4cf713a
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class AbortTransaction {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/AbortTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/AbortTransactionReply.java
new file mode 100644 (file)
index 0000000..84234e5
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class AbortTransactionReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CanCommitTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CanCommitTransaction.java
new file mode 100644 (file)
index 0000000..526d60f
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CanCommitTransaction {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CanCommitTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CanCommitTransactionReply.java
new file mode 100644 (file)
index 0000000..d143c14
--- /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.cluster.datastore.messages;
+
+public class CanCommitTransactionReply {
+  private final Boolean canCommit;
+
+  public CanCommitTransactionReply(Boolean canCommit) {
+    this.canCommit = canCommit;
+  }
+
+  public Boolean getCanCommit() {
+    return canCommit;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseDataChangeListenerRegistration.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseDataChangeListenerRegistration.java
new file mode 100644 (file)
index 0000000..c3cb00c
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CloseDataChangeListenerRegistration {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseDataChangeListenerRegistrationReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseDataChangeListenerRegistrationReply.java
new file mode 100644 (file)
index 0000000..d5c75eb
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CloseDataChangeListenerRegistrationReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransaction.java
new file mode 100644 (file)
index 0000000..6809f4b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CloseTransaction {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChain.java
new file mode 100644 (file)
index 0000000..04c422b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CloseTransactionChain {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChainReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChainReply.java
new file mode 100644 (file)
index 0000000..89fa93b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CloseTransactionChainReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionReply.java
new file mode 100644 (file)
index 0000000..4910a3e
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CloseTransactionReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CommitTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CommitTransaction.java
new file mode 100644 (file)
index 0000000..d7b210f
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CommitTransaction {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CommitTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CommitTransactionReply.java
new file mode 100644 (file)
index 0000000..a0e5e89
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CommitTransactionReply {
+}
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * 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.connector.remoterpc;
+package org.opendaylight.controller.cluster.datastore.messages;
 
-public interface RemoteRpcServer extends AutoCloseable {
+public class CreateTransaction {
 
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChain.java
new file mode 100644 (file)
index 0000000..cdad332
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class CreateTransactionChain {
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChainReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChainReply.java
new file mode 100644 (file)
index 0000000..49dd9b6
--- /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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class CreateTransactionChainReply {
+  private final ActorPath transactionChainPath;
+
+  public CreateTransactionChainReply(ActorPath transactionChainPath) {
+    this.transactionChainPath = transactionChainPath;
+  }
+
+  public ActorPath getTransactionChainPath() {
+    return transactionChainPath;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java
new file mode 100644 (file)
index 0000000..4faf9d3
--- /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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class CreateTransactionReply {
+  private final ActorPath transactionPath;
+
+  public CreateTransactionReply(ActorPath transactionPath) {
+    this.transactionPath = transactionPath;
+  }
+
+  public ActorPath getTransactionPath() {
+    return transactionPath;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataChanged.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataChanged.java
new file mode 100644 (file)
index 0000000..c55dae5
--- /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.cluster.datastore.messages;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class DataChanged {
+    private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>>
+        change;
+
+    public DataChanged(
+        AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
+        this.change = change;
+    }
+
+    public AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> getChange() {
+        return change;
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteData.java
new file mode 100644 (file)
index 0000000..384e75a
--- /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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DeleteData {
+  private final InstanceIdentifier path;
+
+  public DeleteData(InstanceIdentifier path) {
+    this.path = path;
+  }
+
+  public InstanceIdentifier getPath() {
+    return path;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteDataReply.java
new file mode 100644 (file)
index 0000000..a3c7305
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class DeleteDataReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimary.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimary.java
new file mode 100644 (file)
index 0000000..f2497e6
--- /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.cluster.datastore.messages;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * The FindPrimary message is used to locate the primary of any given shard
+ *
+ * TODO : Make this serializable
+ */
+public class FindPrimary{
+    private final String shardName;
+
+    public FindPrimary(String shardName){
+
+        Preconditions.checkNotNull(shardName, "shardName should not be null");
+
+        this.shardName = shardName;
+    }
+
+    public String getShardName() {
+        return shardName;
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ForwardedCommitTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ForwardedCommitTransaction.java
new file mode 100644 (file)
index 0000000..0104993
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.cluster.datastore.messages;
+
+import org.opendaylight.controller.cluster.datastore.modification.Modification;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+
+public class ForwardedCommitTransaction {
+  private final DOMStoreThreePhaseCommitCohort cohort;
+  private final Modification modification;
+
+  public ForwardedCommitTransaction(DOMStoreThreePhaseCommitCohort cohort, Modification modification){
+    this.cohort = cohort;
+    this.modification = modification;
+  }
+
+  public DOMStoreThreePhaseCommitCohort getCohort() {
+    return cohort;
+  }
+
+  public Modification getModification() {
+    return modification;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeData.java
new file mode 100644 (file)
index 0000000..75d1e95
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class MergeData extends ModifyData {
+  public MergeData(InstanceIdentifier path, NormalizedNode<?, ?> data) {
+    super(path, data);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeDataReply.java
new file mode 100644 (file)
index 0000000..8e90972
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class MergeDataReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ModifyData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ModifyData.java
new file mode 100644 (file)
index 0000000..da86088
--- /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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public abstract class ModifyData {
+  private final InstanceIdentifier path;
+  private final NormalizedNode<?,?> data;
+
+  public ModifyData(InstanceIdentifier path, NormalizedNode<?, ?> data) {
+    this.path = path;
+    this.data = data;
+  }
+
+  public InstanceIdentifier getPath() {
+    return path;
+  }
+
+  public NormalizedNode<?, ?> getData() {
+    return data;
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PreCommitTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PreCommitTransaction.java
new file mode 100644 (file)
index 0000000..87a9c77
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class PreCommitTransaction {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PreCommitTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PreCommitTransactionReply.java
new file mode 100644 (file)
index 0000000..f499c72
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class PreCommitTransactionReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryFound.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryFound.java
new file mode 100644 (file)
index 0000000..d6aae37
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class PrimaryFound {
+  private final String primaryPath;
+
+  public PrimaryFound(String primaryPath) {
+    this.primaryPath = primaryPath;
+  }
+
+  public String getPrimaryPath() {
+    return primaryPath;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    PrimaryFound that = (PrimaryFound) o;
+
+    if (!primaryPath.equals(that.primaryPath)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return primaryPath.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return "PrimaryFound{" +
+            "primaryPath='" + primaryPath + '\'' +
+            '}';
+  }
+
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryNotFound.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PrimaryNotFound.java
new file mode 100644 (file)
index 0000000..c66e12c
--- /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.cluster.datastore.messages;
+
+import com.google.common.base.Preconditions;
+
+public class PrimaryNotFound {
+
+    private final String shardName;
+
+    public PrimaryNotFound(String shardName){
+
+        Preconditions.checkNotNull(shardName, "shardName should not be null");
+
+        this.shardName = shardName;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        PrimaryNotFound that = (PrimaryNotFound) o;
+
+        if (shardName != null ? !shardName.equals(that.shardName) : that.shardName != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return shardName != null ? shardName.hashCode() : 0;
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadData.java
new file mode 100644 (file)
index 0000000..2f56a97
--- /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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class ReadData {
+  private final InstanceIdentifier path;
+
+  public ReadData(InstanceIdentifier path) {
+    this.path = path;
+  }
+
+  public InstanceIdentifier getPath() {
+    return path;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadDataReply.java
new file mode 100644 (file)
index 0000000..52e2c29
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class ReadDataReply {
+  private final NormalizedNode<?, ?> normalizedNode;
+
+  public ReadDataReply(NormalizedNode<?, ?> normalizedNode){
+
+    this.normalizedNode = normalizedNode;
+  }
+
+  public NormalizedNode<?, ?> getNormalizedNode() {
+    return normalizedNode;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransaction.java
new file mode 100644 (file)
index 0000000..58eef66
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class ReadyTransaction {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransactionReply.java
new file mode 100644 (file)
index 0000000..32d31bf
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class ReadyTransactionReply {
+  private final ActorPath cohortPath;
+
+  public ReadyTransactionReply(ActorPath cohortPath) {
+
+    this.cohortPath = cohortPath;
+  }
+
+  public ActorPath getCohortPath() {
+    return cohortPath;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListener.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListener.java
new file mode 100644 (file)
index 0000000..7c9e4f0
--- /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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class RegisterChangeListener {
+    private final InstanceIdentifier path;
+    private final ActorPath dataChangeListenerPath;
+    private final AsyncDataBroker.DataChangeScope scope;
+
+
+    public RegisterChangeListener(InstanceIdentifier path,
+        ActorPath dataChangeListenerPath,
+        AsyncDataBroker.DataChangeScope scope) {
+        this.path = path;
+        this.dataChangeListenerPath = dataChangeListenerPath;
+        this.scope = scope;
+    }
+
+    public InstanceIdentifier getPath() {
+        return path;
+    }
+
+
+    public AsyncDataBroker.DataChangeScope getScope() {
+        return scope;
+    }
+
+    public ActorPath getDataChangeListenerPath() {
+        return dataChangeListenerPath;
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListenerReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListenerReply.java
new file mode 100644 (file)
index 0000000..ae8bbbd
--- /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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class RegisterChangeListenerReply {
+  private final ActorPath listenerRegistrationPath;
+
+  public RegisterChangeListenerReply(ActorPath listenerRegistrationPath) {
+    this.listenerRegistrationPath = listenerRegistrationPath;
+  }
+
+  public ActorPath getListenerRegistrationPath() {
+    return listenerRegistrationPath;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/UpdateSchemaContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/UpdateSchemaContext.java
new file mode 100644 (file)
index 0000000..47f9ea8
--- /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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class UpdateSchemaContext {
+  private final SchemaContext schemaContext;
+
+  public UpdateSchemaContext(SchemaContext schemaContext) {
+    this.schemaContext = schemaContext;
+  }
+
+  public SchemaContext getSchemaContext() {
+    return schemaContext;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteData.java
new file mode 100644 (file)
index 0000000..1348e65
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class WriteData extends ModifyData{
+
+  public WriteData(InstanceIdentifier path, NormalizedNode<?, ?> data) {
+    super(path, data);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteDataReply.java
new file mode 100644 (file)
index 0000000..2a2b4ed
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.cluster.datastore.messages;
+
+public class WriteDataReply {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/AbstractModification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/AbstractModification.java
new file mode 100644 (file)
index 0000000..5d9f962
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.cluster.datastore.modification;
+
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.io.Serializable;
+
+/**
+ * Base class to be used for all simple modifications that can be applied to a DOMStoreTransaction
+ */
+public abstract class AbstractModification implements Modification,
+    Serializable {
+
+    private static final long serialVersionUID = 1638042650152084457L;
+
+    protected final InstanceIdentifier path;
+
+    protected AbstractModification(InstanceIdentifier path) {
+        this.path = path;
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/CompositeModification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/CompositeModification.java
new file mode 100644 (file)
index 0000000..4c856d3
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.cluster.datastore.modification;
+
+import java.util.List;
+
+/**
+ * CompositeModification contains a list of modifications that need to be applied to the DOMStore
+ * <p>
+ * A CompositeModification gets stored in the transaction log for a Shard. During recovery when the transaction log
+ * is being replayed a DOMStoreWriteTransaction could be created and a CompositeModification could be applied to it.
+ * </p>
+ */
+public interface CompositeModification extends Modification {
+    /**
+     * Get a list of Modifications contained by this Composite
+     * @return
+     */
+    List<Modification> getModifications();
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/DeleteModification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/DeleteModification.java
new file mode 100644 (file)
index 0000000..063ec3e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.cluster.datastore.modification;
+
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+/**
+ * DeleteModification store all the parameters required to delete a path from the data tree
+ */
+public class DeleteModification extends AbstractModification {
+  public DeleteModification(InstanceIdentifier path) {
+    super(path);
+  }
+
+  @Override
+  public void apply(DOMStoreWriteTransaction transaction) {
+    transaction.delete(path);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/ImmutableCompositeModification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/ImmutableCompositeModification.java
new file mode 100644 (file)
index 0000000..5a15d76
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.cluster.datastore.modification;
+
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+
+import java.util.List;
+
+public class ImmutableCompositeModification implements CompositeModification{
+
+  private final CompositeModification modification;
+
+  public ImmutableCompositeModification(CompositeModification modification){
+    this.modification = modification;
+  }
+
+  @Override
+  public List<Modification> getModifications() {
+    return modification.getModifications();
+  }
+
+  @Override
+  public void apply(DOMStoreWriteTransaction transaction) {
+    modification.apply(transaction);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/MergeModification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/MergeModification.java
new file mode 100644 (file)
index 0000000..0457a78
--- /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.cluster.datastore.modification;
+
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * MergeModification stores all the parameters required to merge data into the specified path
+ */
+public class MergeModification extends AbstractModification{
+  private final NormalizedNode data;
+
+
+  public MergeModification(InstanceIdentifier path, NormalizedNode data) {
+    super(path);
+    this.data = data;
+  }
+
+  @Override
+  public void apply(DOMStoreWriteTransaction transaction) {
+    transaction.merge(path, data);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/Modification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/Modification.java
new file mode 100644 (file)
index 0000000..60dbf0f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.cluster.datastore.modification;
+
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+
+/**
+ * Represents a modification to the data store.
+ * <p>
+ * Simple modifications can be of type,
+ * <li> {@link org.opendaylight.controller.cluster.datastore.modification.WriteModification}
+ * <li> {@link org.opendaylight.controller.cluster.datastore.modification.MergeModification}
+ * <li> {@link org.opendaylight.controller.cluster.datastore.modification.DeleteModification}
+ * </p>
+ *
+ * <p>
+ * Modifications can in turn be lumped into a single {@link org.opendaylight.controller.cluster.datastore.modification.CompositeModification}
+ * which can then be applied to a write transaction
+ * </p>
+ */
+public interface Modification {
+  /**
+   * Apply the modification to the specified transaction
+   * @param transaction
+   */
+  void apply(DOMStoreWriteTransaction transaction);
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModification.java
new file mode 100644 (file)
index 0000000..9f37ba4
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.cluster.datastore.modification;
+
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * MutableCompositeModification is just a mutable version of a
+ * CompositeModification {@link org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification#addModification(Modification)}
+ */
+public class MutableCompositeModification
+    implements CompositeModification, Serializable {
+
+    private static final long serialVersionUID = 1163377899140186790L;
+
+    private final List<Modification> modifications = new ArrayList<>();
+
+    @Override
+    public void apply(DOMStoreWriteTransaction transaction) {
+        for (Modification modification : modifications) {
+            modification.apply(transaction);
+        }
+    }
+
+    /**
+     * Add a new Modification to the list of Modifications represented by this
+     * composite
+     *
+     * @param modification
+     */
+    public void addModification(Modification modification) {
+        modifications.add(modification);
+    }
+
+    public List<Modification> getModifications() {
+        return Collections.unmodifiableList(modifications);
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/WriteModification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/modification/WriteModification.java
new file mode 100644 (file)
index 0000000..1b2a87f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.cluster.datastore.modification;
+
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * WriteModification stores all the parameters required to write data to the specified path
+ */
+public class WriteModification extends AbstractModification {
+
+  private final NormalizedNode data;
+
+  public WriteModification(InstanceIdentifier path, NormalizedNode data) {
+    super(path);
+    this.data = data;
+  }
+
+  @Override
+  public void apply(DOMStoreWriteTransaction transaction) {
+    transaction.write(path, data);
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategy.java
new file mode 100644 (file)
index 0000000..a8ab5c4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.cluster.datastore.shardstrategy;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+/**
+ * The DefaultShardStrategy basically puts all data into the default Shard
+ * <p>
+ *   The default shard stores data for all modules for which a specific set of shards has not been configured
+ * </p>
+ */
+public class DefaultShardStrategy implements ShardStrategy{
+
+  public static final String NAME = "default";
+  public static final String DEFAULT_SHARD = "default";
+
+  @Override
+  public String findShard(InstanceIdentifier path) {
+    return DEFAULT_SHARD;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java
new file mode 100644 (file)
index 0000000..f75eb2d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.cluster.datastore.shardstrategy;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+/**
+ * The role of ShardStrategy is to figure out which Shards a given piece of data belongs to
+ */
+public interface ShardStrategy {
+  /**
+   * Find the name of the shard in which the data pointed to by the specified path belongs in
+   *
+   * @param path The location of the data in the logical tree
+   * @return
+   */
+  String findShard(InstanceIdentifier path);
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactory.java
new file mode 100644 (file)
index 0000000..2105379
--- /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.cluster.datastore.shardstrategy;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ShardStrategyFactory {
+  private static final Map<String, ShardStrategy> moduleNameToStrategyMap = new ConcurrentHashMap();
+
+  private static final String UNKNOWN_MODULE_NAME = "unknown";
+
+  public static ShardStrategy getStrategy(InstanceIdentifier path){
+    Preconditions.checkNotNull(path, "path should not be null");
+
+    String moduleName = getModuleName(path);
+    ShardStrategy shardStrategy = moduleNameToStrategyMap.get(moduleName);
+    if(shardStrategy == null){
+      return new DefaultShardStrategy();
+    }
+
+    return shardStrategy;
+  }
+
+
+  private static String getModuleName(InstanceIdentifier path){
+    return UNKNOWN_MODULE_NAME;
+  }
+
+  /**
+   * This is to be used in the future to register a custom shard strategy
+   *
+   * @param moduleName
+   * @param shardStrategy
+   */
+  public static void registerShardStrategy(String moduleName, ShardStrategy shardStrategy){
+    throw new UnsupportedOperationException("registering a custom shard strategy not supported yet");
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java
new file mode 100644 (file)
index 0000000..ba4d4de
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 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.cluster.datastore.utils;
+
+import akka.actor.ActorPath;
+import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
+import akka.actor.ActorSystem;
+import akka.util.Timeout;
+import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
+import scala.concurrent.duration.FiniteDuration;
+
+import java.util.concurrent.TimeUnit;
+
+import static akka.pattern.Patterns.ask;
+
+/**
+ * The ActorContext class contains utility methods which could be used by
+ * non-actors (like DistributedDataStore) to work with actors a little more
+ * easily. An ActorContext can be freely passed around to local object instances
+ * but should not be passed to actors especially remote actors
+ */
+public class ActorContext {
+    private static final Logger
+        LOG = LoggerFactory.getLogger(ActorContext.class);
+
+    public static final FiniteDuration ASK_DURATION = Duration.create(5, TimeUnit.SECONDS);
+    public static final Duration AWAIT_DURATION = Duration.create(5, TimeUnit.SECONDS);
+
+    private final ActorSystem actorSystem;
+    private final ActorRef shardManager;
+
+    public ActorContext(ActorSystem actorSystem, ActorRef shardManager){
+        this.actorSystem = actorSystem;
+        this.shardManager = shardManager;
+    }
+
+    public ActorSystem getActorSystem() {
+        return actorSystem;
+    }
+
+    public ActorRef getShardManager() {
+        return shardManager;
+    }
+
+    public ActorSelection actorSelection(String actorPath){
+        return actorSystem.actorSelection(actorPath);
+    }
+
+    public ActorSelection actorSelection(ActorPath actorPath){
+        return actorSystem.actorSelection(actorPath);
+    }
+
+
+    /**
+     * Finds the primary for a given shard
+     *
+     * @param shardName
+     * @return
+     */
+    public ActorSelection findPrimary(String shardName) {
+        Object result = executeLocalOperation(shardManager,
+            new FindPrimary(shardName), ASK_DURATION);
+
+        if(result instanceof PrimaryFound){
+            PrimaryFound found = (PrimaryFound) result;
+
+            LOG.error("Primary found {}", found.getPrimaryPath());
+
+            return actorSystem.actorSelection(found.getPrimaryPath());
+        }
+        throw new RuntimeException("primary was not found");
+    }
+
+    /**
+     * Executes an operation on a local actor and wait for it's response
+     * @param actor
+     * @param message
+     * @param duration
+     * @return The response of the operation
+     */
+    public Object executeLocalOperation(ActorRef actor, Object message,
+        FiniteDuration duration){
+        Future<Object> future =
+            ask(actor, message, new Timeout(duration));
+
+        try {
+            return Await.result(future, AWAIT_DURATION);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Execute an operation on a remote actor and wait for it's response
+     * @param actor
+     * @param message
+     * @param duration
+     * @return
+     */
+    public Object executeRemoteOperation(ActorSelection actor, Object message,
+        FiniteDuration duration){
+        Future<Object> future =
+            ask(actor, message, new Timeout(duration));
+
+        try {
+            return Await.result(future, AWAIT_DURATION);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Execute an operation on the primary for a given shard
+     * <p>
+     *     This method first finds the primary for a given shard ,then sends
+     *     the message to the remote shard and waits for a response
+     * </p>
+     * @param shardName
+     * @param message
+     * @param duration
+     * @throws java.lang.RuntimeException when a primary is not found or if the message to the remote shard fails or times out
+     *
+     * @return
+     */
+    public Object executeShardOperation(String shardName, Object message, FiniteDuration duration){
+        ActorSelection primary = findPrimary(shardName);
+
+        return executeRemoteOperation(primary, message, duration);
+    }
+
+}
index 241bcb0a41654987835c249374c0c953d83e8814..3a78f93d8d18874e56386422771e322ac2d34581 100644 (file)
@@ -1,34 +1,36 @@
 package org.opendaylight.controller.config.yang.config.distributed_datastore_provider;
 
+import akka.actor.ActorSystem;
 import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
 
 public class DistributedDataStoreProviderModule extends org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedDataStoreProviderModule {
-    public DistributedDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-        super(identifier, dependencyResolver);
+  public DistributedDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    super(identifier, dependencyResolver);
+  }
+
+  public DistributedDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.distributed_datastore_provider.DistributedDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+    super(identifier, dependencyResolver, oldModule, oldInstance);
+  }
+
+  @Override
+  public void customValidation() {
+    // add custom validation form module attributes here.
+  }
+
+  @Override
+  public java.lang.AutoCloseable createInstance() {
+    ActorSystem actorSystem = ActorSystem.create("opendaylight-cluster");
+    final DistributedDataStore configurationStore = new DistributedDataStore(actorSystem, "config");
+    final DistributedDataStore operationalStore = new DistributedDataStore(actorSystem, "operational");
+
+    final class AutoCloseableDistributedDataStore implements AutoCloseable {
+
+      @Override
+      public void close() throws Exception {
+      }
     }
 
-    public DistributedDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.distributed_datastore_provider.DistributedDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
-        super(identifier, dependencyResolver, oldModule, oldInstance);
-    }
-
-    @Override
-    public void customValidation() {
-        // add custom validation form module attributes here.
-    }
-
-    @Override
-    public java.lang.AutoCloseable createInstance() {
-        new DistributedDataStore();
-
-        final class AutoCloseableDistributedDataStore implements AutoCloseable {
-
-            @Override
-            public void close() throws Exception {
-
-            }
-        }
-
-        return new AutoCloseableDistributedDataStore();
-    }
+    return new AutoCloseableDistributedDataStore();
+  }
 
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java
new file mode 100644 (file)
index 0000000..45ef32f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorSystem;
+import akka.testkit.JavaTestKit;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public abstract class AbstractActorTest {
+  private static ActorSystem system;
+
+  @BeforeClass
+  public static void setUpClass(){
+    system = ActorSystem.create("test");
+  }
+
+  @AfterClass
+  public static void tearDownClass(){
+    JavaTestKit.shutdownActorSystem(system);
+    system = null;
+  }
+
+  protected ActorSystem getSystem(){
+    return system;
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java
new file mode 100644 (file)
index 0000000..8c3ec82
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * 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.cluster.datastore;
+
+import akka.actor.ActorPath;
+import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CommitTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+public class BasicIntegrationTest extends AbstractActorTest {
+
+    @Test
+    public void integrationTest() {
+        // This test will
+        // - create a Shard
+        // - initiate a transaction
+        // - write something
+        // - read the transaction for commit
+        // - commit the transaction
+
+
+        new JavaTestKit(getSystem()) {{
+            final Props props = Shard.props("config");
+            final ActorRef shard = getSystem().actorOf(props);
+
+            new Within(duration("5 seconds")) {
+                protected void run() {
+
+                    shard.tell(
+                        new UpdateSchemaContext(TestModel.createTestContext()),
+                        getRef());
+
+                    shard.tell(new CreateTransactionChain(), getRef());
+
+                    final ActorSelection transactionChain =
+                        new ExpectMsg<ActorSelection>("match hint") {
+                            protected ActorSelection match(Object in) {
+                                if (in instanceof CreateTransactionChainReply) {
+                                    ActorPath transactionChainPath =
+                                        ((CreateTransactionChainReply) in)
+                                            .getTransactionChainPath();
+                                    return getSystem()
+                                        .actorSelection(transactionChainPath);
+                                } else {
+                                    throw noMatch();
+                                }
+                            }
+                        }.get(); // this extracts the received message
+
+                    Assert.assertNotNull(transactionChain);
+
+                    transactionChain.tell(new CreateTransaction(), getRef());
+
+                    final ActorSelection transaction =
+                        new ExpectMsg<ActorSelection>("match hint") {
+                            protected ActorSelection match(Object in) {
+                                if (in instanceof CreateTransactionReply) {
+                                    ActorPath transactionPath =
+                                        ((CreateTransactionReply) in)
+                                            .getTransactionPath();
+                                    return getSystem()
+                                        .actorSelection(transactionPath);
+                                } else {
+                                    throw noMatch();
+                                }
+                            }
+                        }.get(); // this extracts the received message
+
+                    Assert.assertNotNull(transaction);
+
+                    transaction.tell(new WriteData(TestModel.TEST_PATH,
+                        ImmutableNodes.containerNode(TestModel.TEST_QNAME)),
+                        getRef());
+
+                    Boolean writeDone = new ExpectMsg<Boolean>("match hint") {
+                        protected Boolean match(Object in) {
+                            if (in instanceof WriteDataReply) {
+                                return true;
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    Assert.assertTrue(writeDone);
+
+                    transaction.tell(new ReadyTransaction(), getRef());
+
+                    final ActorSelection cohort =
+                        new ExpectMsg<ActorSelection>("match hint") {
+                            protected ActorSelection match(Object in) {
+                                if (in instanceof ReadyTransactionReply) {
+                                    ActorPath cohortPath =
+                                        ((ReadyTransactionReply) in)
+                                            .getCohortPath();
+                                    return getSystem()
+                                        .actorSelection(cohortPath);
+                                } else {
+                                    throw noMatch();
+                                }
+                            }
+                        }.get(); // this extracts the received message
+
+                    Assert.assertNotNull(cohort);
+
+                    cohort.tell(new PreCommitTransaction(), getRef());
+
+                    Boolean preCommitDone =
+                        new ExpectMsg<Boolean>("match hint") {
+                            protected Boolean match(Object in) {
+                                if (in instanceof PreCommitTransactionReply) {
+                                    return true;
+                                } else {
+                                    throw noMatch();
+                                }
+                            }
+                        }.get(); // this extracts the received message
+
+                    Assert.assertTrue(preCommitDone);
+
+                    cohort.tell(new CommitTransaction(), getRef());
+
+                    final Boolean commitDone =
+                        new ExpectMsg<Boolean>("match hint") {
+                            protected Boolean match(Object in) {
+                                if (in instanceof CommitTransactionReply) {
+                                    return true;
+                                } else {
+                                    throw noMatch();
+                                }
+                            }
+                        }.get(); // this extracts the received message
+
+                    Assert.assertTrue(commitDone);
+
+                }
+
+
+            };
+        }};
+
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxyTest.java
new file mode 100644 (file)
index 0000000..a8409a6
--- /dev/null
@@ -0,0 +1,81 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import org.opendaylight.controller.cluster.datastore.utils.DoNothingActor;
+import org.opendaylight.controller.cluster.datastore.utils.MessageCollectorActor;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class DataChangeListenerProxyTest extends AbstractActorTest {
+
+    private static class MockDataChangeEvent implements
+        AsyncDataChangeEvent<InstanceIdentifier,NormalizedNode<?,?>> {
+
+        @Override
+        public Map<InstanceIdentifier, NormalizedNode<?, ?>> getCreatedData() {
+            throw new UnsupportedOperationException("getCreatedData");
+        }
+
+        @Override
+        public Map<InstanceIdentifier, NormalizedNode<?, ?>> getUpdatedData() {
+            throw new UnsupportedOperationException("getUpdatedData");
+        }
+
+        @Override public Set<InstanceIdentifier> getRemovedPaths() {
+            throw new UnsupportedOperationException("getRemovedPaths");
+        }
+
+        @Override
+        public Map<InstanceIdentifier, ? extends NormalizedNode<?, ?>> getOriginalData() {
+            throw new UnsupportedOperationException("getOriginalData");
+        }
+
+        @Override public NormalizedNode<?, ?> getOriginalSubtree() {
+            throw new UnsupportedOperationException("getOriginalSubtree");
+        }
+
+        @Override public NormalizedNode<?, ?> getUpdatedSubtree() {
+            throw new UnsupportedOperationException("getUpdatedSubtree");
+        }
+    }
+
+    @Test
+    public void testOnDataChanged() throws Exception {
+        final Props props = Props.create(MessageCollectorActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        DataChangeListenerProxy dataChangeListenerProxy =
+            new DataChangeListenerProxy(
+                getSystem().actorSelection(actorRef.path()));
+
+        dataChangeListenerProxy.onDataChanged(new MockDataChangeEvent());
+
+        //Check if it was received by the remote actor
+        ActorContext
+            testContext = new ActorContext(getSystem(), getSystem().actorOf(Props.create(DoNothingActor.class)));
+        Object messages = testContext
+            .executeLocalOperation(actorRef, "messages",
+                ActorContext.ASK_DURATION);
+
+        Assert.assertNotNull(messages);
+
+        Assert.assertTrue(messages instanceof List);
+
+        List<Object> listMessages = (List<Object>) messages;
+
+        Assert.assertEquals(1, listMessages.size());
+
+        Assert.assertTrue(listMessages.get(0) instanceof DataChanged);
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationProxyTest.java
new file mode 100644 (file)
index 0000000..be7be17
--- /dev/null
@@ -0,0 +1,74 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistration;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import org.opendaylight.controller.cluster.datastore.utils.DoNothingActor;
+import org.opendaylight.controller.cluster.datastore.utils.MessageCollectorActor;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.List;
+
+public class DataChangeListenerRegistrationProxyTest extends AbstractActorTest{
+
+    private static class MockDataChangeListener implements
+        AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> {
+
+        @Override public void onDataChanged(
+            AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
+            throw new UnsupportedOperationException("onDataChanged");
+        }
+    }
+
+    @Test
+    public void testGetInstance() throws Exception {
+        final Props props = Props.create(MessageCollectorActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        MockDataChangeListener listener =
+            new MockDataChangeListener();
+        DataChangeListenerRegistrationProxy proxy =
+            new DataChangeListenerRegistrationProxy(
+                getSystem().actorSelection(actorRef.path()),
+                listener);
+
+        Assert.assertEquals(listener, proxy.getInstance());
+
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        final Props props = Props.create(MessageCollectorActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        DataChangeListenerRegistrationProxy proxy =
+            new DataChangeListenerRegistrationProxy(
+                getSystem().actorSelection(actorRef.path()),
+                new MockDataChangeListener());
+
+        proxy.close();
+
+        //Check if it was received by the remote actor
+        ActorContext
+            testContext = new ActorContext(getSystem(), getSystem().actorOf(Props.create(DoNothingActor.class)));
+        Object messages = testContext
+            .executeLocalOperation(actorRef, "messages",
+                ActorContext.ASK_DURATION);
+
+        Assert.assertNotNull(messages);
+
+        Assert.assertTrue(messages instanceof List);
+
+        List<Object> listMessages = (List<Object>) messages;
+
+        Assert.assertEquals(1, listMessages.size());
+
+        Assert.assertTrue(listMessages.get(0) instanceof CloseDataChangeListenerRegistration);
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationTest.java
new file mode 100644 (file)
index 0000000..23302b5
--- /dev/null
@@ -0,0 +1,74 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistration;
+import org.opendaylight.controller.cluster.datastore.messages.CloseDataChangeListenerRegistrationReply;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+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.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import static org.junit.Assert.assertEquals;
+
+public class DataChangeListenerRegistrationTest extends AbstractActorTest {
+  private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
+
+  private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor);
+
+  static {
+    store.onGlobalContextUpdated(TestModel.createTestContext());
+  }
+
+
+  @Test
+  public void testOnReceiveCloseListenerRegistration() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final Props props = DataChangeListenerRegistration.props(store
+          .registerChangeListener(TestModel.TEST_PATH, noOpDataChangeListener(),
+              AsyncDataBroker.DataChangeScope.BASE));
+      final ActorRef subject = getSystem().actorOf(props, "testCloseListenerRegistration");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new CloseDataChangeListenerRegistration(), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof CloseDataChangeListenerRegistrationReply) {
+                return "match";
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+  private  AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> noOpDataChangeListener(){
+    return new AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>() {
+      @Override
+      public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
+
+      }
+    };
+  }
+
+}
index 6544f3303022b698580d24f350073e5a79fa7b55..3a74a4ca7656dc01ae650d011595335474297de1 100644 (file)
@@ -1,6 +1,13 @@
 package org.opendaylight.controller.cluster.datastore;
 
+import akka.actor.ActorRef;
+import akka.actor.Props;
 import junit.framework.Assert;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
+import org.opendaylight.controller.cluster.datastore.utils.DoNothingActor;
+import org.opendaylight.controller.cluster.datastore.utils.MockActorContext;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
 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.AsyncDataChangeListener;
@@ -12,13 +19,27 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
-public class DistributedDataStoreTest {
+public class DistributedDataStoreTest extends AbstractActorTest{
 
     private DistributedDataStore distributedDataStore;
+    private MockActorContext mockActorContext;
+    private ActorRef doNothingActorRef;
 
     @org.junit.Before
     public void setUp() throws Exception {
-        distributedDataStore = new DistributedDataStore();
+        final Props props = Props.create(DoNothingActor.class);
+
+        doNothingActorRef = getSystem().actorOf(props);
+
+        mockActorContext = new MockActorContext(getSystem(), doNothingActorRef);
+        distributedDataStore = new DistributedDataStore(mockActorContext, "config");
+        distributedDataStore.onGlobalContextUpdated(
+            TestModel.createTestContext());
+
+        // Make CreateTransactionReply as the default response. Will need to be
+        // tuned if a specific test requires some other response
+        mockActorContext.setExecuteShardOperationResponse(
+            new CreateTransactionReply(doNothingActorRef.path()));
     }
 
     @org.junit.After
@@ -28,8 +49,9 @@ public class DistributedDataStoreTest {
 
     @org.junit.Test
     public void testRegisterChangeListener() throws Exception {
+        mockActorContext.setExecuteShardOperationResponse(new RegisterChangeListenerReply(doNothingActorRef.path()));
         ListenerRegistration registration =
-                distributedDataStore.registerChangeListener(InstanceIdentifier.builder().build(), new AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>() {
+                distributedDataStore.registerChangeListener(TestModel.TEST_PATH, new AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>() {
             @Override
             public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
                 throw new UnsupportedOperationException("onDataChanged");
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardManagerTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardManagerTest.java
new file mode 100644 (file)
index 0000000..fa436c1
--- /dev/null
@@ -0,0 +1,70 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
+import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
+import scala.concurrent.duration.Duration;
+
+public class ShardManagerTest {
+    private static ActorSystem system;
+
+    @BeforeClass
+    public static void setUp(){
+        system = ActorSystem.create("test");
+    }
+
+    @AfterClass
+    public static void tearDown(){
+        JavaTestKit.shutdownActorSystem(system);
+        system = null;
+    }
+
+    @Test
+    public void testOnReceiveFindPrimaryForNonExistentShard() throws Exception {
+
+        new JavaTestKit(system) {{
+            final Props props = ShardManager.props("config");
+            final TestActorRef<ShardManager> subject = TestActorRef.create(system, props);
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    subject.tell(new FindPrimary("inventory"), getRef());
+
+                    expectMsgEquals(Duration.Zero(), new PrimaryNotFound("inventory"));
+
+                    // Will wait for the rest of the 3 seconds
+                    expectNoMsg();
+                }
+            };
+        }};
+    }
+
+  @Test
+  public void testOnReceiveFindPrimaryForExistentShard() throws Exception {
+
+    new JavaTestKit(system) {{
+      final Props props = ShardManager.props("config");
+      final TestActorRef<ShardManager> subject = TestActorRef.create(system, props);
+
+      // the run() method needs to finish within 3 seconds
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new FindPrimary(Shard.DEFAULT_NAME), getRef());
+
+          expectMsgClass(PrimaryFound.class);
+
+          expectNoMsg();
+        }
+      };
+    }};
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java
new file mode 100644 (file)
index 0000000..48365fa
--- /dev/null
@@ -0,0 +1,100 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+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.AsyncDataChangeListener;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import static org.junit.Assert.assertTrue;
+
+public class ShardTest extends AbstractActorTest{
+  @Test
+  public void testOnReceiveCreateTransactionChain() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final Props props = Shard.props("config");
+      final ActorRef subject = getSystem().actorOf(props, "testCreateTransactionChain");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new CreateTransactionChain(), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof CreateTransactionChainReply) {
+                CreateTransactionChainReply reply = (CreateTransactionChainReply) in;
+                return reply.getTransactionChainPath().toString();
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertTrue(out.matches("akka:\\/\\/test\\/user\\/testCreateTransactionChain\\/\\$.*"));
+          // Will wait for the rest of the 3 seconds
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+  @Test
+  public void testOnReceiveRegisterListener() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final Props props = Shard.props("config");
+      final ActorRef subject = getSystem().actorOf(props, "testRegisterChangeListener");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new UpdateSchemaContext(TestModel.createTestContext()), getRef());
+
+          subject.tell(new RegisterChangeListener(TestModel.TEST_PATH, getRef().path() , AsyncDataBroker.DataChangeScope.BASE), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof RegisterChangeListenerReply) {
+                RegisterChangeListenerReply reply = (RegisterChangeListenerReply) in;
+                return reply.getListenerRegistrationPath().toString();
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertTrue(out.matches("akka:\\/\\/test\\/user\\/testRegisterChangeListener\\/\\$.*"));
+          // Will wait for the rest of the 3 seconds
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+
+
+  private  AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> noOpDataChangeListener(){
+    return new AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>() {
+      @Override
+      public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
+
+      }
+    };
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java
new file mode 100644 (file)
index 0000000..bc3a104
--- /dev/null
@@ -0,0 +1,91 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ShardTransactionChainTest extends AbstractActorTest {
+
+  private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
+
+  private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor);
+
+  static {
+    store.onGlobalContextUpdated(TestModel.createTestContext());
+  }
+  @Test
+  public void testOnReceiveCreateTransaction() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final Props props = ShardTransactionChain.props(store.createTransactionChain());
+      final ActorRef subject = getSystem().actorOf(props, "testCreateTransaction");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new CreateTransaction(), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof CreateTransactionReply) {
+                return ((CreateTransactionReply) in).getTransactionPath().toString();
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertTrue(out.matches("akka:\\/\\/test\\/user\\/testCreateTransaction\\/\\$.*"));
+          // Will wait for the rest of the 3 seconds
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+  @Test
+  public void testOnReceiveCloseTransactionChain() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final Props props = ShardTransactionChain.props(store.createTransactionChain());
+      final ActorRef subject = getSystem().actorOf(props, "testCloseTransactionChain");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new CloseTransactionChain(), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof CloseTransactionChainReply) {
+                return "match";
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+          // Will wait for the rest of the 3 seconds
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
new file mode 100644 (file)
index 0000000..9116f24
--- /dev/null
@@ -0,0 +1,277 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
+import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
+import org.opendaylight.controller.cluster.datastore.modification.DeleteModification;
+import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
+import org.opendaylight.controller.cluster.datastore.modification.Modification;
+import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ShardTransactionTest extends AbstractActorTest {
+  private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
+
+  private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor);
+
+  static {
+    store.onGlobalContextUpdated(TestModel.createTestContext());
+  }
+
+  @Test
+  public void testOnReceiveReadData() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+      final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard);
+      final ActorRef subject = getSystem().actorOf(props, "testReadData");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new ReadData(InstanceIdentifier.builder().build()), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof ReadDataReply) {
+                if (((ReadDataReply) in).getNormalizedNode() != null) {
+                  return "match";
+                }
+                return null;
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+  private void assertModification(final ActorRef subject, final Class<? extends Modification> modificationType){
+    new JavaTestKit(getSystem()) {{
+      new Within(duration("1 seconds")) {
+        protected void run() {
+          subject.tell(new ShardTransaction.GetCompositedModification(), getRef());
+
+          final CompositeModification compositeModification = new ExpectMsg<CompositeModification>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected CompositeModification match(Object in) {
+              if (in instanceof ShardTransaction.GetCompositeModificationReply) {
+                return ((ShardTransaction.GetCompositeModificationReply) in).getModification();
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertTrue(compositeModification.getModifications().size() == 1);
+          assertEquals(modificationType, compositeModification.getModifications().get(0).getClass());
+
+        }
+      };
+    }};
+  }
+
+  @Test
+  public void testOnReceiveWriteData() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+      final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard);
+      final ActorRef subject = getSystem().actorOf(props, "testWriteData");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new WriteData(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof WriteDataReply) {
+                return "match";
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+
+          assertModification(subject, WriteModification.class);
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+  @Test
+  public void testOnReceiveMergeData() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+      final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard);
+      final ActorRef subject = getSystem().actorOf(props, "testMergeData");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new MergeData(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof MergeDataReply) {
+                return "match";
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+
+          assertModification(subject, MergeModification.class);
+
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+  @Test
+  public void testOnReceiveDeleteData() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+      final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard);
+      final ActorRef subject = getSystem().actorOf(props, "testDeleteData");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new DeleteData(TestModel.TEST_PATH), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof DeleteDataReply) {
+                return "match";
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+
+          assertModification(subject, DeleteModification.class);
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+  }
+
+
+  @Test
+  public void testOnReceiveReadyTransaction() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+      final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard);
+      final ActorRef subject = getSystem().actorOf(props, "testReadyTransaction");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new ReadyTransaction(), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof ReadyTransactionReply) {
+                return "match";
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+
+  }
+
+  @Test
+  public void testOnReceiveCloseTransaction() throws Exception {
+    new JavaTestKit(getSystem()) {{
+      final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+      final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard);
+      final ActorRef subject = getSystem().actorOf(props, "testCloseTransaction");
+
+      new Within(duration("1 seconds")) {
+        protected void run() {
+
+          subject.tell(new CloseTransaction(), getRef());
+
+          final String out = new ExpectMsg<String>("match hint") {
+            // do not put code outside this method, will run afterwards
+            protected String match(Object in) {
+              if (in instanceof CloseTransactionReply) {
+                return "match";
+              } else {
+                throw noMatch();
+              }
+            }
+          }.get(); // this extracts the received message
+
+          assertEquals("match", out);
+
+          expectNoMsg();
+        }
+
+
+      };
+    }};
+
+  }
+
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java
new file mode 100644 (file)
index 0000000..6d057a4
--- /dev/null
@@ -0,0 +1,225 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import org.opendaylight.controller.cluster.datastore.utils.DoNothingActor;
+import org.opendaylight.controller.cluster.datastore.utils.MessageCollectorActor;
+import org.opendaylight.controller.cluster.datastore.utils.MockActorContext;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+import java.util.List;
+
+public class TransactionProxyTest extends AbstractActorTest {
+
+    @Test
+    public void testRead() throws Exception {
+        final Props props = Props.create(DoNothingActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteShardOperationResponse(new CreateTransactionReply(actorRef.path()));
+        actorContext.setExecuteRemoteOperationResponse("message");
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY);
+
+
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> read =
+            transactionProxy.read(TestModel.TEST_PATH);
+
+        Optional<NormalizedNode<?, ?>> normalizedNodeOptional = read.get();
+
+        Assert.assertFalse(normalizedNodeOptional.isPresent());
+
+        actorContext.setExecuteRemoteOperationResponse(new ReadDataReply(
+            ImmutableNodes.containerNode(TestModel.TEST_QNAME)));
+
+        read = transactionProxy.read(TestModel.TEST_PATH);
+
+        normalizedNodeOptional = read.get();
+
+        Assert.assertTrue(normalizedNodeOptional.isPresent());
+    }
+
+    @Test
+    public void testWrite() throws Exception {
+        final Props props = Props.create(MessageCollectorActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteShardOperationResponse(new CreateTransactionReply(actorRef.path()));
+        actorContext.setExecuteRemoteOperationResponse("message");
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY);
+
+        transactionProxy.write(TestModel.TEST_PATH,
+            ImmutableNodes.containerNode(TestModel.NAME_QNAME));
+
+        ActorContext testContext = new ActorContext(getSystem(), getSystem().actorOf(Props.create(DoNothingActor.class)));
+        Object messages = testContext
+            .executeLocalOperation(actorRef, "messages",
+                ActorContext.ASK_DURATION);
+
+        Assert.assertNotNull(messages);
+
+        Assert.assertTrue(messages instanceof List);
+
+        List<Object> listMessages = (List<Object>) messages;
+
+        Assert.assertEquals(1, listMessages.size());
+
+        Assert.assertTrue(listMessages.get(0) instanceof WriteData);
+    }
+
+    @Test
+    public void testMerge() throws Exception {
+        final Props props = Props.create(MessageCollectorActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteShardOperationResponse(new CreateTransactionReply(actorRef.path()));
+        actorContext.setExecuteRemoteOperationResponse("message");
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY);
+
+        transactionProxy.merge(TestModel.TEST_PATH,
+            ImmutableNodes.containerNode(TestModel.NAME_QNAME));
+
+        ActorContext testContext = new ActorContext(getSystem(), getSystem().actorOf(Props.create(DoNothingActor.class)));
+        Object messages = testContext
+            .executeLocalOperation(actorRef, "messages",
+                ActorContext.ASK_DURATION);
+
+        Assert.assertNotNull(messages);
+
+        Assert.assertTrue(messages instanceof List);
+
+        List<Object> listMessages = (List<Object>) messages;
+
+        Assert.assertEquals(1, listMessages.size());
+
+        Assert.assertTrue(listMessages.get(0) instanceof MergeData);
+    }
+
+    @Test
+    public void testDelete() throws Exception {
+        final Props props = Props.create(MessageCollectorActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteShardOperationResponse(new CreateTransactionReply(actorRef.path()));
+        actorContext.setExecuteRemoteOperationResponse("message");
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY);
+
+        transactionProxy.delete(TestModel.TEST_PATH);
+
+        ActorContext testContext = new ActorContext(getSystem(), getSystem().actorOf(Props.create(DoNothingActor.class)));
+        Object messages = testContext
+            .executeLocalOperation(actorRef, "messages",
+                ActorContext.ASK_DURATION);
+
+        Assert.assertNotNull(messages);
+
+        Assert.assertTrue(messages instanceof List);
+
+        List<Object> listMessages = (List<Object>) messages;
+
+        Assert.assertEquals(1, listMessages.size());
+
+        Assert.assertTrue(listMessages.get(0) instanceof DeleteData);
+    }
+
+    @Test
+    public void testReady() throws Exception {
+        final Props props = Props.create(DoNothingActor.class);
+        final ActorRef doNothingActorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteShardOperationResponse(new CreateTransactionReply(doNothingActorRef.path()));
+        actorContext.setExecuteRemoteOperationResponse(new ReadyTransactionReply(doNothingActorRef.path()));
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY);
+
+
+        DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
+
+        Assert.assertTrue(ready instanceof ThreePhaseCommitCohortProxy);
+
+        ThreePhaseCommitCohortProxy proxy = (ThreePhaseCommitCohortProxy) ready;
+
+        Assert.assertTrue("No cohort paths returned", proxy.getCohortPaths().size() > 0);
+
+    }
+
+    @Test
+    public void testGetIdentifier(){
+        final Props props = Props.create(DoNothingActor.class);
+        final ActorRef doNothingActorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteShardOperationResponse(
+            new CreateTransactionReply(doNothingActorRef.path()));
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY);
+
+        Assert.assertNotNull(transactionProxy.getIdentifier());
+    }
+
+    @Test
+    public void testClose(){
+        final Props props = Props.create(MessageCollectorActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteShardOperationResponse(new CreateTransactionReply(actorRef.path()));
+        actorContext.setExecuteRemoteOperationResponse("message");
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY);
+
+        transactionProxy.close();
+
+        ActorContext testContext = new ActorContext(getSystem(), getSystem().actorOf(Props.create(DoNothingActor.class)));
+        Object messages = testContext
+            .executeLocalOperation(actorRef, "messages",
+                ActorContext.ASK_DURATION);
+
+        Assert.assertNotNull(messages);
+
+        Assert.assertTrue(messages instanceof List);
+
+        List<Object> listMessages = (List<Object>) messages;
+
+        Assert.assertEquals(1, listMessages.size());
+
+        Assert.assertTrue(listMessages.get(0) instanceof CloseTransaction);
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimaryTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/messages/FindPrimaryTest.java
new file mode 100644 (file)
index 0000000..7e4ec10
--- /dev/null
@@ -0,0 +1,21 @@
+package org.opendaylight.controller.cluster.datastore.messages;
+
+import org.junit.Test;
+
+public class FindPrimaryTest {
+
+    @Test
+    public void testNewBuilderForType() throws Exception {
+
+    }
+
+    @Test
+    public void testToBuilder() throws Exception {
+
+    }
+
+    @Test
+    public void testGetDefaultInstanceForType() throws Exception {
+
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/AbstractModificationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/AbstractModificationTest.java
new file mode 100644 (file)
index 0000000..efaca5d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.cluster.datastore.modification;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Before;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public abstract class AbstractModificationTest {
+
+  protected InMemoryDOMDataStore store;
+
+  @Before
+  public void setUp(){
+    store = new InMemoryDOMDataStore("test", MoreExecutors.sameThreadExecutor());
+    store.onGlobalContextUpdated(TestModel.createTestContext());
+  }
+
+  protected void commitTransaction(DOMStoreWriteTransaction transaction){
+    DOMStoreThreePhaseCommitCohort cohort = transaction.ready();
+    cohort.preCommit();
+    cohort.commit();
+  }
+
+  protected Optional<NormalizedNode<?,?>> readData(InstanceIdentifier path) throws Exception{
+    DOMStoreReadTransaction transaction = store.newReadOnlyTransaction();
+    ListenableFuture<Optional<NormalizedNode<?, ?>>> future = transaction.read(path);
+    return future.get();
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/DeleteModificationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/DeleteModificationTest.java
new file mode 100644 (file)
index 0000000..c1f9f3a
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.cluster.datastore.modification;
+
+import com.google.common.base.Optional;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+public class DeleteModificationTest extends AbstractModificationTest{
+
+  @Test
+  public void testApply() throws Exception {
+    //Write something into the datastore
+    DOMStoreReadWriteTransaction writeTransaction = store.newReadWriteTransaction();
+    WriteModification writeModification = new WriteModification(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+    writeModification.apply(writeTransaction);
+    commitTransaction(writeTransaction);
+
+    //Check if it's in the datastore
+    Optional<NormalizedNode<?,?>> data = readData(TestModel.TEST_PATH);
+    Assert.assertTrue(data.isPresent());
+
+    //Delete stuff from the datastore
+    DOMStoreWriteTransaction deleteTransaction = store.newWriteOnlyTransaction();
+    DeleteModification deleteModification = new DeleteModification(TestModel.TEST_PATH);
+    deleteModification.apply(deleteTransaction);
+    commitTransaction(deleteTransaction);
+
+    data = readData(TestModel.TEST_PATH);
+    Assert.assertFalse(data.isPresent());
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MergeModificationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MergeModificationTest.java
new file mode 100644 (file)
index 0000000..fd125fb
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.controller.cluster.datastore.modification;
+
+import com.google.common.base.Optional;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+public class MergeModificationTest extends AbstractModificationTest{
+
+  @Test
+  public void testApply() throws Exception {
+    //TODO : Need to write a better test for this
+
+    //Write something into the datastore
+    DOMStoreReadWriteTransaction writeTransaction = store.newReadWriteTransaction();
+    MergeModification writeModification = new MergeModification(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+    writeModification.apply(writeTransaction);
+    commitTransaction(writeTransaction);
+
+    //Check if it's in the datastore
+    Optional<NormalizedNode<?,?>> data = readData(TestModel.TEST_PATH);
+    Assert.assertTrue(data.isPresent());
+
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModificationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModificationTest.java
new file mode 100644 (file)
index 0000000..e30936b
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.controller.cluster.datastore.modification;
+
+import com.google.common.base.Optional;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+public class MutableCompositeModificationTest extends AbstractModificationTest {
+
+  @Test
+  public void testApply() throws Exception {
+
+    MutableCompositeModification compositeModification = new MutableCompositeModification();
+    compositeModification.addModification(new WriteModification(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)));
+
+    DOMStoreReadWriteTransaction transaction = store.newReadWriteTransaction();
+    compositeModification.apply(transaction);
+    commitTransaction(transaction);
+
+    Optional<NormalizedNode<?,?>> data = readData(TestModel.TEST_PATH);
+
+    Assert.assertNotNull(data.get());
+    Assert.assertEquals(TestModel.TEST_QNAME, data.get().getNodeType());
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/WriteModificationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/WriteModificationTest.java
new file mode 100644 (file)
index 0000000..e206bf8
--- /dev/null
@@ -0,0 +1,26 @@
+package org.opendaylight.controller.cluster.datastore.modification;
+
+import com.google.common.base.Optional;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+public class WriteModificationTest extends AbstractModificationTest{
+
+  @Test
+  public void testApply() throws Exception {
+    //Write something into the datastore
+    DOMStoreReadWriteTransaction writeTransaction = store.newReadWriteTransaction();
+    WriteModification writeModification = new WriteModification(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+    writeModification.apply(writeTransaction);
+    commitTransaction(writeTransaction);
+
+    //Check if it's in the datastore
+    Optional<NormalizedNode<?,?>> data = readData(TestModel.TEST_PATH);
+    Assert.assertTrue(data.isPresent());
+
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategyTest.java
new file mode 100644 (file)
index 0000000..d3ba9b1
--- /dev/null
@@ -0,0 +1,14 @@
+package org.opendaylight.controller.cluster.datastore.shardstrategy;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+
+public class DefaultShardStrategyTest {
+
+  @Test
+  public void testFindShard() throws Exception {
+    String shard = new DefaultShardStrategy().findShard(TestModel.TEST_PATH);
+    Assert.assertEquals(DefaultShardStrategy.DEFAULT_SHARD, shard);
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactoryTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactoryTest.java
new file mode 100644 (file)
index 0000000..2cff981
--- /dev/null
@@ -0,0 +1,29 @@
+package org.opendaylight.controller.cluster.datastore.shardstrategy;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+
+import static junit.framework.Assert.assertNotNull;
+
+public class ShardStrategyFactoryTest {
+
+  @Rule
+  public ExpectedException expectedEx = ExpectedException.none();
+
+  @Test
+  public void testGetStrategy(){
+    ShardStrategy strategy = ShardStrategyFactory.getStrategy(TestModel.TEST_PATH);
+    assertNotNull(strategy);
+  }
+
+  @Test
+  public void testGetStrategyNullPointerExceptionWhenPathIsNull(){
+    expectedEx.expect(NullPointerException.class);
+    expectedEx.expectMessage("path should not be null");
+
+    ShardStrategyFactory.getStrategy(null);
+  }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/DoNothingActor.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/DoNothingActor.java
new file mode 100644 (file)
index 0000000..819cfd0
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.cluster.datastore.utils;
+
+import akka.actor.UntypedActor;
+
+public class DoNothingActor extends UntypedActor {
+
+    @Override public void onReceive(Object message) throws Exception {
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MessageCollectorActor.java
new file mode 100644 (file)
index 0000000..f75aa54
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.cluster.datastore.utils;
+
+import akka.actor.UntypedActor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MessageCollectorActor collects messages as it receives them. It can send
+ * those collected messages to any sender which sends it the "messages" message
+ * <p>
+ *     This class would be useful as a mock to test whether messages were sent
+ *     to a remote actor or not.
+ * </p>
+ */
+public class MessageCollectorActor extends UntypedActor {
+    private List<Object> messages = new ArrayList<>();
+
+    @Override public void onReceive(Object message) throws Exception {
+        if(message instanceof String){
+            if("messages".equals(message)){
+                getSender().tell(messages, getSelf());
+            }
+        } else {
+            messages.add(message);
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockActorContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockActorContext.java
new file mode 100644 (file)
index 0000000..fe62516
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.cluster.datastore.utils;
+
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
+import akka.actor.ActorSystem;
+import scala.concurrent.duration.FiniteDuration;
+
+public class MockActorContext extends ActorContext {
+
+    private Object executeShardOperationResponse;
+    private Object executeRemoteOperationResponse;
+    private Object executeLocalOperationResponse;
+
+    public MockActorContext(ActorSystem actorSystem) {
+        super(actorSystem, null);
+    }
+
+    public MockActorContext(ActorSystem actorSystem, ActorRef shardManager) {
+        super(actorSystem, shardManager);
+    }
+
+
+    @Override public Object executeShardOperation(String shardName,
+        Object message, FiniteDuration duration) {
+        return executeShardOperationResponse;
+    }
+
+    @Override public Object executeRemoteOperation(ActorSelection actor,
+        Object message, FiniteDuration duration) {
+        return executeRemoteOperationResponse;
+    }
+
+    @Override public ActorSelection findPrimary(String shardName) {
+        return null;
+    }
+
+    public void setExecuteShardOperationResponse(Object response){
+        executeShardOperationResponse = response;
+    }
+
+    public void setExecuteRemoteOperationResponse(Object response){
+        executeRemoteOperationResponse = response;
+    }
+
+    public void setExecuteLocalOperationResponse(
+        Object executeLocalOperationResponse) {
+        this.executeLocalOperationResponse = executeLocalOperationResponse;
+    }
+
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/TestModel.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/TestModel.java
new file mode 100644 (file)
index 0000000..7a1def9
--- /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.cluster.datastore.model;
+
+import org.opendaylight.yangtools.yang.common.QName;
+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 org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+
+public class TestModel {
+
+  public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+          "test");
+  public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+  public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+  public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
+  public static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
+  public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
+  public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
+  private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
+
+  public static final InstanceIdentifier TEST_PATH = InstanceIdentifier.of(TEST_QNAME);
+  public static final InstanceIdentifier OUTER_LIST_PATH = InstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
+  public static final QName TWO_QNAME = QName.create(TEST_QNAME,"two");
+  public static final QName THREE_QNAME = QName.create(TEST_QNAME,"three");
+
+
+  public static final InputStream getDatastoreTestInputStream() {
+    return getInputStream(DATASTORE_TEST_YANG);
+  }
+
+  private static InputStream getInputStream(final String resourceName) {
+    return TestModel.class.getResourceAsStream(DATASTORE_TEST_YANG);
+  }
+
+  public static SchemaContext createTestContext() {
+    YangParserImpl parser = new YangParserImpl();
+    Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(getDatastoreTestInputStream()));
+    return parser.resolveSchemaContext(modules);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/application.conf b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/application.conf
new file mode 100644 (file)
index 0000000..2647850
--- /dev/null
@@ -0,0 +1,11 @@
+akka {
+    actor {
+        serializers {
+          java = "akka.serialization.JavaSerializer"
+        }
+
+        serialization-bindings {
+            "org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification" = java
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/odl-datastore-test.yang b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/odl-datastore-test.yang
new file mode 100644 (file)
index 0000000..f6d0202
--- /dev/null
@@ -0,0 +1,42 @@
+module odl-datastore-test {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test";
+    prefix "store-test";
+
+    revision "2014-03-13" {
+        description "Initial revision.";
+    }
+
+    container test {
+        list outer-list {
+            key id;
+            leaf id {
+                type uint16;
+            }
+            choice outer-choice {
+                case one {
+                    leaf one {
+                        type string;
+                    }
+                }
+                case two-three {
+                    leaf two {
+                        type string;
+                    }
+                    leaf three {
+                        type string;
+                    }
+               }
+           }
+           list inner-list {
+                key name;
+                leaf name {
+                    type string;
+                }
+                leaf value {
+                    type string;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
index c120508f875acfc0f5710aaced9d699204307fbc..613cf1bfe24e1b31cf854d978c35c48ef11d96f3 100644 (file)
@@ -29,7 +29,7 @@ public interface DOMDataBroker extends
      * {@inheritDoc}
      */
     @Override
-    DOMDataReadTransaction newReadOnlyTransaction();
+    DOMDataReadOnlyTransaction newReadOnlyTransaction();
 
     /**
      * {@inheritDoc}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadOnlyTransaction.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadOnlyTransaction.java
new file mode 100644 (file)
index 0000000..18fb988
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.md.sal.dom.api;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncReadOnlyTransaction;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface DOMDataReadOnlyTransaction extends DOMDataReadTransaction, AsyncReadOnlyTransaction<InstanceIdentifier, NormalizedNode<?, ?>> {
+
+}
index b894911ffad8fcac128f38f743df5a3a6819ea30..73a0c28465108e951ddafdd6fa2639bd088f9ff1 100644 (file)
@@ -24,7 +24,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 public interface DOMTransactionChain extends TransactionChain<InstanceIdentifier, NormalizedNode<?, ?>> {
 
     @Override
-    DOMDataReadTransaction newReadOnlyTransaction();
+    DOMDataReadOnlyTransaction newReadOnlyTransaction();
 
     @Override
     DOMDataReadWriteTransaction newReadWriteTransaction();
index 266b6976afbde367ecca294a90023253d903b0ff..9c7deaf406fb955bcb43339a784f1b17748579cf 100644 (file)
@@ -21,8 +21,10 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
  *
  *
  * @see DataProviderService
+ * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.dom.api.DOMDataBroker}
  *
  */
+@Deprecated
 public interface DataBrokerService extends
     BrokerService, //
     DataReader<InstanceIdentifier, CompositeNode>, //
@@ -36,5 +38,6 @@ public interface DataBrokerService extends
     @Override
     public CompositeNode readOperationalData(InstanceIdentifier path);
 
+    @Override
     DataModificationTransaction beginTransaction();
 }
index 944ccc5b33a120f5ad3ef2eeb3e347dd5881621c..2bf949d208b9bf563c9b7d41e39826bbd853339a 100644 (file)
@@ -11,6 +11,11 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
+/**
+ *
+ * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener}
+ */
+@Deprecated
 public interface DataChangeListener
         extends
         org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<InstanceIdentifier, CompositeNode> {
index 9706bbacdbdbee3b22c3a8b163b069617b452347..82e62255c3ba465c86ef665038f362b6cad1f0fe 100644 (file)
@@ -17,7 +17,17 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
-public interface DataModificationTransaction extends DataModification<InstanceIdentifier, CompositeNode>{
+/**
+ *
+ * @deprecated Replaced by more specific
+ *             {@link org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction}
+ *             ,
+ *             {@link org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction}
+ *             or {@link org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction}
+ *
+ */
+@Deprecated
+public interface DataModificationTransaction extends DataModification<InstanceIdentifier, CompositeNode> {
 
     /**
      * Returns transaction identifier
@@ -34,8 +44,8 @@ public interface DataModificationTransaction extends DataModification<InstanceId
      * Commits transaction to be stored in global data repository.
      *
      *
-     * @return  Future object which returns RpcResult with TransactionStatus
-     *          when transaction is processed by store.
+     * @return Future object which returns RpcResult with TransactionStatus when
+     *         transaction is processed by store.
      */
     @Override
     Future<RpcResult<TransactionStatus>> commit();
@@ -43,6 +53,6 @@ public interface DataModificationTransaction extends DataModification<InstanceId
     ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener);
 
     public interface DataTransactionListener extends EventListener {
-        void onStatusUpdated(DataModificationTransaction transaction,TransactionStatus status);
+        void onStatusUpdated(DataModificationTransaction transaction, TransactionStatus status);
     }
 }
index 0538660fd79eea473d705ae588ce83035683941e..0810fa3e98ab9041c51b0febb83184ec14f6463d 100644 (file)
@@ -8,13 +8,19 @@
 package org.opendaylight.controller.sal.core.api.data;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;;
 
+/**
+ *
+ * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.dom.api.DOMDataBroker}
+ *
+ */
+@Deprecated
 public interface DataProviderService extends
     DataBrokerService, //
     DataProvisionService<InstanceIdentifier, CompositeNode>
index 58ffb38365c0d6673fa10ef9f1ccd229cdb26bcd..56d2e87c2c1007954c7560f01132298bf37f2387 100644 (file)
@@ -12,6 +12,12 @@ import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
+/**
+ *
+ * @deprecated Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore.
+ *
+ */
+@Deprecated
 public interface DataStore extends //
     DataReader<InstanceIdentifier, CompositeNode>,
     DataCommitHandler<InstanceIdentifier, CompositeNode> {
index 286770b0482d36d600f9f2eeebe5ed24cf928a43..e4e6e2f26df00fb1baf8035649143e87afe95a96 100644 (file)
@@ -28,7 +28,10 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  * {@link DataProviderService#addValidator(DataStoreIdentifier, DataValidator)}
  * </ul>
  *
+ * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.common.api.data.AsyncConfigurationCommitHandler}
+ *
  **/
+@Deprecated
 public interface DataValidator extends Provider.ProviderFunctionality {
 
     /**
index bac9146bf5395f29a7ce9c8fa733802b0cf42259..022882fcebd042404689f64abf2ed614894c3262 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-core-spi</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-inmemory-datastore</artifactId>
+      <version>1.1-SNAPSHOT</version>
+
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>util</artifactId>
@@ -88,8 +94,6 @@
                             org.opendaylight.controller.config.yang.md.sal.dom.statistics,
                             org.opendaylight.controller.md.sal.dom.broker.impl,
                             org.opendaylight.controller.md.sal.dom.broker.impl.*,
-                            org.opendaylight.controller.md.sal.dom.store.impl,
-                            org.opendaylight.controller.md.sal.dom.store.impl.*,
                             org.opendaylight.yangtools.yang.util,
                             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.dom.impl.rev131028.*</Private-Package>
             <Import-Package>*</Import-Package>
index 767785dbf13c1dac1231b46e2339f044ebe0cb97..998d884b0cde71cd2fe774352229a61afd98761d 100644 (file)
@@ -8,10 +8,26 @@
 package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 
 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.BrokerService;
+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.dom.broker.BrokerConfigActivator;
+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.BrokerImpl;
-import org.osgi.framework.BundleContext;
+import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
+import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl;
+import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
+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 com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.MutableClassToInstanceMap;
 
 /**
 *
@@ -19,8 +35,6 @@ import org.osgi.framework.BundleContext;
 public final class DomBrokerImplModule extends org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractDomBrokerImplModule
 {
 
-    private BundleContext bundleContext;
-
     public DomBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
@@ -36,23 +50,58 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        final BrokerImpl broker = new BrokerImpl();
-        final BrokerConfigActivator activator = new BrokerConfigActivator();
-        final DataStore store = getDataStoreDependency();
+        final DataStore legacyStore = getDataStoreDependency();
         final DOMDataBroker asyncBroker= getAsyncDataBrokerDependency();
 
-        activator.start(broker, store, asyncBroker,getBundleContext());
+        ClassToInstanceMap<BrokerService> services = MutableClassToInstanceMap.create();
+
+
+        SchemaService schemaService = getSchemaServiceImpl();
+        services.putInstance(SchemaService.class, schemaService);
+        SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", SchemaContextProviders
+                .fromSchemaService(schemaService));
+        services.putInstance(RpcProvisionRegistry.class, router);
+
+        final DataProviderService legacyData;
+        if(asyncBroker != null) {
+            services.putInstance(DOMDataBroker.class, asyncBroker);
+            legacyData = new BackwardsCompatibleDataBroker(asyncBroker,schemaService);
+        } else {
+            legacyData = createLegacyDataService(legacyStore,schemaService);
+        }
+        services.putInstance(DataProviderService.class,legacyData);
+        services.putInstance(DataBrokerService.class, legacyData);
 
-//        final DomBrokerImplRuntimeMXBean domBrokerRuntimeMXBean = new DomBrokerRuntimeMXBeanImpl(activator.getDataService());
-//        getRootRuntimeBeanRegistratorWrapper().register(domBrokerRuntimeMXBean);
-        return broker;
+
+        MountPointManagerImpl mountService = new MountPointManagerImpl();
+        services.putInstance(MountService.class, mountService);
+        services.putInstance(MountProvisionService.class, mountService);
+
+        return new BrokerImpl(router, services);
     }
 
-    private BundleContext getBundleContext() {
-        return this.bundleContext;
+    private DataProviderService createLegacyDataService(final DataStore legacyStore, final SchemaService schemaService) {
+        InstanceIdentifier rootPath = InstanceIdentifier.builder().toInstance();
+        DataBrokerImpl dataService = new DataBrokerImpl();
+        SchemaAwareDataStoreAdapter wrappedStore = new SchemaAwareDataStoreAdapter();
+        wrappedStore.changeDelegate(legacyStore);
+        wrappedStore.setValidationEnabled(false);
+
+        schemaService.registerSchemaServiceListener(wrappedStore);
+
+        dataService.registerConfigurationReader(rootPath, wrappedStore);
+        dataService.registerCommitHandler(rootPath, wrappedStore);
+        dataService.registerOperationalReader(rootPath, wrappedStore);
+        return dataService;
     }
 
-    public void setBundleContext(final BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
+    private SchemaService getSchemaServiceImpl() {
+        final SchemaService schemaService;
+        if(getRootSchemaService() != null) {
+            schemaService = getRootSchemaServiceDependency();
+        } else {
+            schemaService = GlobalBundleScanningSchemaServiceImpl.getInstance();
+        }
+        return schemaService;
     }
 }
index 38f5009feb85e14376755f71008425d137c8cd00..f1fcb495aace6a38ade530efa34b32eba817772f 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 
-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;
 
 /**
 *
@@ -18,19 +14,4 @@ import org.osgi.framework.BundleContext;
 public class DomBrokerImplModuleFactory extends
         org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractDomBrokerImplModuleFactory {
 
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
-        DomBrokerImplModule module = (DomBrokerImplModule) super.createModule(instanceName, dependencyResolver, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver,
-            DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
-        DomBrokerImplModule module = (DomBrokerImplModule) super.createModule(instanceName, dependencyResolver, old, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
 }
index ad0de54bc035bf49863ef350cdc045af2fd35f48..69b17ee3c48aeb5aae64dc8c4b02e36abdfce7a7 100644 (file)
@@ -7,15 +7,12 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 
-import java.util.Hashtable;
 import java.util.concurrent.Executors;
 
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
-import org.osgi.framework.BundleContext;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -27,8 +24,6 @@ import com.google.common.util.concurrent.MoreExecutors;
 public final class DomInmemoryDataBrokerModule extends
         org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractDomInmemoryDataBrokerModule {
 
-    private BundleContext bundleContext;
-
     public DomInmemoryDataBrokerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
             final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
@@ -49,27 +44,28 @@ public final class DomInmemoryDataBrokerModule extends
     @Override
     public java.lang.AutoCloseable createInstance() {
         ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2));
-        InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("DOM-OPER", storeExecutor);
-        InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("DOM-CFG", storeExecutor);
+        //Initializing Operational DOM DataStore defaulting to InMemoryDOMDataStore if one is not configured
+        DOMStore operStore =  getOperationalDataStoreDependency();
+        if(operStore == null){
+           //we will default to InMemoryDOMDataStore creation
+          operStore = new InMemoryDOMDataStore("DOM-OPER", storeExecutor);
+          //here we will register the SchemaContext listener
+          getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)operStore);
+        }
+
+        DOMStore configStore = getConfigDataStoreDependency();
+        if(configStore == null){
+           //we will default to InMemoryDOMDataStore creation
+           configStore = new InMemoryDOMDataStore("DOM-CFG", storeExecutor);
+          //here we will register the SchemaContext listener
+          getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)configStore);
+        }
         ImmutableMap<LogicalDatastoreType, DOMStore> datastores = ImmutableMap
                 .<LogicalDatastoreType, DOMStore> builder().put(LogicalDatastoreType.OPERATIONAL, operStore)
                 .put(LogicalDatastoreType.CONFIGURATION, configStore).build();
 
         DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores, MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
 
-        getBundleContext().registerService(DOMDataBroker.class, newDataBroker, new Hashtable<String, String>());
-
-        getSchemaServiceDependency().registerSchemaServiceListener(operStore);
-        getSchemaServiceDependency().registerSchemaServiceListener(configStore);
-
         return newDataBroker;
     }
-
-    private BundleContext getBundleContext() {
-        return bundleContext;
-    }
-
-    void setBundleContext(final BundleContext ctx) {
-        bundleContext = ctx;
-    }
 }
index 91d42c48c13577853ecbc7d3a618bf0b2de93f4e..56a51ed45e75588d40adca6b9613348e3e1c8d9a 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 
-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;
 
 /**
 *
@@ -19,19 +15,4 @@ public class DomInmemoryDataBrokerModuleFactory extends org.opendaylight.control
 {
 
 
-
-    @Override
-    public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
-        DomInmemoryDataBrokerModule module = (DomInmemoryDataBrokerModule) super.createModule(instanceName, dependencyResolver, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
-    @Override
-    public Module createModule(final String instanceName, final DependencyResolver dependencyResolver,
-            final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
-        DomInmemoryDataBrokerModule module = (DomInmemoryDataBrokerModule)  super.createModule(instanceName, dependencyResolver, old, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
 }
index fd24944018c69b3b9480a7018e0fea1c23986719..fbc418dc2aec0203d4f52ad6b7ace8cc083ca019 100644 (file)
@@ -15,7 +15,6 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 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;
 
@@ -57,43 +56,21 @@ org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImp
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        ServiceReference<SchemaService> ref = getBundleContext().getServiceReference(SchemaService.class);
-        if (ref != null) {
-            return new GlobalSchemaServiceProxy(getBundleContext(), ref);
-        }
-
-        GlobalBundleScanningSchemaServiceImpl newInstance = new GlobalBundleScanningSchemaServiceImpl(getBundleContext());
-        newInstance.start();
-        return newInstance;
+        return GlobalBundleScanningSchemaServiceImpl.getInstance();
     }
 
     public class GlobalSchemaServiceProxy implements AutoCloseable, SchemaService, Delegator<SchemaService> {
 
-        private BundleContext bundleContext;
-        private ServiceReference<SchemaService> reference;
         private SchemaService delegate;
 
-        public GlobalSchemaServiceProxy(final BundleContext bundleContext, final ServiceReference<SchemaService> ref) {
-            this.bundleContext = bundleContext;
-            this.reference = ref;
-            this.delegate = bundleContext.getService(reference);
+        public GlobalSchemaServiceProxy() {
+            this.delegate = GlobalBundleScanningSchemaServiceImpl.getInstance();
         }
 
         @Override
         public void close() throws Exception {
             if (delegate != null) {
                 delegate = null;
-
-                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;
             }
         }
 
index 0c07b0684c9b9291344c8f55daadd7d3846ee4da..0be4327f7ae06231cd86814c62c724ddb16fd937 100644 (file)
@@ -75,8 +75,7 @@ abstract class AbstractDOMForwardedCompositeTransaction<K, T extends DOMStoreTra
         return identifier;
     }
 
-    @Override
-    public void close() {
+    protected void closeSubtransactions() {
         /*
          *  We share one exception for all failures, which are added
          *  as supressedExceptions to it.
index 2203087c997ce536485f5359b03ee85c56c1c568..5694d0bca9a68fccd5f31557418a8824b35d7a5a 100644 (file)
@@ -13,7 +13,7 @@ import java.util.Map.Entry;
 import javax.annotation.concurrent.GuardedBy;
 
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
@@ -66,7 +66,7 @@ public abstract class AbstractDOMForwardedTransactionFactory<T extends DOMStoreT
      *
      * Subtransaction for reading is selected by supplied
      * {@link LogicalDatastoreType} as parameter for
-     * {@link DOMDataReadTransaction#read(LogicalDatastoreType,org.opendaylight.yangtools.yang.data.api.InstanceIdentifier)}
+     * {@link DOMDataReadOnlyTransaction#read(LogicalDatastoreType,org.opendaylight.yangtools.yang.data.api.InstanceIdentifier)}
      * .
      *
      * Id of returned transaction is retrieved via
@@ -74,7 +74,7 @@ public abstract class AbstractDOMForwardedTransactionFactory<T extends DOMStoreT
      *
      * @return New composite read-only transaction.
      */
-    public DOMDataReadTransaction newReadOnlyTransaction() {
+    public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
         checkNotClosed();
         ImmutableMap.Builder<LogicalDatastoreType, DOMStoreReadTransaction> builder = ImmutableMap.builder();
         for (Entry<LogicalDatastoreType, T> store : storeTxFactories.entrySet()) {
index d2543f02bc548be0430584d926a0ed372c6ccf55..f207783c29f7820e5e472b13359d90f8b92f39db 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.controller.md.sal.dom.broker.impl;
 
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -26,7 +26,7 @@ import com.google.common.util.concurrent.ListenableFuture;
  */
 class DOMForwardedReadOnlyTransaction extends
         AbstractDOMForwardedCompositeTransaction<LogicalDatastoreType, DOMStoreReadTransaction> implements
-        DOMDataReadTransaction {
+        DOMDataReadOnlyTransaction {
 
     protected DOMForwardedReadOnlyTransaction(final Object identifier,
             final ImmutableMap<LogicalDatastoreType, DOMStoreReadTransaction> backingTxs) {
@@ -39,4 +39,9 @@ class DOMForwardedReadOnlyTransaction extends
         return getSubtransaction(store).read(path);
     }
 
+    @Override
+    public void close() {
+        closeSubtransactions();
+    }
+
 }
index eeb345e9ce663e7340300f779ab789805be86a7f..f791522a2a77214e9a233f966801fac096948618 100644 (file)
@@ -50,13 +50,31 @@ import com.google.common.util.concurrent.ListenableFuture;
 class DOMForwardedWriteTransaction<T extends DOMStoreWriteTransaction> extends
         AbstractDOMForwardedCompositeTransaction<LogicalDatastoreType, T> implements DOMDataWriteTransaction {
 
+    /**
+     *  Implementation of real commit.
+     *
+     *  Transaction can not be commited if commitImpl is null,
+     *  so this seting this property to null is also used to
+     *  prevent write to
+     *  already commited / canceled transaction {@link #checkNotCanceled()
+     *
+     *
+     */
     @GuardedBy("this")
-    private DOMDataCommitImplementation commitImpl;
-
-    @GuardedBy("this")
-    private boolean canceled;
+    private volatile DOMDataCommitImplementation commitImpl;
+
+    /**
+     *
+     * Future task of transaction commit.
+     *
+     * This value is initially null, and is once updated if transaction
+     * is commited {@link #commit()}.
+     * If this future exists, transaction MUST not be commited again
+     * and all modifications should fail. See {@link #checkNotCommited()}.
+     *
+     */
     @GuardedBy("this")
-    private ListenableFuture<RpcResult<TransactionStatus>> commitFuture;
+    private volatile ListenableFuture<RpcResult<TransactionStatus>> commitFuture;
 
     protected DOMForwardedWriteTransaction(final Object identifier,
             final ImmutableMap<LogicalDatastoreType, T> backingTxs, final DOMDataCommitImplementation commitImpl) {
@@ -83,15 +101,19 @@ class DOMForwardedWriteTransaction<T extends DOMStoreWriteTransaction> extends
     }
 
     @Override
-    public synchronized void cancel() {
-        checkState(!canceled, "Transaction was canceled.");
-        if (commitFuture != null) {
-            // FIXME: Implement cancelation of commit future
-            // when Broker impl will support cancelation.
-            throw new UnsupportedOperationException("Not implemented yet.");
+    public synchronized boolean cancel() {
+        // Transaction is already canceled, we are safe to return true
+        final boolean cancelationResult;
+        if (commitImpl == null && commitFuture != null) {
+            // Transaction is submitted, we try to cancel future.
+            cancelationResult = commitFuture.cancel(false);
+        } else if(commitImpl == null) {
+            return true;
+        } else {
+            cancelationResult = true;
+            commitImpl = null;
         }
-        canceled = true;
-        commitImpl = null;
+        return cancelationResult;
 
     }
 
@@ -105,20 +127,26 @@ class DOMForwardedWriteTransaction<T extends DOMStoreWriteTransaction> extends
         }
         ImmutableList<DOMStoreThreePhaseCommitCohort> cohorts = cohortsBuilder.build();
         commitFuture = commitImpl.commit(this, cohorts);
+
+        /*
+         *We remove reference to Commit Implementation in order
+         *to prevent memory leak
+         */
+        commitImpl = null;
         return commitFuture;
     }
 
     private void checkNotReady() {
-        checkNotCanceled();
         checkNotCommited();
+        checkNotCanceled();
     }
 
     private void checkNotCanceled() {
-        Preconditions.checkState(!canceled, "Transaction was canceled.");
+        Preconditions.checkState(commitImpl != null, "Transaction was canceled.");
     }
 
     private void checkNotCommited() {
-        checkState(commitFuture == null, "Transaction was already commited.");
+        checkState(commitFuture == null, "Transaction was already submited.");
     }
 
 }
\ No newline at end of file
index 5b34fba69ac1b0eaebabaf8a82c801082eacc864..f361af948cb1c600a1c778fe97958cbcef1643d0 100644 (file)
@@ -1,5 +1,7 @@
 package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
@@ -11,6 +13,7 @@ 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.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
@@ -18,19 +21,18 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
 
-public class BackwardsCompatibleDataBroker implements DataProviderService, SchemaContextListener {
+@ThreadSafe
+public class BackwardsCompatibleDataBroker implements DataProviderService {
 
     private final DOMDataBroker backingBroker;
-    private DataNormalizer normalizer;
+    private volatile DataNormalizer normalizer;
+    private final ListenerRegistration<SchemaServiceListener> schemaReg;
 
-    public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl) {
+    public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl, final SchemaService schemaService) {
         backingBroker = newBiDataImpl;
-    }
-
-    @Override
-    public void onGlobalContextUpdated(final SchemaContext ctx) {
-        normalizer = new DataNormalizer(ctx);
+        schemaReg = schemaService.registerSchemaServiceListener(new SchemaListener());
     }
 
     @Override
@@ -148,4 +150,13 @@ public class BackwardsCompatibleDataBroker implements DataProviderService, Schem
             return listener;
         }
     }
+
+    private class SchemaListener implements SchemaContextListener {
+
+        @Override
+        public void onGlobalContextUpdated(final SchemaContext ctx) {
+            normalizer = new DataNormalizer(ctx);
+        }
+
+    }
 }
index 29f2af511e8b8bb03ab0921837b8acae80aa59a7..27e322f23baf265a046d04317f2bfbf78ab2f74c 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 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.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
@@ -42,7 +43,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.ListenableFuture;
 
 public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransaction> implements
-        DataModificationTransaction, Delegator<T> {
+DataModificationTransaction, Delegator<T> {
 
     private static final Logger LOG = LoggerFactory.getLogger(BackwardsCompatibleTransaction.class);
 
@@ -55,10 +56,10 @@ public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransa
         this.normalizer = normalizer;
     }
 
-    public static BackwardsCompatibleTransaction<?> readOnlyTransaction(final DOMDataReadTransaction readTx,
+    public static BackwardsCompatibleTransaction<?> readOnlyTransaction(final DOMDataReadOnlyTransaction readTx,
             final DataNormalizer normalizer) {
 
-        return new BackwardsCompatibleTransaction<DOMDataReadTransaction>(readTx, normalizer) {
+        return new BackwardsCompatibleTransaction<DOMDataReadOnlyTransaction>(readTx, normalizer) {
 
             @Override
             public TransactionStatus getStatus() {
@@ -227,23 +228,23 @@ public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransa
 
             LOG.trace("write {}:{} ",store,normalizedPath);
             try {
-            List<PathArgument> currentArguments = new ArrayList<>();
-            DataNormalizationOperation<?> currentOp = getNormalizer().getRootOperation();
-            Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
-            while(iterator.hasNext()) {
-                PathArgument currentArg = iterator.next();
-                try {
-                    currentOp = currentOp.getChild(currentArg);
-                } catch (DataNormalizationException e) {
-                    throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", normalizedPath), e);
+                List<PathArgument> currentArguments = new ArrayList<>();
+                DataNormalizationOperation<?> currentOp = getNormalizer().getRootOperation();
+                Iterator<PathArgument> iterator = normalizedPath.getPathArguments().iterator();
+                while(iterator.hasNext()) {
+                    PathArgument currentArg = iterator.next();
+                    try {
+                        currentOp = currentOp.getChild(currentArg);
+                    } catch (DataNormalizationException e) {
+                        throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", normalizedPath), e);
+                    }
+                    currentArguments.add(currentArg);
+                    InstanceIdentifier currentPath = InstanceIdentifier.create(currentArguments);
+                    boolean isPresent = getDelegate().read(store, currentPath).get().isPresent();
+                    if(isPresent == false && iterator.hasNext()) {
+                        getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg));
+                    }
                 }
-                currentArguments.add(currentArg);
-                InstanceIdentifier currentPath = new InstanceIdentifier(currentArguments);
-                boolean isPresent = getDelegate().read(store, currentPath).get().isPresent();
-                if(isPresent == false && iterator.hasNext()) {
-                    getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg));
-                }
-            }
             } catch (InterruptedException | ExecutionException e) {
                 LOG.error("Exception durring read.",e);
             }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ConflictingModificationAppliedException.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ConflictingModificationAppliedException.java
deleted file mode 100644 (file)
index 3625d33..0000000
+++ /dev/null
@@ -1,33 +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;
-
-/**
- * Exception thrown when a proposed change fails validation before being
- * applied into the Data Tree because the Data Tree has been modified
- * in way that a conflicting
- * node is present.
- */
-public class ConflictingModificationAppliedException extends DataValidationFailedException {
-
-    /**
-     *
-     */
-    private static final long serialVersionUID = 1L;
-
-    public ConflictingModificationAppliedException(final InstanceIdentifier path, final String message, final Throwable cause) {
-        super(path, message, cause);
-    }
-
-    public ConflictingModificationAppliedException(final InstanceIdentifier path, final String message) {
-        super(path, message);
-    }
-
-}
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
deleted file mode 100644 (file)
index 4807e15..0000000
+++ /dev/null
@@ -1,51 +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.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 DataValidationFailedException;
-
-    /**
-     * 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
deleted file mode 100644 (file)
index d860dfc..0000000
+++ /dev/null
@@ -1,35 +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;
-
-/**
- * An encapsulation of a validated data tree modification. This candidate
- * is ready for atomic commit to the datastore. It allows access to before-
- * and after-state as it will be seen in to subsequent commit. This capture
- * can be accessed for reference, but cannot be modified and the content
- * is limited to nodes which were affected by the modification from which
- * this instance originated.
- */
-public interface DataTreeCandidate {
-    /**
-     * Get the candidate tree root node.
-     *
-     * @return Candidate tree root node
-     */
-    DataTreeCandidateNode getRootNode();
-
-    /**
-     * Get the candidate tree root path. This is the path of the root node
-     * relative to the root of InstanceIdentifier namespace.
-     *
-     * @return Relative path of the root node
-     */
-    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
deleted file mode 100644 (file)
index 528419d..0000000
+++ /dev/null
@@ -1,58 +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.api.schema.NormalizedNode;
-
-import com.google.common.base.Optional;
-
-/**
- * A single node within a {@link DataTreeCandidate}. The nodes are organized
- * in tree hierarchy, reflecting the modification from which this candidate
- * was created. The node itself exposes the before- and after-image of the
- * tree restricted to the modified nodes.
- */
-public interface DataTreeCandidateNode {
-    /**
-     * Get the node identifier.
-     *
-     * @return The node identifier.
-     */
-    PathArgument getIdentifier();
-
-    /**
-     * Get an unmodifiable iterable of modified child nodes.
-     *
-     * @return Unmodifiable iterable of modified child nodes.
-     */
-    Iterable<DataTreeCandidateNode> getChildNodes();
-
-    /**
-     * Return the type of modification this node is undergoing.
-     *
-     * @return Node modification type.
-     */
-    ModificationType getModificationType();
-
-    /**
-     * Return the before-image of data corresponding to the node.
-     *
-     * @return Node data as they were present in the tree before
-     *         the modification was applied.
-     */
-    Optional<NormalizedNode<?, ?>> getDataAfter();
-
-    /**
-     * Return the after-image of data corresponding to the node.
-     *
-     * @return Node data as they will be present in the tree after
-     *         the modification is applied.
-     */
-    Optional<NormalizedNode<?, ?>> getDataBefore();
-}
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
deleted file mode 100644 (file)
index e4370c4..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.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 {
-    /**
-     * Delete the node at specified path.
-     *
-     * @param path Node path
-     */
-    void delete(InstanceIdentifier path);
-
-    /**
-     * Merge the specified data with the currently-present data
-     * at specified path.
-     *
-     * @param path Node path
-     * @param data Data to be merged
-     */
-    void merge(InstanceIdentifier path, NormalizedNode<?, ?> data);
-
-    /**
-     * Replace the data at specified path with supplied data.
-     *
-     * @param path Node path
-     * @param data New node data
-     */
-    void write(InstanceIdentifier path, NormalizedNode<?, ?> data);
-
-    /**
-     * Finish creation of a modification, making it ready for application
-     * to the data tree. Any calls to this object's methods will result
-     * in undefined behavior, possibly with an
-     * {@link IllegalStateException} being thrown.
-     */
-    void ready();
-}
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
deleted file mode 100644 (file)
index a94acc5..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.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/DataValidationFailedException.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/DataValidationFailedException.java
deleted file mode 100644 (file)
index 3683240..0000000
+++ /dev/null
@@ -1,53 +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;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Exception thrown when a proposed change fails validation before being
- * applied into the datastore. This can have multiple reasons, for example
- * the datastore has been concurrently modified such that a conflicting
- * node is present, or the modification is structurally incorrect.
- */
-public class DataValidationFailedException extends Exception {
-    private static final long serialVersionUID = 1L;
-    private final InstanceIdentifier path;
-
-    /**
-     * Create a new instance.
-     *
-     * @param path Object path which caused this exception
-     * @param message Specific message describing the failure
-     */
-    public DataValidationFailedException(final InstanceIdentifier path, final String message) {
-        this(path, message, null);
-    }
-    /**
-     * Create a new instance, initializing
-     *
-     * @param path Object path which caused this exception
-     * @param message Specific message describing the failure
-     * @param cause Exception which triggered this failure, may be null
-     */
-    public DataValidationFailedException(final InstanceIdentifier path, final String message, final Throwable cause) {
-        super(message, cause);
-        this.path = Preconditions.checkNotNull(path);
-    }
-
-    /**
-     * Returns the offending object path.
-     *
-     * @return Path of the offending object
-     */
-    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/IncorrectDataStructureException.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/IncorrectDataStructureException.java
deleted file mode 100644 (file)
index 87482a9..0000000
+++ /dev/null
@@ -1,33 +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;
-
-/**
- * Exception thrown when a proposed change fails validation before being
- * applied into the datastore because of incorrect structure of user supplied
- * data.
- *
- */
-public class IncorrectDataStructureException extends DataValidationFailedException {
-
-    /**
-     *
-     */
-    private static final long serialVersionUID = 1L;
-
-    public IncorrectDataStructureException(final InstanceIdentifier path, final String message, final Throwable cause) {
-        super(path, message, cause);
-    }
-
-    public IncorrectDataStructureException(final InstanceIdentifier path, final String message) {
-        super(path, message);
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ModificationType.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ModificationType.java
deleted file mode 100644 (file)
index b9a26f5..0000000
+++ /dev/null
@@ -1,45 +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;
-
-/**
- * Enumeration of all possible node modification states. These are used in
- * data tree modification context to quickly assess what sort of modification
- * the node is undergoing.
- */
-public enum ModificationType {
-    /**
-     * Node is currently unmodified.
-     */
-    UNMODIFIED,
-
-    /**
-     * A child node, either direct or indirect, has been modified. This means
-     * that the data representation of this node has potentially changed.
-     */
-    SUBTREE_MODIFIED,
-
-    /**
-     * This node has been placed into the tree, potentially completely replacing
-     * pre-existing contents.
-     */
-    WRITE,
-
-    /**
-     * This node has been deleted along with any of its child nodes.
-     */
-    DELETE,
-
-    /**
-     * Node has been written into the tree, but instead of replacing pre-existing
-     * contents, it has been merged. This means that any incoming nodes which
-     * were present in the tree have been replaced, but their child nodes have
-     * been retained.
-     */
-    MERGE,
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreTreeNode.java
deleted file mode 100644 (file)
index d714f1c..0000000
+++ /dev/null
@@ -1,29 +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 com.google.common.base.Optional;
-
-/**
- * A tree node which has references to its child leaves. This are typically
- * internal non-data leaves, such as containers, lists, etc.
- *
- * @param <C> Final node type
- */
-public interface StoreTreeNode<C extends StoreTreeNode<C>> {
-
-    /**
-     * Returns a direct child of the node
-     *
-     * @param child Identifier of child
-     * @return Optional with node if the child is existing, {@link Optional#absent()} otherwise.
-     */
-    Optional<C> getChild(PathArgument child);
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreUtils.java
deleted file mode 100644 (file)
index b634866..0000000
+++ /dev/null
@@ -1,70 +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.AugmentationIdentifier;
-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.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-
-import com.google.common.base.Strings;
-
-/**
- * Data store tree manipulation utilities.
- */
-public final class StoreUtils {
-    private static final int STRINGTREE_INDENT = 4;
-
-    private StoreUtils() {
-        throw new UnsupportedOperationException("Utility class should not be instantiated");
-    }
-
-    /**
-     * Convert a data subtree under a node into a human-readable string format.
-     *
-     * @param node Data subtree root
-     * @return String containing a human-readable form of the subtree.
-     */
-    public static String toStringTree(final NormalizedNode<?, ?> node) {
-        final StringBuilder builder = new StringBuilder();
-        toStringTree(builder, node, 0);
-        return builder.toString();
-    }
-
-    private static void toStringTree(final StringBuilder builder, final NormalizedNode<?, ?> node, final int offset) {
-        final String prefix = Strings.repeat(" ", offset);
-
-        builder.append(prefix).append(toStringTree(node.getIdentifier()));
-        if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
-            final NormalizedNodeContainer<?, ?, ?> container = (NormalizedNodeContainer<?, ?, ?>) node;
-
-            builder.append(" {\n");
-            for (NormalizedNode<?, ?> child : container.getValue()) {
-                toStringTree(builder, child, offset + STRINGTREE_INDENT);
-            }
-
-            builder.append(prefix).append('}');
-        } else {
-            builder.append(' ').append(node.getValue());
-        }
-        builder.append('\n');
-    }
-
-    private static String toStringTree(final PathArgument identifier) {
-        if (identifier instanceof NodeIdentifierWithPredicates) {
-            StringBuilder builder = new StringBuilder();
-            builder.append(identifier.getNodeType().getLocalName());
-            builder.append(((NodeIdentifierWithPredicates) identifier).getKeyValues().values());
-            return builder.toString();
-        } else if (identifier instanceof AugmentationIdentifier) {
-            return "augmentation";
-        }
-        return identifier.getNodeType().getLocalName();
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.java
deleted file mode 100644 (file)
index fe98468..0000000
+++ /dev/null
@@ -1,107 +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 java.util.AbstractMap.SimpleEntry;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-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.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-
-/**
- * A set of utility methods for interacting with {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode} objects.
- */
-public final class TreeNodeUtils {
-    private TreeNodeUtils() {
-        throw new UnsupportedOperationException("Utility class should not be instantiated");
-    }
-
-    /**
-     * Finds a node in tree
-     *
-     * @param tree Data Tree
-     * @param path Path to the node
-     * @return Optional with node if the node is present in tree, {@link Optional#absent()} otherwise.
-     */
-    public static <T extends StoreTreeNode<T>> Optional<T> findNode(final T tree, final InstanceIdentifier path) {
-        Optional<T> current = Optional.<T> of(tree);
-        Iterator<PathArgument> pathIter = path.getPath().iterator();
-        while (current.isPresent() && pathIter.hasNext()) {
-            current = current.get().getChild(pathIter.next());
-        }
-        return current;
-    }
-
-    public static <T extends StoreTreeNode<T>> T findNodeChecked(final T tree, final InstanceIdentifier path) {
-        T current = tree;
-        List<PathArgument> nested = new ArrayList<>(path.getPath().size());
-        for(PathArgument pathArg : path.getPath()) {
-            Optional<T> potential = current.getChild(pathArg);
-            nested.add(pathArg);
-            Preconditions.checkArgument(potential.isPresent(),"Child %s is not present in tree.",nested);
-            current = potential.get();
-        }
-        return current;
-    }
-
-    /**
-     * Finds a node or closest parent in  the tree
-     *
-     * @param tree Data Tree
-     * @param path Path to the node
-     * @return Map.Entry Entry with key which is path to closest parent and value is parent node.
-     *
-     */
-    public static <T extends StoreTreeNode<T>> Map.Entry<InstanceIdentifier, T> findClosest(final T tree, final InstanceIdentifier path) {
-        return findClosestsOrFirstMatch(tree, path, Predicates.<T>alwaysFalse());
-    }
-
-    public static <T extends StoreTreeNode<T>> Map.Entry<InstanceIdentifier, T> findClosestsOrFirstMatch(final T tree, final InstanceIdentifier path, final Predicate<T> predicate) {
-        Optional<T> parent = Optional.<T>of(tree);
-        Optional<T> current = Optional.<T> of(tree);
-
-        int nesting = 0;
-        Iterator<PathArgument> pathIter = path.getPath().iterator();
-        while (current.isPresent() && pathIter.hasNext() && !predicate.apply(current.get())) {
-            parent = current;
-            current = current.get().getChild(pathIter.next());
-            nesting++;
-        }
-        if(current.isPresent()) {
-            final InstanceIdentifier currentPath = new InstanceIdentifier(path.getPath().subList(0, nesting));
-            return new SimpleEntry<InstanceIdentifier,T>(currentPath,current.get());
-        }
-
-        /*
-         * Subtracting 1 from nesting level at this point is safe, because we
-         * cannot reach here with nesting == 0: that would mean the above check
-         * for current.isPresent() failed, which it cannot, as current is always
-         * present. At any rate we check state just to be on the safe side.
-         */
-        Preconditions.checkState(nesting > 0);
-        final InstanceIdentifier parentPath = new InstanceIdentifier(path.getPath().subList(0, nesting - 1));
-
-        return new SimpleEntry<InstanceIdentifier,T>(parentPath,parent.get());
-    }
-
-    public static <T extends StoreTreeNode<T>> Optional<T> getChild(final Optional<T> parent,final PathArgument child) {
-        if(parent.isPresent()) {
-            return parent.get().getChild(child);
-        }
-        return Optional.absent();
-    }
-
-}
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
deleted file mode 100644 (file)
index cddda5c..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.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
deleted file mode 100644 (file)
index c09a1a3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-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 version) {
-        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
deleted file mode 100644 (file)
index dc89148..0000000
+++ /dev/null
@@ -1,160 +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.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
deleted file mode 100644 (file)
index 4ffa6f9..0000000
+++ /dev/null
@@ -1,138 +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.data;
-
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-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 DataValidationFailedException {
-        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
deleted file mode 100644 (file)
index bafea6b..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-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
deleted file mode 100644 (file)
index 4640be4..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-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
deleted file mode 100644 (file)
index 39ff4f0..0000000
+++ /dev/null
@@ -1,178 +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.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.ModificationType;
-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 ready() {
-        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");
-
-        if(rootNode.getType() == ModificationType.UNMODIFIED) {
-            return snapshot.newModification();
-        }
-
-        /*
-         *  FIXME: Add advanced transaction chaining for modification of not rebased
-         *  modification.
-         *
-         *  Current computation of tempRoot may yeld incorrect subtree versions
-         *  if there are multiple concurrent transactions, which may break
-         *  versioning preconditions for modification of previously occured write,
-         *  directly nested under parent node, since node version is derived from
-         *  subtree version.
-         *
-         *  For deeper nodes subtree version is derived from their respective metadata
-         *  nodes, so this incorrect root subtree version is not affecting us.
-         */
-        TreeNode originalSnapshotRoot = snapshot.getRootNode();
-        Optional<TreeNode> tempRoot = strategyTree.apply(rootNode, Optional.of(originalSnapshotRoot), originalSnapshotRoot.getSubtreeVersion().next());
-
-        InMemoryDataTreeSnapshot tempTree = new InMemoryDataTreeSnapshot(snapshot.getSchemaContext(), tempRoot.get(), strategyTree);
-        return tempTree.newModification();
-    }
-}
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
deleted file mode 100644 (file)
index ee91e62..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-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
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java
deleted file mode 100644 (file)
index f72d575..0000000
+++ /dev/null
@@ -1,93 +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.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-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;
-
-/**
- *
- * 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
- * invoke suboperations independently.
- *
- * <b>Implementation notes</b>
- * <ul>
- * <li>
- * 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(ModifiedNode, Optional)} if applicable.
- *
- *
- * Hierarchical composite operation which is responsible for applying
- * modification on particular subtree and creating updated subtree
- *
- *
- */
-interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
-
-    /**
-     *
-     * Implementation of this operation must be stateless and must not change
-     * state of this object.
-     *
-     * @param modification
-     *            NodeModification to be applied
-     * @param storeMeta
-     *            Store Metadata Node on which NodeModification should be
-     *            applied
-     * @param version New subtree version of parent node
-     * @throws IllegalArgumentException
-     *             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 ModifiedNode}
-     *         resulted in deletion of this node.
-     */
-    Optional<TreeNode> apply(ModifiedNode modification, Optional<TreeNode> storeMeta, Version version);
-
-    /**
-     *
-     * Performs structural verification of NodeModification, such as writen values / types
-     * uses right structural elements.
-     *
-     * @param modification to be verified.
-     * @throws IllegalArgumentException If provided NodeModification does not adhere to the structure.
-     */
-    void verifyStructure(ModifiedNode modification) throws IllegalArgumentException;
-
-    /**
-     * Returns a suboperation for specified tree node
-     *
-     * @return Reference to suboperation for specified tree node, {@link Optional#absent()}
-     *    if suboperation is not supported for specified tree node.
-     */
-    @Override
-    Optional<ModificationApplyOperation> getChild(PathArgument child);
-
-    /**
-     *
-     * Checks if provided node modification could be applied to current metadata node.
-     *
-     * @param modification Modification
-     * @param current Metadata Node to which modification should be applied
-     * @return true if modification is applicable
-     *         false if modification is no applicable
-     * @throws DataValidationFailedException
-     */
-    void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<TreeNode> current) throws DataValidationFailedException;
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java
deleted file mode 100644 (file)
index f83ea1a..0000000
+++ /dev/null
@@ -1,225 +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.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;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-
-/**
- * Node Modification Node and Tree
- *
- * Tree which structurally resembles data tree and captures client modifications
- * to the data store tree.
- *
- * This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
- * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
- */
-final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<PathArgument>, NodeModification {
-
-    public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
-        @Override
-        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 Optional<TreeNode> snapshotCache;
-    private NormalizedNode<?, ?> value;
-
-    private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original) {
-        this.identifier = identifier;
-        this.original = original;
-    }
-
-    /**
-     *
-     *
-     * @return
-     */
-    public NormalizedNode<?, ?> getWrittenValue() {
-        return value;
-    }
-
-    @Override
-    public PathArgument getIdentifier() {
-        return identifier;
-    }
-
-    /**
-     *
-     * Returns original store metadata
-     * @return original store metadata
-     */
-    @Override
-    public Optional<TreeNode> getOriginal() {
-        return original;
-    }
-
-    /**
-     * Returns modification type
-     *
-     * @return modification type
-     */
-    @Override
-    public ModificationType getType() {
-        return modificationType;
-    }
-
-    /**
-     *
-     * Returns child modification if child was modified
-     *
-     * @return Child modification if direct child or it's subtree
-     *  was modified.
-     *
-     */
-    @Override
-    public Optional<ModifiedNode> getChild(final PathArgument child) {
-        return Optional.<ModifiedNode> fromNullable(children.get(child));
-    }
-
-    /**
-     *
-     * 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 ModifiedNode} for specified child, with {@link #getOriginal()}
-     *         containing child metadata if child was present in original data.
-     */
-    public ModifiedNode modifyChild(final PathArgument child) {
-        clearSnapshot();
-        if (modificationType == ModificationType.UNMODIFIED) {
-            updateModificationType(ModificationType.SUBTREE_MODIFIED);
-        }
-        final ModifiedNode potential = children.get(child);
-        if (potential != null) {
-            return potential;
-        }
-
-        final Optional<TreeNode> currentMetadata;
-        if (original.isPresent()) {
-            final TreeNode orig = original.get();
-            currentMetadata = orig.getChild(child);
-        } else {
-            currentMetadata = Optional.absent();
-        }
-
-        ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata);
-        children.put(child, newlyCreated);
-        return newlyCreated;
-    }
-
-    /**
-     *
-     * Returns all recorded direct child modification
-     *
-     * @return all recorded direct child modifications
-     */
-    @Override
-    public Iterable<ModifiedNode> getChildren() {
-        return children.values();
-    }
-
-    /**
-     *
-     * Records a delete for associated node.
-     *
-     */
-    public void delete() {
-        clearSnapshot();
-        updateModificationType(ModificationType.DELETE);
-        children.clear();
-        this.value = null;
-    }
-
-    /**
-     *
-     * Records a write for associated node.
-     *
-     * @param value
-     */
-    public void write(final NormalizedNode<?, ?> value) {
-        clearSnapshot();
-        updateModificationType(ModificationType.WRITE);
-        children.clear();
-        this.value = value;
-    }
-
-    public void merge(final NormalizedNode<?, ?> data) {
-        clearSnapshot();
-        updateModificationType(ModificationType.MERGE);
-        // FIXME: Probably merge with previous value.
-        this.value = data;
-    }
-
-    void seal() {
-        clearSnapshot();
-        for (ModifiedNode child : children.values()) {
-            child.seal();
-        }
-    }
-
-    private void clearSnapshot() {
-        snapshotCache = null;
-    }
-
-    public Optional<TreeNode> storeSnapshot(final Optional<TreeNode> snapshot) {
-        snapshotCache = snapshot;
-        return snapshot;
-    }
-
-    public Optional<Optional<TreeNode>> getSnapshotCache() {
-        return Optional.fromNullable(snapshotCache);
-    }
-
-    @GuardedBy("this")
-    private void updateModificationType(final ModificationType type) {
-        modificationType = type;
-        clearSnapshot();
-    }
-
-    @Override
-    public String toString() {
-        return "NodeModification [identifier=" + identifier + ", modificationType="
-                + modificationType + ", childModification=" + children + "]";
-    }
-
-    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
deleted file mode 100644 (file)
index e7e79f8..0000000
+++ /dev/null
@@ -1,44 +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.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;
-
-/**
- * Internal interface representing a modification action of a particular node.
- * It is used by the validation code to allow for a read-only view of the
- * modification tree as we should never modify that during validation.
- */
-interface NodeModification extends Identifiable<PathArgument> {
-    /**
-     * Get the type of modification.
-     *
-     * @return Modification type.
-     */
-    ModificationType getType();
-
-    /**
-     * Get the original tree node to which the modification is to be applied.
-     *
-     * @return The original node, or {@link Optional#absent()} if the node is
-     *         a new node.
-     */
-    Optional<TreeNode> getOriginal();
-
-    /**
-     * Get a read-only view of children nodes.
-     *
-     * @return Iterable of all children nodes.
-     */
-    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
deleted file mode 100644 (file)
index 227684a..0000000
+++ /dev/null
@@ -1,63 +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.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;
-
-/**
- * Internal utility class for an empty candidate. We instantiate this class
- * for empty modifications, saving memory and processing speed. Instances
- * of this class are explicitly recognized and processing of them is skipped.
- */
-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
deleted file mode 100644 (file)
index 1d10ab6..0000000
+++ /dev/null
@@ -1,337 +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.data;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.Map;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-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 DataValidationFailedException {
-        // 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 version) {
-        final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
-        final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
-
-        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(version);
-
-        @SuppressWarnings("rawtypes")
-        final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
-
-        return mutateChildren(mutable, dataBuilder, version, 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 version) {
-        // For Node Containers - merge is same as subtree change - we only replace children.
-        return applySubtreeChange(modification, currentMeta, version);
-    }
-
-    @Override
-    public TreeNode applySubtreeChange(final ModifiedNode modification,
-            final TreeNode currentMeta, final Version version) {
-        final MutableTreeNode newMeta = currentMeta.mutable();
-        newMeta.setSubtreeVersion(version);
-
-        @SuppressWarnings("rawtypes")
-        NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
-
-        return mutateChildren(newMeta, dataBuilder, version, modification.getChildren());
-    }
-
-    @Override
-    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
-            final Optional<TreeNode> current) throws DataValidationFailedException {
-        checkConflicting(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 DataValidationFailedException {
-        final TreeNode currentMeta = current.get();
-        for (NodeModification childMod : modification.getChildren()) {
-            final PathArgument childId = childMod.getIdentifier();
-            final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
-
-            InstanceIdentifier childPath = path.node(childId);
-            resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
-        }
-    }
-
-    @Override
-    protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
-            final Optional<TreeNode> current) throws DataValidationFailedException {
-        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 + "]";
-        }
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java
deleted file mode 100644 (file)
index e1cc1a1..0000000
+++ /dev/null
@@ -1,68 +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.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.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Optional;
-
-final class OperationWithModification {
-
-    private final ModifiedNode modification;
-
-    private final ModificationApplyOperation applyOperation;
-
-    private OperationWithModification(final ModificationApplyOperation op, final ModifiedNode mod) {
-        this.modification = mod;
-        this.applyOperation = op;
-    }
-
-    public OperationWithModification write(final NormalizedNode<?, ?> value) {
-        modification.write(value);
-        applyOperation.verifyStructure(modification);
-        return this;
-    }
-
-    public OperationWithModification delete() {
-        modification.delete();
-        return this;
-    }
-
-    public ModifiedNode getModification() {
-        return modification;
-    }
-
-    public ModificationApplyOperation getApplyOperation() {
-        return applyOperation;
-    }
-
-    public Optional<TreeNode> apply(final Optional<TreeNode> data, final Version version) {
-        return applyOperation.apply(modification, data, version);
-    }
-
-    public static OperationWithModification from(final ModificationApplyOperation operation,
-            final ModifiedNode modification) {
-        return new OperationWithModification(operation, modification);
-
-    }
-
-    public void merge(final NormalizedNode<?, ?> data) {
-        modification.merge(data);
-        applyOperation.verifyStructure(modification);
-
-    }
-
-    public OperationWithModification forChild(final PathArgument 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
deleted file mode 100644 (file)
index f600635..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.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.ConflictingModificationAppliedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.IncorrectDataStructureException;
-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 checkConflicting(final InstanceIdentifier path, final boolean condition, final String message) throws ConflictingModificationAppliedException {
-        if(!condition) {
-            throw new ConflictingModificationAppliedException(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 ConflictingModificationAppliedException {
-        checkConflicting(path, original.getVersion().equals(current.getVersion()),
-                "Node was replaced by other transaction.");
-        checkConflicting(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 DataValidationFailedException {
-        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 DataValidationFailedException {
-        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 DataValidationFailedException {
-        Optional<TreeNode> original = modification.getOriginal();
-        if (original.isPresent() && current.isPresent()) {
-            checkNotConflicting(path, original.get(), current.get());
-        } else if(original.isPresent()) {
-            throw new ConflictingModificationAppliedException(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 version) {
-
-        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(),
-                    version)));
-        case MERGE:
-            if(currentMeta.isPresent()) {
-                return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(), version)));
-            } // 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, version)));
-        case UNMODIFIED:
-            return currentMeta;
-        default:
-            throw new IllegalArgumentException("Provided modification type is not supported.");
-        }
-    }
-
-    protected abstract TreeNode applyMerge(ModifiedNode modification,
-            TreeNode currentMeta, Version version);
-
-    protected abstract TreeNode applyWrite(ModifiedNode modification,
-            Optional<TreeNode> currentMeta, Version version);
-
-    protected abstract TreeNode applySubtreeChange(ModifiedNode modification,
-            TreeNode currentMeta, Version version);
-
-    /**
-     *
-     * Checks is supplied {@link NodeModification} is applicable for Subtree Modification.
-     *
-     * @param path Path to current node
-     * @param modification Node modification which should be applied.
-     * @param current Current state of data tree
-     * @throws ConflictingModificationAppliedException If subtree was changed in conflicting way
-     * @throws IncorrectDataStructureException If subtree modification is not applicable (e.g. leaf node).
-     */
-    protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path, final NodeModification modification,
-            final Optional<TreeNode> current) throws DataValidationFailedException;
-
-    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 version) {
-            return applyWrite(modification, Optional.of(currentMeta), version);
-        }
-
-        @Override
-        protected TreeNode applySubtreeChange(final ModifiedNode modification,
-                final TreeNode currentMeta, final Version version) {
-            throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
-        }
-
-        @Override
-        protected TreeNode applyWrite(final ModifiedNode modification,
-                final Optional<TreeNode> currentMeta, final Version version) {
-            return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
-        }
-
-        @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 IncorrectDataStructureException {
-            throw new IncorrectDataStructureException(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
deleted file mode 100644 (file)
index 900fa32..0000000
+++ /dev/null
@@ -1,88 +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.data;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.IncorrectDataStructureException;
-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 version) {
-        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 version) {
-        // Just overwrite whatever was there
-        return applyWrite(modification, null, version);
-    }
-
-    @Override
-    protected TreeNode applyWrite(final ModifiedNode modification,
-            final Optional<TreeNode> currentMeta, final Version version) {
-        return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
-    }
-
-    @Override
-    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
-            final Optional<TreeNode> current) throws IncorrectDataStructureException {
-        throw new IncorrectDataStructureException(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
deleted file mode 100644 (file)
index 522bf3c..0000000
+++ /dev/null
@@ -1,41 +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.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
deleted file mode 100644 (file)
index 3ca8db2..0000000
+++ /dev/null
@@ -1,118 +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.spi;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.opendaylight.yangtools.util.MapAdaptor;
-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 Version version;
-        private Map<PathArgument, TreeNode> children;
-        private NormalizedNode<?, ?> data;
-        private Version subtreeVersion;
-
-        private Mutable(final ContainerNode parent) {
-            this.data = parent.getData();
-            this.children = MapAdaptor.getDefaultInstance().takeSnapshot(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 TreeNode ret = new ContainerNode(data, version, MapAdaptor.getDefaultInstance().optimize(children), subtreeVersion);
-
-            // This forces a NPE if this class is accessed again. Better than corruption.
-            children = null;
-            return ret;
-        }
-
-        @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
deleted file mode 100644 (file)
index 087f4de..0000000
+++ /dev/null
@@ -1,59 +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.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;
-
-/**
- * A mutable tree node. This is a transient view materialized from a pre-existing
- * node. Modifications are isolated. Once this object is {@link #seal()}-ed,
- * any interactions with it will result in undefined behavior.
- */
-public interface MutableTreeNode extends StoreTreeNode<TreeNode> {
-    /**
-     * Set the data component of the node.
-     *
-     * @param data New data component, may not be null.
-     */
-    void setData(NormalizedNode<?, ?> data);
-
-    /**
-     * Set the new subtree version. This is typically invoked when the user
-     * has modified some of this node's children.
-     *
-     * @param subtreeVersion New subtree version.
-     */
-    void setSubtreeVersion(Version subtreeVersion);
-
-    /**
-     * Add a new child node. This acts as add-or-replace operation, e.g. it
-     * succeeds even if a conflicting child is already present.
-     *
-     * @param child New child node.
-     */
-    void addChild(TreeNode child);
-
-    /**
-     * Remove a child node. This acts as delete-or-nothing operation, e.g. it
-     * succeeds even if the corresponding child is not present.
-     *
-     * @param id Child identificator.
-     */
-    void removeChild(PathArgument id);
-
-    /**
-     * Finish node modification and return a read-only view of this node. After
-     * this method is invoked, any further calls to this object's method result
-     * in undefined behavior.
-     *
-     * @return Read-only view of this node.
-     */
-    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
deleted file mode 100644 (file)
index def1958..0000000
+++ /dev/null
@@ -1,48 +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.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
deleted file mode 100644 (file)
index 9547628..0000000
+++ /dev/null
@@ -1,46 +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.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 entrypoint for other packages. Allows instantiating a tree node
- * with specified version.
- */
-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
deleted file mode 100644 (file)
index d89928b..0000000
+++ /dev/null
@@ -1,48 +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.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;
-
-/**
- * Concretization of AbstractTreeNode for leaf nodes which only contain data.
- * Instances of this class report all children as absent, subtree version
- * equal to this node's version and do not support mutable view.
- */
-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
deleted file mode 100644 (file)
index 09a35d3..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.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
deleted file mode 100644 (file)
index 3291afa..0000000
+++ /dev/null
@@ -1,134 +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.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;
-    }
-}
index e4bd0343cfcf62999d3becca52177eaf8d366bcd..1af03e50465e2acc922f19ad66f15a3c640bfc34 100644 (file)
@@ -7,9 +7,6 @@
  */
 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;
@@ -17,22 +14,29 @@ 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.BrokerService;
 import org.opendaylight.controller.sal.core.api.Consumer;
 import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.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;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableClassToInstanceMap;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private final static Logger log = LoggerFactory.getLogger(BrokerImpl.class);
@@ -43,12 +47,18 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private final Set<ProviderContextImpl> providerSessions = Collections
             .synchronizedSet(new HashSet<ProviderContextImpl>());
 
-    private BundleContext bundleContext = null;
-
     private AutoCloseable deactivator = null;
 
     private RpcRouter router = null;
 
+    private final ClassToInstanceMap<BrokerService> services;
+
+    public  BrokerImpl(final RpcRouter router,final ClassToInstanceMap<BrokerService> services) {
+        this.router = Preconditions.checkNotNull(router, "RPC Router must not be null");
+        this.services = ImmutableClassToInstanceMap.copyOf(services);
+    }
+
+
     @Override
     public ConsumerSession registerConsumer(final Consumer consumer,
             final BundleContext ctx) {
@@ -79,8 +89,9 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private void checkPredicates(final Provider prov) {
         Preconditions.checkNotNull(prov, "Provider should not be null.");
         for (ProviderContextImpl session : providerSessions) {
-            if (prov.equals(session.getProvider()))
+            if (prov.equals(session.getProvider())) {
                 throw new IllegalStateException("Provider already registered");
+            }
         }
 
     }
@@ -88,23 +99,22 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private void checkPredicates(final Consumer cons) {
         Preconditions.checkNotNull(cons, "Consumer should not be null.");
         for (ConsumerContextImpl session : sessions) {
-            if (cons.equals(session.getConsumer()))
+            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);
+        ConsumerContextImpl ret = new ConsumerContextImpl(provider, this);
         return ret;
     }
 
     private ProviderContextImpl newSessionFor(final Provider provider,
             final BundleContext ctx) {
-        ProviderContextImpl ret = new ProviderContextImpl(provider, ctx);
-        ret.setBroker(this);
+        ProviderContextImpl ret = new ProviderContextImpl(provider, this);
         return ret;
     }
 
@@ -164,21 +174,6 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
         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
      */
@@ -208,4 +203,9 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     public void setRouter(final RpcRouter router) {
         this.router = router;
     }
+
+    protected <T extends BrokerService> Optional<T> getGlobalService(final Class<T> service) {
+        return Optional.fromNullable(services.getInstance(service));
+    }
+
 }
index fa81bc9040849c6b198187c4d846de308bfbe685..e96b242720e88bbabe918cbde127af6eb0b3d5e8 100644 (file)
@@ -20,9 +20,9 @@ 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.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ClassToInstanceMap;
 import com.google.common.collect.MutableClassToInstanceMap;
 
@@ -30,41 +30,39 @@ 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;
+    public ConsumerContextImpl(final Consumer provider, final BrokerImpl brokerImpl) {
+        broker = brokerImpl;
+        consumer = provider;
     }
 
     @Override
     public Future<RpcResult<CompositeNode>> rpc(final QName rpc,
             final CompositeNode input) {
+        checkNotClosed();
         return broker.invokeRpcAsync(rpc, input);
     }
 
     @Override
     public <T extends BrokerService> T getService(final Class<T> service) {
+        checkNotClosed();
         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) {
+        final Optional<T> serviceImpl = broker.getGlobalService(service);
+        if(serviceImpl.isPresent()) {
+            final T ret = ProxyFactory.createProxy(null,serviceImpl.get());
             instantiatedServices.putInstance(service, ret);
+            return ret;
+        } else {
+            return null;
         }
-        return ret;
     }
 
     @Override
@@ -83,6 +81,7 @@ class ConsumerContextImpl implements ConsumerSession {
             }
         }
         broker.consumerSessionClosed(this);
+        broker = null;
     }
 
     @Override
@@ -93,22 +92,19 @@ class ConsumerContextImpl implements ConsumerSession {
     /**
      * @return the broker
      */
-    public BrokerImpl getBroker() {
+    protected final  BrokerImpl getBrokerChecked() {
+        checkNotClosed();
         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;
     }
+
+    protected final void checkNotClosed()  {
+        Preconditions.checkState(!closed, "Session is closed.");
+    }
 }
index 430963a884b4fbaa71a7c3c12d5df9356058be0c..60a7e81c4c046183e6ee59e0f27d48e5a15e90bc 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.dom.broker;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -50,11 +51,29 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     private ServiceTracker<SchemaServiceListener, SchemaServiceListener> listenerTracker;
     private BundleTracker<Iterable<Registration<URL>>> bundleTracker;
     private boolean starting = true;
+    private static GlobalBundleScanningSchemaServiceImpl instance;
 
-    public GlobalBundleScanningSchemaServiceImpl(final BundleContext context) {
+    private GlobalBundleScanningSchemaServiceImpl(final BundleContext context) {
         this.context = Preconditions.checkNotNull(context);
     }
 
+    public synchronized static GlobalBundleScanningSchemaServiceImpl createInstance(final BundleContext ctx) {
+        Preconditions.checkState(instance == null);
+        instance = new GlobalBundleScanningSchemaServiceImpl(ctx);
+        instance.start();
+        return instance;
+    }
+
+    public synchronized static GlobalBundleScanningSchemaServiceImpl getInstance() {
+        Preconditions.checkState(instance != null, "Global Instance was not instantiated");
+        return instance;
+    }
+
+    @VisibleForTesting
+    public static synchronized void destroyInstance() {
+        instance = null;
+    }
+
     public BundleContext getContext() {
         return context;
     }
@@ -96,7 +115,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     }
 
     @Override
-    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(final SchemaServiceListener listener) {
+    public synchronized ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(final SchemaServiceListener listener) {
         Optional<SchemaContext> potentialCtx = contextResolver.getSchemaContext();
         if(potentialCtx.isPresent()) {
             listener.onGlobalContextUpdated(potentialCtx.get());
@@ -116,7 +135,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     }
 
 
-    private void updateContext(final SchemaContext snapshot) {
+    private synchronized void updateContext(final SchemaContext snapshot) {
         Object[] services = listenerTracker.getServices();
         for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
             try {
@@ -194,7 +213,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     }
 
     @Override
-    public SchemaServiceListener addingService(final ServiceReference<SchemaServiceListener> reference) {
+    public synchronized SchemaServiceListener addingService(final ServiceReference<SchemaServiceListener> reference) {
 
         SchemaServiceListener listener = context.getService(reference);
         SchemaContext _ctxContext = getGlobalContext();
index 623bbdb19514ce15ffa0b9102959fbac77cb51d2..e69343d4fe82c7f36a7a9c378c8669e67cb1114b 100644 (file)
@@ -54,7 +54,7 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
 
     private SchemaContext schemaContext;
 
-    public MountPointImpl(InstanceIdentifier path) {
+    public MountPointImpl(final InstanceIdentifier path) {
         this.mountPath = path;
         rpcs = new SchemaAwareRpcBroker(path.toString(),this);
         dataReader = new DataBrokerImpl();
@@ -71,49 +71,49 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
     }
 
     @Override
-    public void publish(CompositeNode notification) {
+    public void publish(final CompositeNode notification) {
         notificationRouter.publish(notification);
     }
 
     @Override
-    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+    public Registration<NotificationListener> addNotificationListener(final QName notification, final NotificationListener listener) {
         return notificationRouter.addNotificationListener(notification, listener);
     }
 
     @Override
-    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+    public CompositeNode readConfigurationData(final InstanceIdentifier path) {
         return dataReader.readConfigurationData(path);
     }
 
     @Override
-    public CompositeNode readOperationalData(InstanceIdentifier path) {
+    public CompositeNode readOperationalData(final InstanceIdentifier path) {
         return dataReader.readOperationalData(path);
     }
 
     @Override
     public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
-            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+            final InstanceIdentifier path, final DataReader<InstanceIdentifier, CompositeNode> reader) {
         return dataReader.registerOperationalReader(path, reader);
     }
 
     @Override
     public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
-            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+            final InstanceIdentifier path, final DataReader<InstanceIdentifier, CompositeNode> reader) {
         return dataReader.registerConfigurationReader(path, reader);
     }
 
     @Override
-    public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
+    public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
         return rpcs.addRoutedRpcImplementation(rpcType, implementation);
     }
 
     @Override
-    public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultImplementation) {
-      rpcs.setRoutedRpcDefaultDelegate(defaultImplementation);
+    public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultImplementation) {
+        rpcs.setRoutedRpcDefaultDelegate(defaultImplementation);
     }
 
-  @Override
-    public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
+    @Override
+    public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
             throws IllegalArgumentException {
         return rpcs.addRpcImplementation(rpcType, implementation);
     }
@@ -124,17 +124,17 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
     }
 
     @Override
-    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
         return rpcs.invokeRpc(rpc, input);
     }
 
     @Override
-    public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener) {
+    public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(final RpcRegistrationListener listener) {
         return rpcs.addRpcRegistrationListener(listener);
     }
 
     @Override
-    public ListenableFuture<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input) {
+    public ListenableFuture<RpcResult<CompositeNode>> rpc(final QName type, final CompositeNode input) {
         return rpcs.invokeRpc( type, input );
     }
 
@@ -144,33 +144,33 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
     }
 
     @Override
-    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
-            DataChangeListener listener) {
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier path,
+            final DataChangeListener listener) {
         return dataReader.registerDataChangeListener(path, listener);
     }
 
     @Override
     public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
-            InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+            final InstanceIdentifier path, final DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
         return dataReader.registerCommitHandler(path, commitHandler);
     }
 
     @Override
-    public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
-     // NOOP
+    public void removeRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
+        // NOOP
     }
 
     @Override
-    public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
-     // NOOP
+    public void addRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
+        // NOOP
     }
 
     @Override
-    public void addValidator(DataStoreIdentifier store, DataValidator validator) {
-     // NOOP
+    public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
+        // NOOP
     }
     @Override
-    public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+    public void removeValidator(final DataStoreIdentifier store, final DataValidator validator) {
         // NOOP
     }
 
@@ -180,24 +180,22 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
     }
 
     @Override
-    public void setSchemaContext(SchemaContext schemaContext) {
+    public void setSchemaContext(final SchemaContext schemaContext) {
         this.schemaContext = schemaContext;
     }
 
     class ReadWrapper implements DataReader<InstanceIdentifier, CompositeNode> {
-
-
-        private InstanceIdentifier shortenPath(InstanceIdentifier path) {
+        private InstanceIdentifier shortenPath(final InstanceIdentifier path) {
             InstanceIdentifier ret = null;
             if(mountPath.contains(path)) {
                 List<PathArgument> newArgs = path.getPath().subList(mountPath.getPath().size(), path.getPath().size());
-                ret = new InstanceIdentifier(newArgs);
+                ret = InstanceIdentifier.create(newArgs);
             }
             return ret;
         }
 
         @Override
-        public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        public CompositeNode readConfigurationData(final InstanceIdentifier path) {
             InstanceIdentifier newPath = shortenPath(path);
             if(newPath == null) {
                 return null;
@@ -206,7 +204,7 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
         }
 
         @Override
-        public CompositeNode readOperationalData(InstanceIdentifier path) {
+        public CompositeNode readOperationalData(final InstanceIdentifier path) {
             InstanceIdentifier newPath = shortenPath(path);
             if(newPath == null) {
                 return null;
@@ -217,13 +215,13 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
 
     @Override
     public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier, CompositeNode>>> registerCommitHandlerListener(
-            RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier, CompositeNode>> commitHandlerListener) {
+            final RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier, CompositeNode>> commitHandlerListener) {
         return dataReader.registerCommitHandlerListener(commitHandlerListener);
     }
 
     @Override
     public <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
-            L listener) {
+            final L listener) {
         return rpcs.registerRouteChangeListener(listener);
     }
 }
index 5e8c0e82538b4d2beacddd3366571ac2a734f7c5..b8bb279297cf835cb185d909d6eaf280dccc59d7 100644 (file)
@@ -18,21 +18,20 @@ 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);
+    public ProviderContextImpl(final Provider provider, final BrokerImpl broker) {
+        super(null, broker);
         this.provider = provider;
     }
 
     @Override
     public RpcRegistrationWrapper addRpcImplementation(final QName rpcType,
             final RpcImplementation implementation) throws IllegalArgumentException {
-        final RpcRegistration origReg = getBroker().getRouter()
+        final RpcRegistration origReg = getBrokerChecked().getRouter()
                 .addRpcImplementation(rpcType, implementation);
         final RpcRegistrationWrapper newReg = new RpcRegistrationWrapper(
                 origReg);
@@ -56,24 +55,24 @@ class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession
             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");
+        return getBrokerChecked().getRouter().addRoutedRpcImplementation(rpcType, implementation);
     }
 
     @Override
     public Set<QName> getSupportedRpcs() {
-        return getBroker().getRouter().getSupportedRpcs();
+        return getBrokerChecked().getRouter().getSupportedRpcs();
     }
 
     @Override
     public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
             final RpcRegistrationListener listener) {
-        return getBroker().getRouter().addRpcRegistrationListener(listener);
+        return getBrokerChecked().getRouter().addRpcRegistrationListener(listener);
     }
 
     /**
index ba9b2b7f55964d90023532082bc41767f037daa4..4b5b86d0dafd2cc08df1f7c9a31086350e3b3512 100644 (file)
@@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.dom.broker.impl;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.collect.Iterables;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -32,8 +34,6 @@ 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
@@ -46,7 +46,7 @@ AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
     @Override
     protected CompositeNodeTOImpl merge(final InstanceIdentifier path,
             final Iterable<CompositeNode> data) {
-        PathArgument pathArgument = Iterables.getLast(path.getPath(), null);
+        PathArgument pathArgument = Iterables.getLast(path.getPathArguments(), null);
         boolean empty = true;
         QName name = (pathArgument == null ? null : pathArgument.getNodeType());
         final ArrayList<Node<?>> nodes = new ArrayList<Node<?>>();
index 1a572d157dba9f8272140495b8eabf9669df11bc..3cd7ed5e13ed16b2449f2386604aa81802679b17 100644 (file)
@@ -9,6 +9,11 @@ package org.opendaylight.controller.sal.dom.broker.impl;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -40,10 +45,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableSet;
-
 public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
 DataStore, //
 SchemaContextListener, //
@@ -235,7 +236,7 @@ AutoCloseable {
         public CompositeNode readConfigurationData(final InstanceIdentifier path) {
             getDelegateReadLock().lock();
             try {
-                if (path.getPath().isEmpty()) {
+                if (Iterables.isEmpty(path.getPathArguments())) {
                     return null;
                 }
                 QName qname = null;
@@ -278,7 +279,7 @@ AutoCloseable {
         public CompositeNode readOperationalData(final InstanceIdentifier path) {
             getDelegateReadLock().lock();
             try {
-                if (path.getPath().isEmpty()) {
+                if (Iterables.isEmpty(path.getPathArguments())) {
                     return null;
                 }
                 QName qname = null;
index 853e3e391f591a8b3d6c5aad72d5d62da0093471..8d33ff7997dab4b2a09d813c9200e8b95f7dc762 100644 (file)
@@ -14,6 +14,8 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
+import javax.annotation.Nullable;
+
 import org.opendaylight.controller.sal.core.api.BrokerService;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.osgi.framework.ServiceReference;
@@ -23,9 +25,9 @@ public abstract class AbstractBrokerServiceProxy<T extends BrokerService> implem
     private T delegate;
     private final ServiceReference<T> reference;
 
-    public AbstractBrokerServiceProxy(final ServiceReference<T> ref, final T delegate) {
+    public AbstractBrokerServiceProxy(final @Nullable ServiceReference<T> ref, final T delegate) {
         this.delegate = checkNotNull(delegate, "Delegate should not be null.");
-        this.reference = checkNotNull(ref, "Reference should not be null.");
+        this.reference = ref;
     }
 
     protected final T getDelegate() {
index b0ccfb995db612188cff2bbb5014def94911e4d7..4f44f361d5d352e51378a681ef57dc48ebddd78c 100644 (file)
@@ -4,7 +4,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
@@ -19,7 +19,7 @@ public class DOMDataBrokerProxy extends AbstractBrokerServiceProxy<DOMDataBroker
     }
 
     @Override
-    public DOMDataReadTransaction newReadOnlyTransaction() {
+    public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
         return getDelegate().newReadOnlyTransaction();
     }
 
index f893f96d18c59e94df9fe7961b8856b214a6f196..113a9c08dbe064f2d8d2066ee94dd8a1e0952505 100644 (file)
@@ -23,7 +23,7 @@ public class SchemaServiceActivator implements BundleActivator {
 
     @Override
     public void start(final BundleContext context) {
-        schemaService = new GlobalBundleScanningSchemaServiceImpl(context);
+        schemaService = GlobalBundleScanningSchemaServiceImpl.createInstance(context);
         schemaService.start();
         schemaServiceReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String,String>());
     }
index 0f8ce1d95d31f727c018a9f801dca421c73f8a32..5adf39142ec5ee2af194b921a76b2ce01031ffd5 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.controller.sal.dom.broker.util;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -29,9 +32,6 @@ 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,
@@ -84,10 +84,10 @@ public class YangDataOperations {
         }
         @SuppressWarnings({ "unchecked", "rawtypes" })
         final Map<Map<QName, Object>, CompositeNode> originalMap = YangDataUtils
-                .toIndexMap((List) original, node.getKeyDefinition());
+        .toIndexMap((List) original, node.getKeyDefinition());
         @SuppressWarnings({ "unchecked", "rawtypes" })
         final Map<Map<QName, Object>, CompositeNode> modifiedMap = YangDataUtils
-                .toIndexMap((List) modified, node.getKeyDefinition());
+        .toIndexMap((List) modified, node.getKeyDefinition());
 
         final List<Node<?>> mergedNodes = new ArrayList<Node<?>>(
                 original.size() + modified.size());
@@ -140,7 +140,7 @@ public class YangDataOperations {
                 modified.getNodeType()));
 
         final List<Node<?>> mergedChildNodes = new ArrayList<Node<?>>(stored
-                .getChildren().size() + modified.getChildren().size());
+                .getValue().size() + modified.getValue().size());
         final Set<QName> toProcess = new HashSet<QName>(stored.keySet());
         toProcess.addAll(modified.keySet());
 
index 306cd34a69502187084bec2a33643cac5231e979..29392dc7b3e91e6c6dbe202cbe1b4e4292cce17d 100644 (file)
@@ -10,6 +10,9 @@ package org.opendaylight.controller.sal.dom.broker.util;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -34,9 +37,6 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 
-import com.google.common.base.Function;
-import com.google.common.collect.FluentIterable;
-
 public final class YangSchemaUtils {
 
     private static final Function<PathArgument, QName> QNAME_FROM_PATH_ARGUMENT = new Function<PathArgument, QName>(){
@@ -57,7 +57,7 @@ public final class YangSchemaUtils {
     public static DataSchemaNode getSchemaNode(final SchemaContext schema,final InstanceIdentifier path) {
         checkArgument(schema != null,"YANG Schema must not be null.");
         checkArgument(path != null,"Path must not be null.");
-        return getSchemaNode(schema, FluentIterable.from(path.getPath()).transform(QNAME_FROM_PATH_ARGUMENT));
+        return getSchemaNode(schema, FluentIterable.from(path.getPathArguments()).transform(QNAME_FROM_PATH_ARGUMENT));
     }
 
     public static DataSchemaNode getSchemaNode(final SchemaContext schema,final Iterable<QName> path) {
index 3c29fe588567dafee48c5f4e628e4eb22a8364fc..a0ee5c50c93bc8a576c2d71b2dd7b37b86cda896 100644 (file)
@@ -6,9 +6,14 @@ module opendaylight-sal-dom-broker-impl {
        import config { prefix config; revision-date 2013-04-05; }
        import opendaylight-md-sal-dom {prefix sal;}
        import opendaylight-md-sal-common {prefix common;}
+       import opendaylight-config-dom-datastore {prefix config-dom-store-spi;}
+       import opendaylight-operational-dom-datastore {prefix operational-dom-store-spi;}
 
     description
-        "Service definition for Binding Aware MD-SAL.";
+        "Service definition for Binding Aware MD-SAL.
+        Note: The dom-inmemory-data-broker utilizes configurable config-dom-datastore
+        and operation-dom-datastore. If configuration is not done for this stores
+        then it defaults to InMemoryDOMDataStore";
  
     revision "2013-10-28" {
         description
@@ -50,7 +55,7 @@ module opendaylight-sal-dom-broker-impl {
                     }
                 }
             }
-            
+
             container async-data-broker {
                 uses config:service-ref {
                     refine type {
@@ -58,7 +63,15 @@ module opendaylight-sal-dom-broker-impl {
                         config:required-identity sal:dom-async-data-broker;
                     }
                 }
-            
+            }
+
+            container root-schema-service {
+                uses config:service-ref {
+                    refine type {
+                        mandatory false;
+                        config:required-identity sal:schema-service;
+                    }
+                }
             }
         }
     }
@@ -66,7 +79,8 @@ module opendaylight-sal-dom-broker-impl {
     augment "/config:modules/config:module/config:configuration" {
         case dom-inmemory-data-broker {
             when "/config:modules/config:module/config:type = 'dom-inmemory-data-broker'";
-            
+
+
             container schema-service {
                 uses config:service-ref {
                     refine type {
@@ -74,7 +88,25 @@ module opendaylight-sal-dom-broker-impl {
                         config:required-identity sal:schema-service;
                     }
                 }
-            
+
+            }
+
+            container config-data-store{
+                 uses config:service-ref {
+                     refine type {
+                         mandatory false;
+                         config:required-identity  config-dom-store-spi:config-dom-datastore;
+                     }
+                 }
+            }
+
+            container operational-data-store{
+                  uses config:service-ref {
+                       refine type {
+                           mandatory false;
+                           config:required-identity operational-dom-store-spi:operational-dom-datastore;
+                       }
+                   }
             }
         }
     }
index 66d57f9f87ae9181b549f2a2029b938509473618..29e078918e65eeae080f62c61d6ce5bae4fc3a9f 100644 (file)
@@ -63,8 +63,8 @@ public class DOMBrokerPerformanceTest {
 
     @Before
     public void setupStore() {
-        InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", MoreExecutors.sameThreadExecutor());
-        InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", MoreExecutors.sameThreadExecutor());
+       InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", MoreExecutors.sameThreadExecutor());
+       InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", MoreExecutors.sameThreadExecutor());
         schemaContext = TestModel.createTestContext();
 
         operStore.onGlobalContextUpdated(schemaContext);
index 2a955e5f4215e6dccc0c397ca9c0850ccb159aa3..38f08b30f94ea37d4e73e3537c5c7bd798eb12ed 100644 (file)
@@ -104,28 +104,29 @@ public class DOMTransactionChainTest {
          */
         DOMDataReadWriteTransaction thirdDeleteTx = allocateAndDelete(txChain);
 
-        /**
-         * third transaction is sealed.
-         */
-        ListenableFuture<RpcResult<TransactionStatus>> thirdDeleteTxFuture = thirdDeleteTx.commit();
-
         /**
          * We commit first transaction
          *
          */
         assertCommitSuccessful(firstWriteTxFuture);
 
-        // Alocates store transaction
+        /**
+         *
+         * Allocates transaction from data store.
+         *
+         */
         DOMDataReadTransaction storeReadTx = domBroker.newReadOnlyTransaction();
+
         /**
          * We verify transaction is commited to store, container should exists
          * in datastore.
          */
         assertTestContainerExists(storeReadTx);
+
         /**
-         * We commit third transaction
-         *
+         * third transaction is sealed and commited
          */
+        ListenableFuture<RpcResult<TransactionStatus>> thirdDeleteTxFuture = thirdDeleteTx.commit();
         assertCommitSuccessful(thirdDeleteTxFuture);
 
         /**
diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DataNormalizerTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DataNormalizerTest.java
deleted file mode 100644 (file)
index ac7b87a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.opendaylight.controller.md.sal.dom.broker.impl;
-
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
-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.Node;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class DataNormalizerTest {
-
-    private static final Short OUTER_LIST_ID = (short)10;
-
-    private static final InstanceIdentifier OUTER_LIST_PATH_LEGACY = InstanceIdentifier.builder(TestModel.TEST_QNAME)
-            .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME,OUTER_LIST_ID).build();
-
-    private  static final InstanceIdentifier LEAF_TWO_PATH_LEGACY = InstanceIdentifier.builder(OUTER_LIST_PATH_LEGACY)
-            .node(TestModel.TWO_QNAME).build();
-
-    private static final ChoiceNode OUTER_CHOICE_ITEM = Builders.choiceBuilder()
-            .withNodeIdentifier(new NodeIdentifier(TestModel.OUTER_CHOICE_QNAME))
-            .withChild(ImmutableNodes.leafNode(TestModel.TWO_QNAME, "two"))
-            .withChild(ImmutableNodes.leafNode(TestModel.THREE_QNAME, "three"))
-            .build();
-
-    private static final MapEntryNode OUTER_LIST_WITHOUT_CHOICE = Builders.mapEntryBuilder()
-            .withNodeIdentifier(new NodeIdentifierWithPredicates(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME,OUTER_LIST_ID))
-            .withChild(ImmutableNodes.leafNode(TestModel.ID_QNAME, OUTER_LIST_ID))
-            .build();
-
-    private static final MapEntryNode OUTER_LIST_WITH_CHOICE = Builders.mapEntryBuilder()
-            .withNodeIdentifier(new NodeIdentifierWithPredicates(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME,OUTER_LIST_ID))
-            .withChild(ImmutableNodes.leafNode(TestModel.ID_QNAME, OUTER_LIST_ID))
-            .withChild(OUTER_CHOICE_ITEM)
-            .build();
-
-    @Test
-    public void test() {
-        SchemaContext testCtx = TestModel.createTestContext();
-        DataNormalizer normalizer = new DataNormalizer(testCtx);
-
-        InstanceIdentifier normalizedPath = normalizer.toNormalized(LEAF_TWO_PATH_LEGACY);
-
-        Node<?> outerListLegacy = DataNormalizer.toLegacy(OUTER_LIST_WITH_CHOICE);
-        assertNotNull(outerListLegacy);
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java
deleted file mode 100644 (file)
index 413d81d..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-package org.opendaylight.controller.md.sal.dom.store.impl;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-
-public class InMemoryDataStoreTest {
-
-    private SchemaContext schemaContext;
-    private InMemoryDOMDataStore domStore;
-
-    @Before
-    public void setupStore() {
-        domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.sameThreadExecutor());
-        schemaContext = TestModel.createTestContext();
-        domStore.onGlobalContextUpdated(schemaContext);
-
-    }
-
-    @Test
-    public void testTransactionIsolation() throws InterruptedException, ExecutionException {
-
-        assertNotNull(domStore);
-
-        DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
-        assertNotNull(readTx);
-
-        DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
-        assertNotNull(writeTx);
-        /**
-         *
-         * Writes /test in writeTx
-         *
-         */
-        writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
-        /**
-         *
-         * Reads /test from writeTx Read should return container.
-         *
-         */
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
-        assertTrue(writeTxContainer.get().isPresent());
-
-        /**
-         *
-         * Reads /test from readTx Read should return Absent.
-         *
-         */
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx.read(TestModel.TEST_PATH);
-        assertFalse(readTxContainer.get().isPresent());
-    }
-
-    @Test
-    public void testTransactionCommit() throws InterruptedException, ExecutionException {
-
-        DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
-        assertNotNull(writeTx);
-        /**
-         *
-         * Writes /test in writeTx
-         *
-         */
-        writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
-        /**
-         *
-         * Reads /test from writeTx Read should return container.
-         *
-         */
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
-        assertTrue(writeTxContainer.get().isPresent());
-
-        DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
-
-        assertThreePhaseCommit(cohort);
-
-        Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
-                .get();
-        assertTrue(afterCommitRead.isPresent());
-    }
-
-    @Test
-    public void testTransactionAbort() throws InterruptedException, ExecutionException {
-
-        DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
-        assertNotNull(writeTx);
-
-        assertTestContainerWrite(writeTx);
-
-        DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
-
-        assertTrue(cohort.canCommit().get().booleanValue());
-        cohort.preCommit().get();
-        cohort.abort().get();
-
-        Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
-                .get();
-        assertFalse(afterCommitRead.isPresent());
-    }
-
-    @Test
-    public void testTransactionChain() throws InterruptedException, ExecutionException {
-        DOMStoreTransactionChain txChain = domStore.createTransactionChain();
-        assertNotNull(txChain);
-
-        /**
-         * We alocate new read-write transaction and write /test
-         *
-         *
-         */
-        DOMStoreReadWriteTransaction firstTx = txChain.newReadWriteTransaction();
-        assertTestContainerWrite(firstTx);
-
-        /**
-         * First transaction is marked as ready, we are able to allocate chained
-         * transactions
-         */
-        DOMStoreThreePhaseCommitCohort firstWriteTxCohort = firstTx.ready();
-
-        /**
-         * We alocate chained transaction - read transaction, note first one is
-         * still not commited to datastore.
-         */
-        DOMStoreReadTransaction secondReadTx = txChain.newReadOnlyTransaction();
-
-        /**
-         *
-         * We test if we are able to read data from tx, read should not fail
-         * since we are using chained transaction.
-         *
-         *
-         */
-        assertTestContainerExists(secondReadTx);
-
-        /**
-         *
-         * We alocate next transaction, which is still based on first one, but
-         * is read-write.
-         *
-         */
-        DOMStoreReadWriteTransaction thirdDeleteTx = txChain.newReadWriteTransaction();
-
-        /**
-         * We test existence of /test in third transaction container should
-         * still be visible from first one (which is still uncommmited).
-         *
-         *
-         */
-        assertTestContainerExists(thirdDeleteTx);
-
-        /**
-         * We delete node in third transaction
-         */
-        thirdDeleteTx.delete(TestModel.TEST_PATH);
-
-        /**
-         * third transaction is sealed.
-         */
-        DOMStoreThreePhaseCommitCohort thirdDeleteTxCohort = thirdDeleteTx.ready();
-
-        /**
-         * We commit first transaction
-         *
-         */
-        assertThreePhaseCommit(firstWriteTxCohort);
-
-        // Alocates store transacion
-        DOMStoreReadTransaction storeReadTx = domStore.newReadOnlyTransaction();
-        /**
-         * We verify transaction is commited to store, container should exists
-         * in datastore.
-         */
-        assertTestContainerExists(storeReadTx);
-        /**
-         * We commit third transaction
-         *
-         */
-        assertThreePhaseCommit(thirdDeleteTxCohort);
-    }
-
-    @Test
-    @Ignore
-    public void testTransactionConflict() throws InterruptedException, ExecutionException {
-        DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
-        DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
-        assertTestContainerWrite(txOne);
-        assertTestContainerWrite(txTwo);
-
-        /**
-         * Commits transaction
-         */
-        assertThreePhaseCommit(txOne.ready());
-
-        /**
-         * Asserts that txTwo could not be commited
-         */
-        assertFalse(txTwo.ready().canCommit().get());
-    }
-
-    private static void assertThreePhaseCommit(final DOMStoreThreePhaseCommitCohort cohort)
-            throws InterruptedException, ExecutionException {
-        assertTrue(cohort.canCommit().get().booleanValue());
-        cohort.preCommit().get();
-        cohort.commit().get();
-    }
-
-    private static Optional<NormalizedNode<?, ?>> assertTestContainerWrite(final DOMStoreReadWriteTransaction writeTx)
-            throws InterruptedException, ExecutionException {
-        /**
-         *
-         * Writes /test in writeTx
-         *
-         */
-        writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
-        return assertTestContainerExists(writeTx);
-    }
-
-    /**
-     *
-     * Reads /test from readTx Read should return container.
-     *
-     */
-    private static Optional<NormalizedNode<?, ?>> assertTestContainerExists(DOMStoreReadTransaction readTx)
-            throws InterruptedException, ExecutionException {
-
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = readTx.read(TestModel.TEST_PATH);
-        assertTrue(writeTxContainer.get().isPresent());
-        return writeTxContainer.get();
-    }
-
-}
index 2c965047dbf1dea8112a2b8b4fe9bc414ae34665..91aa57c25957a392bffb82f092c4b19f0a5ba4ed 100644 (file)
@@ -7,16 +7,16 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.Set;
-
 import org.opendaylight.yangtools.yang.common.QName;
 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 org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+
 public class TestModel {
 
     public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java
deleted file mode 100644 (file)
index 4fb190f..0000000
+++ /dev/null
@@ -1,259 +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.data;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.ID_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.INNER_LIST_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.NAME_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.OUTER_LIST_PATH;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.OUTER_LIST_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.TEST_PATH;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.TEST_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.VALUE_QNAME;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
-
-import org.junit.Before;
-import org.junit.Test;
-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;
-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.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import com.google.common.base.Optional;
-
-/**
- *
- * Schema structure of document is
- *
- * <pre>
- * container root { 
- *      list list-a {
- *              key leaf-a;
- *              leaf leaf-a;
- *              choice choice-a {
- *                      case one {
- *                              leaf one;
- *                      }
- *                      case two-three {
- *                              leaf two;
- *                              leaf three;
- *                      }
- *              }
- *              list list-b {
- *                      key leaf-b;
- *                      leaf leaf-b;
- *              }
- *      }
- * }
- * </pre>
- *
- */
-public class ModificationMetadataTreeTest {
-
-    private static final Short ONE_ID = 1;
-    private static final Short TWO_ID = 2;
-    private static final String TWO_ONE_NAME = "one";
-    private static final String TWO_TWO_NAME = "two";
-
-    private static final InstanceIdentifier OUTER_LIST_1_PATH = InstanceIdentifier.builder(OUTER_LIST_PATH)
-            .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, ONE_ID) //
-            .build();
-
-    private static final InstanceIdentifier OUTER_LIST_2_PATH = InstanceIdentifier.builder(OUTER_LIST_PATH)
-            .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
-            .build();
-
-    private static final InstanceIdentifier TWO_TWO_PATH = InstanceIdentifier.builder(OUTER_LIST_2_PATH)
-            .node(INNER_LIST_QNAME) //
-            .nodeWithKey(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME) //
-            .build();
-
-    private static final InstanceIdentifier TWO_TWO_VALUE_PATH = InstanceIdentifier.builder(TWO_TWO_PATH)
-            .node(VALUE_QNAME) //
-            .build();
-
-    private static final MapEntryNode BAR_NODE = mapEntryBuilder(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
-            .withChild(mapNodeBuilder(INNER_LIST_QNAME) //
-                    .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_ONE_NAME)) //
-                    .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME)) //
-                    .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);
-    }
-
-    /**
-     * Returns a test document
-     *
-     * <pre>
-     * test
-     *     outer-list
-     *          id 1
-     *     outer-list
-     *          id 2
-     *          inner-list
-     *                  name "one"
-     *          inner-list
-     *                  name "two"
-     *
-     * </pre>
-     *
-     * @return
-     */
-    public NormalizedNode<?, ?> createDocumentOne() {
-        return ImmutableContainerNodeBuilder
-                .create()
-                .withNodeIdentifier(new NodeIdentifier(schemaContext.getQName()))
-                .withChild(createTestContainer()).build();
-
-    }
-
-    private ContainerNode createTestContainer() {
-        return ImmutableContainerNodeBuilder
-                .create()
-                .withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
-                .withChild(
-                        mapNodeBuilder(OUTER_LIST_QNAME)
-                        .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
-                        .withChild(BAR_NODE).build()).build();
-    }
-
-    @Test
-    public void basicReadWrites() {
-        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());
-
-        // writes node to /outer-list/1/inner_list/two/value
-        modificationTree.write(TWO_TWO_VALUE_PATH, ImmutableNodes.leafNode(VALUE_QNAME, "test"));
-
-        // reads node to /outer-list/1/inner_list/two/value
-        // and checks if node is already present
-        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.readNode(TWO_TWO_VALUE_PATH);
-        assertFalse(barTwoCAfterDelete.isPresent());
-    }
-
-
-    public DataTreeModification createEmptyModificationTree() {
-        /**
-         * Creates empty Snapshot with associated schema context.
-         */
-        DataTree t = InMemoryDataTreeFactory.getInstance().create();
-        t.setSchemaContext(schemaContext);
-
-        /**
-         *
-         * Creates Mutable Data Tree based on provided snapshot and schema
-         * context.
-         *
-         */
-        return t.takeSnapshot().newModification();
-    }
-
-    @Test
-    public void createFromEmptyState() {
-
-        DataTreeModification modificationTree = createEmptyModificationTree();
-        /**
-         * Writes empty container node to /test
-         *
-         */
-        modificationTree.write(TEST_PATH, ImmutableNodes.containerNode(TEST_QNAME));
-
-        /**
-         * Writes empty list node to /test/outer-list
-         */
-        modificationTree.write(OUTER_LIST_PATH, ImmutableNodes.mapNodeBuilder(OUTER_LIST_QNAME).build());
-
-        /**
-         * Reads list node from /test/outer-list
-         */
-        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.readNode(TEST_PATH);
-        ContainerNode containerTest = assertPresentAndType(potentialTest, ContainerNode.class);
-
-        /**
-         *
-         * Gets list from returned snapshot of /test and verifies it contains
-         * outer-list
-         *
-         */
-        assertPresentAndType(containerTest.getChild(new NodeIdentifier(OUTER_LIST_QNAME)), MapNode.class);
-
-    }
-
-    @Test
-    public void writeSubtreeReadChildren() {
-        DataTreeModification modificationTree = createEmptyModificationTree();
-        modificationTree.write(TEST_PATH, createTestContainer());
-        Optional<NormalizedNode<?, ?>> potential = modificationTree.readNode(TWO_TWO_PATH);
-        assertPresentAndType(potential, MapEntryNode.class);
-    }
-
-    @Test
-    public void writeSubtreeDeleteChildren() {
-        DataTreeModification modificationTree = createEmptyModificationTree();
-        modificationTree.write(TEST_PATH, createTestContainer());
-
-        // We verify data are present
-        Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.readNode(TWO_TWO_PATH);
-        assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
-
-        modificationTree.delete(TWO_TWO_PATH);
-        Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.readNode(TWO_TWO_PATH);
-        assertFalse(potentialAfterDelete.isPresent());
-
-    }
-
-    private static <T> T assertPresentAndType(final Optional<?> potential, final Class<T> type) {
-        assertNotNull(potential);
-        assertTrue(potential.isPresent());
-        assertTrue(type.isInstance(potential.get()));
-        return type.cast(potential.get());
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java
deleted file mode 100644 (file)
index 03ece2f..0000000
+++ /dev/null
@@ -1,39 +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.data;
-
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class SchemaAwareApplyOperationRoot extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
-    private final SchemaContext context;
-
-    public SchemaAwareApplyOperationRoot(final SchemaContext context) {
-        super(context,ContainerNode.class);
-        this.context = context;
-    }
-
-    public SchemaContext getContext() {
-        return context;
-    }
-
-    @Override
-    public String toString() {
-        return "SchemaAwareApplyOperationRoot [context=" + context + "]";
-    }
-
-    @Override
-    @SuppressWarnings("rawtypes")
-    protected DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original) {
-        return ImmutableContainerNodeBuilder.create((ContainerNode) original);
-    }
-}
index 660a67923ffe5ba06a37484a571505c801af7931..88ac86a45e3f6259a53da0e71f4fb5f2f6a8ed50 100644 (file)
       <artifactId>sal-core-api</artifactId>
     </dependency>
   </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yang-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>config</id>
+            <goals>
+              <goal>generate-sources</goal>
+            </goals>
+            <configuration>
+              <codeGenerators>
+                <generator>
+                  <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                  <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                  <additionalConfiguration>
+                    <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                  </additionalConfiguration>
+                </generator>
+                <generator>
+                  <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                  <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                </generator>
+              </codeGenerators>
+              <inspectDependencies>true</inspectDependencies>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
     <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/yang/opendaylight-config-dom-datastore.yang b/opendaylight/md-sal/sal-dom-spi/src/main/yang/opendaylight-config-dom-datastore.yang
new file mode 100644 (file)
index 0000000..9a3ab18
--- /dev/null
@@ -0,0 +1,22 @@
+module opendaylight-config-dom-datastore {
+       yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store";
+    prefix "config-dom-store-spi";
+
+       import config { prefix config; revision-date 2013-04-05; }
+
+        description
+            "DOM Service Provider Interface definition for MD-SAL config store";
+
+     revision "2014-06-17" {
+             description
+                 "Initial revision";
+         }
+
+     identity config-dom-datastore {
+             base "config:service-type";
+             config:java-class  "org.opendaylight.controller.sal.core.spi.data.DOMStore";
+
+     }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/yang/opendaylight-operational-dom-datastore.yang b/opendaylight/md-sal/sal-dom-spi/src/main/yang/opendaylight-operational-dom-datastore.yang
new file mode 100644 (file)
index 0000000..fd40884
--- /dev/null
@@ -0,0 +1,22 @@
+module opendaylight-operational-dom-datastore {
+       yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store";
+    prefix "operational-dom-store-spi";
+
+       import config { prefix config; revision-date 2013-04-05; }
+
+        description
+            "DOM Service Provider Interface definition for MD-SAL operational store";
+
+     revision "2014-06-17" {
+             description
+                 "Initial revision";
+         }
+
+     identity operational-dom-datastore {
+             base "config:service-type";
+             config:java-class  "org.opendaylight.controller.sal.core.spi.data.DOMStore";
+
+     }
+
+}
\ No newline at end of file
similarity index 57%
rename from opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml
rename to opendaylight/md-sal/sal-inmemory-datastore/pom.xml
index 63b80e91811ce6080d9dec87e1ca84c6a422e14a..dadef821eb349e048d8395f6ab1c24cb39eb89b4 100644 (file)
@@ -5,79 +5,74 @@
     <groupId>org.opendaylight.controller</groupId>
     <artifactId>sal-parent</artifactId>
     <version>1.1-SNAPSHOT</version>
-    <relativePath>../..</relativePath>
   </parent>
 
-  <artifactId>sal-remoterpc-connector</artifactId>
-  <packaging>bundle</packaging>
+  <artifactId>sal-inmemory-datastore</artifactId>
 
-  <properties>
-    <stax.version>1.0.1</stax.version>
-    <zeromq.version>0.3.1</zeromq.version>
-  </properties>
+  <packaging>bundle</packaging>
 
   <dependencies>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>sal-common-util</artifactId>
-      <version>${project.version}</version>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
     </dependency>
+
+    <!-- SAL Dependencies -->
+
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>sal-connector-api</artifactId>
-      <version>${project.version}</version>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-api</artifactId>
     </dependency>
-    <!-- MD Sal interdependencies -->
+
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>sal-core-api</artifactId>
-      <version>${project.version}</version>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-api</artifactId>
     </dependency>
+
     <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-annotations</artifactId>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-config</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-core</artifactId>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-api</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-databind</artifactId>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-util</artifactId>
     </dependency>
+
     <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-core-api</artifactId>
     </dependency>
-
-    <!-- Tests -->
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-core-spi</artifactId>
     </dependency>
+
     <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-all</artifactId>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>concepts</artifactId>
     </dependency>
+
     <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>remoterpc-routingtable.implementation</artifactId>
-      <version>${project.version}</version>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>util</artifactId>
     </dependency>
 
-    <!-- AD Sal -->
     <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-binding</artifactId>
     </dependency>
 
-    <!-- Yang tools -->
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-common</artifactId>
     </dependency>
+
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-api</artifactId>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-impl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-parser-impl</artifactId>
+    </dependency>
 
-    <!-- Third Party -->
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
     </dependency>
+
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.zeromq</groupId>
-      <artifactId>jeromq</artifactId>
-      <version>${zeromq.version}</version>
-    </dependency>
 
+    <!-- Test Dependencies -->
     <dependency>
-      <groupId>stax</groupId>
-      <artifactId>stax-api</artifactId>
-      <version>${stax.version}</version>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>${slf4j.version}</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Import-Package>*,
-                            !org.codehaus.enunciate.jaxrs</Import-Package>
-            <Export-Package>org.opendaylight.controller.config.yang.md.sal.remote.rpc,
-                            org.opendaylight.controller.sal.connector.remoterpc.util,
-                            org.opendaylight.controller.sal.connector.remoterpc.dto,
-                            org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcClient,
-                            org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcServer,
-                            org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcProvider</Export-Package>
             <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+
+            <Export-Package>org.opendaylight.controller.md.sal.dom.store.impl.*</Export-Package>
+
+            <Import-Package>*</Import-Package>
           </instructions>
         </configuration>
       </plugin>
-
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>org.opendaylight.controller.*</include>
+          </includes>
+          <check>false</check>
+        </configuration>
+        <executions>
+          <execution>
+            <id>pre-test</id>
+            <goals>
+              <goal>prepare-agent</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>post-test</id>
+            <goals>
+              <goal>report</goal>
+            </goals>
+            <phase>test</phase>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.opendaylight.yangtools</groupId>
         <artifactId>yang-maven-plugin</artifactId>
         <executions>
           <execution>
+            <id>config</id>
             <goals>
               <goal>generate-sources</goal>
             </goals>
                   <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
                   <outputBaseDir>${salGeneratorPath}</outputBaseDir>
                 </generator>
-                <generator>
-                  <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
-                  <outputBaseDir>target/site/models</outputBaseDir>
-                </generator>
-
-                <generator>
-                  <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
-                  <outputBaseDir>target/site/models</outputBaseDir>
-                </generator>
               </codeGenerators>
               <inspectDependencies>true</inspectDependencies>
             </configuration>
       </plugin>
     </plugins>
   </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:Clustering</url>
+  </scm>
+
 </project>
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java
new file mode 100644 (file)
index 0000000..3ed02df
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+
+import com.google.common.util.concurrent.MoreExecutors;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+
+public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryConfigDataStoreProviderModule {
+    public InMemoryConfigDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public InMemoryConfigDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryConfigDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+      InMemoryDOMDataStore   ids = new InMemoryDOMDataStore("DOM-CFG", MoreExecutors.sameThreadExecutor());
+      getSchemaServiceDependency().registerSchemaServiceListener(ids);
+      return ids;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModuleFactory.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModuleFactory.java
new file mode 100644 (file)
index 0000000..1931c14
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: opendaylight-inmemory-datastore-provider yang module local name: inmemory-config-datastore-provider
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jun 19 17:10:42 PDT 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+public class InMemoryConfigDataStoreProviderModuleFactory extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryConfigDataStoreProviderModuleFactory {
+
+}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java
new file mode 100644 (file)
index 0000000..eea9599
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+
+import com.google.common.util.concurrent.MoreExecutors;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+
+public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryOperationalDataStoreProviderModule {
+    public InMemoryOperationalDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public InMemoryOperationalDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryOperationalDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+      InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-OPER", MoreExecutors.sameThreadExecutor());
+      getSchemaServiceDependency().registerSchemaServiceListener(ids);
+      return ids;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModuleFactory.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModuleFactory.java
new file mode 100644 (file)
index 0000000..49bc6a2
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: opendaylight-inmemory-datastore-provider yang module local name: inmemory-operational-datastore-provider
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jun 19 17:10:42 PDT 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+public class InMemoryOperationalDataStoreProviderModuleFactory extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryOperationalDataStoreProviderModuleFactory {
+
+}
@@ -7,27 +7,25 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collections;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.annotation.concurrent.GuardedBy;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
 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.common.api.data.OptimisticLockFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction.TransactionReadyPrototype;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ConflictingModificationAppliedException;
-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.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.InMemoryDataTreeFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.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;
@@ -44,12 +42,12 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
+import javax.annotation.concurrent.GuardedBy;
+import java.util.Collections;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static com.google.common.base.Preconditions.checkState;
 
 /**
  * In-memory DOM Data Store
@@ -61,12 +59,13 @@ import com.google.common.util.concurrent.ListeningExecutorService;
  *
  */
 public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, SchemaContextListener,
-        TransactionReadyPrototype {
+        TransactionReadyPrototype,AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
     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;
 
     public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) {
@@ -104,6 +103,10 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         dataTree.setSchemaContext(ctx);
     }
 
+    @Override
+    public void close(){
+        executor.shutdownNow();
+    }
     @Override
     public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
             final InstanceIdentifier path, final L listener, final DataChangeScope scope) {
@@ -218,6 +221,8 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         @Override
         public void close() {
 
+             executor.shutdownNow();
+
         }
 
         protected synchronized void onTransactionFailed(final SnapshotBackedWriteTransaction transaction,
@@ -7,26 +7,18 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
+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;
+import com.google.common.collect.Multimap;
 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.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;
@@ -34,15 +26,22 @@ 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.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 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;
-import com.google.common.collect.Multimap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
 
 /**
  * Resolve Data Change Events based on modifications and listeners
@@ -94,7 +93,7 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
      *
      * Dispatch between merge variant and reuse variant of notification task is
      * done in
-     * {@link #addNotificationTask(com.google.common.collect.ImmutableList.Builder, Node, Collection)}
+     * {@link #addNotificationTask(com.google.common.collect.ImmutableList.Builder, Node, java.util.Collection)}
      *
      * @return Collection of notification tasks.
      */
@@ -114,7 +113,7 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
      * {@link #addNotificationTaskByScope(com.google.common.collect.ImmutableList.Builder, Node, DOMImmutableDataChangeEvent)}
      * . Otherwise events are merged by scope and distributed between listeners
      * to particular scope. See
-     * {@link #addNotificationTasksAndMergeEvents(com.google.common.collect.ImmutableList.Builder, Node, Collection)}
+     * {@link #addNotificationTasksAndMergeEvents(com.google.common.collect.ImmutableList.Builder, Node, java.util.Collection)}
      * .
      *
      * @param taskListBuilder
@@ -290,9 +289,8 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) afterData;
             return resolveNodeContainerReplaced(path, listeners, beforeCont, afterCont);
         } else if (!beforeData.equals(afterData)) {
-            // Node is either of Leaf type (does not contain child nodes)
-            // or we do not have listeners, so normal equals method is
-            // sufficient for determining change.
+            // Node is Leaf type (does not contain child nodes)
+            // so normal equals method is sufficient for determining change.
             LOG.trace("Resolving leaf replace event for {} , before {}, after {}",path,beforeData,afterData);
             DOMImmutableDataChangeEvent event = builder(DataChangeScope.BASE).setBefore(beforeData).setAfter(afterData)
                     .addUpdated(path, beforeData, afterData).build();
@@ -421,9 +419,6 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
                 eventBuilder.merge(resolveSameEventRecursivelly(path.node(childId), childListeners, child, eventFactory));
             }
             propagateEvent = eventBuilder.build();
-        } else {
-            // We do not dispatch leaf events since Binding Aware components do not support them.
-            propagateEvent = builder(DataChangeScope.BASE).build();
         }
         if (!listeners.isEmpty()) {
             addPartialTask(listeners, propagateEvent);
@@ -10,7 +10,7 @@ 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 org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -9,8 +9,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import static com.google.common.base.Preconditions.checkState;
 
-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.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -21,11 +20,13 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
 
 /**
  * Implementation of Write transaction which is backed by
  * {@link DataTreeSnapshot} and executed according to
- * {@link TransactionReadyPrototype}.
+ * {@link org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction.TransactionReadyPrototype}.
  *
  */
 class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements DOMStoreWriteTransaction {
@@ -139,10 +140,10 @@ class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction impleme
 
     /**
      * Prototype implementation of
-     * {@link #ready(SnapshotBackedWriteTransaction)}
+     * {@link #ready(org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction)}
      *
      * This class is intended to be implemented by Transaction factories
-     * responsible for allocation of {@link SnapshotBackedWriteTransaction} and
+     * responsible for allocation of {@link org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction} and
      * providing underlying logic for applying implementation.
      *
      */
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl.tree;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -27,17 +30,15 @@ import org.opendaylight.yangtools.concepts.Identifiable;
 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.tree.StoreTreeNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
 /**
  * A set of listeners organized as a tree by node to which they listen. This class
  * allows for efficient lookup of listeners when we walk the DataTreeCandidate.
  */
-public final class ListenerTree {
+public final class ListenerTree  {
     private static final Logger LOG = LoggerFactory.getLogger(ListenerTree.class);
     private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
     private final Node rootNode = new Node(null, null);
@@ -71,7 +72,7 @@ public final class ListenerTree {
 
         try {
             Node walkNode = rootNode;
-            for (final PathArgument arg : path.getPath()) {
+            for (final PathArgument arg : path.getPathArguments()) {
                 walkNode = walkNode.ensureChild(arg);
             }
 
@@ -173,7 +174,7 @@ public final class ListenerTree {
     /**
      * This is a single node within the listener tree. Note that the data returned from
      * and instance of this class is guaranteed to have any relevance or consistency
-     * only as long as the {@link Walker} instance through which it is reached remains
+     * only as long as the {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker} instance through which it is reached remains
      * unclosed.
      */
     public static final class Node implements StoreTreeNode<Node>, Identifiable<PathArgument> {
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang b/opendaylight/md-sal/sal-inmemory-datastore/src/main/yang/opendaylight-inmemory-datastore-provider.yang
new file mode 100644 (file)
index 0000000..03220a3
--- /dev/null
@@ -0,0 +1,71 @@
+
+module opendaylight-inmemory-datastore-provider {
+
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider";
+    prefix "inmemory-datastore-provider";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+       import opendaylight-config-dom-datastore {prefix config-dom-store-spi;}
+       import opendaylight-operational-dom-datastore {prefix operational-dom-store-spi;}
+    import opendaylight-md-sal-dom {prefix sal;}
+
+    description
+        "InMemory datastore provider implementation for config & operational datastore";
+
+    revision "2014-06-17" {
+        description
+        "Initial revision.";
+    }
+
+    // This is the definition of the service implementation as a module identity.
+    identity inmemory-config-datastore-provider {
+            base config:module-type;
+            config:provided-service config-dom-store-spi:config-dom-datastore;
+            config:java-name-prefix InMemoryConfigDataStoreProvider;
+    }
+
+        // This is the definition of the service implementation as a module identity.
+
+     identity inmemory-operational-datastore-provider {
+             base config:module-type;
+             config:provided-service operational-dom-store-spi:operational-dom-datastore;
+             config:java-name-prefix InMemoryOperationalDataStoreProvider;
+      }
+
+
+    // Augments the 'configuration' choice node under modules/module.
+    augment "/config:modules/config:module/config:configuration" {
+        case inmemory-config-datastore-provider {
+            when "/config:modules/config:module/config:type = 'inmemory-config-datastore-provider'";
+
+            container schema-service {
+              uses config:service-ref {
+                   refine type {
+                          mandatory false;
+                          config:required-identity sal:schema-service;
+                    }
+              }
+            }
+        }
+    }
+
+
+
+      // Augments the 'configuration' choice node under modules/module.
+        augment "/config:modules/config:module/config:configuration" {
+            case inmemory-operational-datastore-provider {
+                when "/config:modules/config:module/config:type = 'inmemory-operational-datastore-provider'";
+
+                container schema-service {
+                  uses config:service-ref {
+                       refine type {
+                              mandatory false;
+                              config:required-identity sal:schema-service;
+                        }
+                  }
+                }
+            }
+        }
+}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java
new file mode 100644 (file)
index 0000000..369a7da
--- /dev/null
@@ -0,0 +1,248 @@
+package org.opendaylight.controller.md.sal.dom.store.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+
+public class InMemoryDataStoreTest {
+
+  private SchemaContext schemaContext;
+  private InMemoryDOMDataStore domStore;
+
+  @Before
+  public void setupStore() {
+    domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.sameThreadExecutor());
+    schemaContext = TestModel.createTestContext();
+    domStore.onGlobalContextUpdated(schemaContext);
+
+  }
+
+  @Test
+  public void testTransactionIsolation() throws InterruptedException, ExecutionException {
+
+    assertNotNull(domStore);
+
+    DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
+    assertNotNull(readTx);
+
+    DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+    assertNotNull(writeTx);
+    /**
+     *
+     * Writes /test in writeTx
+     *
+     */
+    writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+
+    /**
+     *
+     * Reads /test from writeTx Read should return container.
+     *
+     */
+    ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
+    assertTrue(writeTxContainer.get().isPresent());
+
+    /**
+     *
+     * Reads /test from readTx Read should return Absent.
+     *
+     */
+    ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx.read(TestModel.TEST_PATH);
+    assertFalse(readTxContainer.get().isPresent());
+  }
+
+  @Test
+  public void testTransactionCommit() throws InterruptedException, ExecutionException {
+
+    DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+    assertNotNull(writeTx);
+    /**
+     *
+     * Writes /test in writeTx
+     *
+     */
+    writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+
+    /**
+     *
+     * Reads /test from writeTx Read should return container.
+     *
+     */
+    ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
+    assertTrue(writeTxContainer.get().isPresent());
+
+    DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
+
+    assertThreePhaseCommit(cohort);
+
+    Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
+        .get();
+    assertTrue(afterCommitRead.isPresent());
+  }
+
+  @Test
+  public void testTransactionAbort() throws InterruptedException, ExecutionException {
+
+    DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+    assertNotNull(writeTx);
+
+    assertTestContainerWrite(writeTx);
+
+    DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
+
+    assertTrue(cohort.canCommit().get().booleanValue());
+    cohort.preCommit().get();
+    cohort.abort().get();
+
+    Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
+        .get();
+    assertFalse(afterCommitRead.isPresent());
+  }
+
+  @Test
+  public void testTransactionChain() throws InterruptedException, ExecutionException {
+    DOMStoreTransactionChain txChain = domStore.createTransactionChain();
+    assertNotNull(txChain);
+
+    /**
+     * We alocate new read-write transaction and write /test
+     *
+     *
+     */
+    DOMStoreReadWriteTransaction firstTx = txChain.newReadWriteTransaction();
+    assertTestContainerWrite(firstTx);
+
+    /**
+     * First transaction is marked as ready, we are able to allocate chained
+     * transactions
+     */
+    DOMStoreThreePhaseCommitCohort firstWriteTxCohort = firstTx.ready();
+
+    /**
+     * We alocate chained transaction - read transaction, note first one is
+     * still not commited to datastore.
+     */
+    DOMStoreReadTransaction secondReadTx = txChain.newReadOnlyTransaction();
+
+    /**
+     *
+     * We test if we are able to read data from tx, read should not fail
+     * since we are using chained transaction.
+     *
+     *
+     */
+    assertTestContainerExists(secondReadTx);
+
+    /**
+     *
+     * We alocate next transaction, which is still based on first one, but
+     * is read-write.
+     *
+     */
+    DOMStoreReadWriteTransaction thirdDeleteTx = txChain.newReadWriteTransaction();
+
+    /**
+     * We test existence of /test in third transaction container should
+     * still be visible from first one (which is still uncommmited).
+     *
+     *
+     */
+    assertTestContainerExists(thirdDeleteTx);
+
+    /**
+     * We delete node in third transaction
+     */
+    thirdDeleteTx.delete(TestModel.TEST_PATH);
+
+    /**
+     * third transaction is sealed.
+     */
+    DOMStoreThreePhaseCommitCohort thirdDeleteTxCohort = thirdDeleteTx.ready();
+
+    /**
+     * We commit first transaction
+     *
+     */
+    assertThreePhaseCommit(firstWriteTxCohort);
+
+    // Alocates store transacion
+    DOMStoreReadTransaction storeReadTx = domStore.newReadOnlyTransaction();
+    /**
+     * We verify transaction is commited to store, container should exists
+     * in datastore.
+     */
+    assertTestContainerExists(storeReadTx);
+    /**
+     * We commit third transaction
+     *
+     */
+    assertThreePhaseCommit(thirdDeleteTxCohort);
+  }
+
+  @Test
+  @Ignore
+  public void testTransactionConflict() throws InterruptedException, ExecutionException {
+    DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
+    DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
+    assertTestContainerWrite(txOne);
+    assertTestContainerWrite(txTwo);
+
+    /**
+     * Commits transaction
+     */
+    assertThreePhaseCommit(txOne.ready());
+
+    /**
+     * Asserts that txTwo could not be commited
+     */
+    assertFalse(txTwo.ready().canCommit().get());
+  }
+
+  private static void assertThreePhaseCommit(final DOMStoreThreePhaseCommitCohort cohort)
+      throws InterruptedException, ExecutionException {
+    assertTrue(cohort.canCommit().get().booleanValue());
+    cohort.preCommit().get();
+    cohort.commit().get();
+  }
+
+  private static Optional<NormalizedNode<?, ?>> assertTestContainerWrite(final DOMStoreReadWriteTransaction writeTx)
+      throws InterruptedException, ExecutionException {
+    /**
+     *
+     * Writes /test in writeTx
+     *
+     */
+    writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+
+    return assertTestContainerExists(writeTx);
+  }
+
+  /**
+   * Reads /test from readTx Read should return container.
+   */
+  private static Optional<NormalizedNode<?, ?>> assertTestContainerExists(DOMStoreReadTransaction readTx)
+      throws InterruptedException, ExecutionException {
+
+    ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = readTx.read(TestModel.TEST_PATH);
+    assertTrue(writeTxContainer.get().isPresent());
+    return writeTxContainer.get();
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/TestModel.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/TestModel.java
new file mode 100644 (file)
index 0000000..3feeb29
--- /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;
+
+import org.opendaylight.yangtools.yang.common.QName;
+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 org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+
+public class TestModel {
+
+    public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+        "test");
+    public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+    public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+    public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
+    public static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
+    public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
+    public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
+    private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
+
+    public static final InstanceIdentifier TEST_PATH = InstanceIdentifier.of(TEST_QNAME);
+    public static final InstanceIdentifier OUTER_LIST_PATH = InstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
+    public static final QName TWO_QNAME = QName.create(TEST_QNAME, "two");
+    public static final QName THREE_QNAME = QName.create(TEST_QNAME, "three");
+
+
+    public static final InputStream getDatastoreTestInputStream() {
+        return getInputStream(DATASTORE_TEST_YANG);
+    }
+
+    private static InputStream getInputStream(final String resourceName) {
+        return TestModel.class.getResourceAsStream(DATASTORE_TEST_YANG);
+    }
+
+    public static SchemaContext createTestContext() {
+        YangParserImpl parser = new YangParserImpl();
+        Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(getDatastoreTestInputStream()));
+        return parser.resolveSchemaContext(modules);
+    }
+}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/resources/odl-datastore-test.yang b/opendaylight/md-sal/sal-inmemory-datastore/src/test/resources/odl-datastore-test.yang
new file mode 100644 (file)
index 0000000..17541fe
--- /dev/null
@@ -0,0 +1,42 @@
+module odl-datastore-test {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test";
+    prefix "store-test";
+    
+    revision "2014-03-13" {
+        description "Initial revision.";
+    }
+
+    container test {
+        list outer-list {
+            key id;
+            leaf id {
+                type uint16;
+            }
+            choice outer-choice {
+                case one {
+                    leaf one {
+                        type string;
+                    }
+                }
+                case two-three {
+                    leaf two {
+                        type string;
+                    }
+                    leaf three {
+                        type string;
+                    }
+               }
+           }
+           list inner-list {
+                key name;
+                leaf name {
+                    type string;
+                }
+                leaf value {
+                    type string;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
index 0dd25292c2b3810e78fbaf3009f9b3a212f8675a..0bf4b3238dd5f78a3e7b95626bd0d04a2ca8591a 100644 (file)
@@ -25,7 +25,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
index f73d9cc72f893aa0260e6adc7bf0f257eb18252e..037bfb4a82c2cd8f34dbfe05513e602e7077b3ff 100644 (file)
@@ -12,13 +12,10 @@ import static org.opendaylight.controller.config.api.JmxAttributeValidationExcep
 
 import java.io.File;
 import java.io.InputStream;
-import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 
 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.NetconfReconnectingClientConfiguration;
 import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
@@ -33,19 +30,16 @@ import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 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;
 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-import com.google.common.net.InetAddresses;
-import io.netty.util.HashedWheelTimer;
-
 /**
  *
  */
@@ -67,6 +61,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
     @Override
     protected void customValidation() {
         checkNotNull(getAddress(), addressJmxAttribute);
+        checkCondition(isHostAddressPresent(getAddress()), "Host address not present in " + getAddress(), addressJmxAttribute);
         checkNotNull(getPort(), portJmxAttribute);
         checkNotNull(getDomRegistry(), portJmxAttribute);
         checkNotNull(getDomRegistry(), domRegistryJmxAttribute);
@@ -77,11 +72,9 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         checkNotNull(getBetweenAttemptsTimeoutMillis(), betweenAttemptsTimeoutMillisJmxAttribute);
         checkCondition(getBetweenAttemptsTimeoutMillis() > 0, "must be > 0", betweenAttemptsTimeoutMillisJmxAttribute);
 
-        // FIXME BUG-944 remove backwards compatibility
-        if(getClientDispatcher() == null) {
-            checkCondition(getBossThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", bossThreadGroupJmxAttribute);
-            checkCondition(getWorkerThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", workerThreadGroupJmxAttribute);
-        }
+        checkNotNull(getClientDispatcher(), clientDispatcherJmxAttribute);
+        checkNotNull(getBindingRegistry(), bindingRegistryJmxAttribute);
+        checkNotNull(getProcessingExecutor(), processingExecutorJmxAttribute);
 
         // Check username + password in case of ssh
         if(getTcpOnly() == false) {
@@ -89,33 +82,21 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
             checkNotNull(getPassword(), passwordJmxAttribute);
         }
 
-        // FIXME BUG 944 remove this warning
-        if(getBindingRegistry() == null) {
-            logger.warn("Configuration property: \"binding-registry\" not set for sal-netconf-connector (" + getIdentifier() + "). " +
-                    "Netconf-connector now requires a dependency on \"binding-broker-osgi-registry\". " +
-                    "The dependency is optional for now to preserve backwards compatibility, but will be mandatory in the future. " +
-                    "Please set the property as in \"01-netconf-connector\" initial config file. " +
-                    "The service will be retrieved from OSGi service registry now.");
-        }
+    }
 
-        // FIXME BUG 944 remove this warning
-        if(getProcessingExecutor() == null) {
-            logger.warn("Configuration property: \"processing-executor\" not set for sal-netconf-connector (" + getIdentifier() + "). " +
-                    "Netconf-connector now requires a dependency on \"threadpool\". " +
-                    "The dependency is optional for now to preserve backwards compatibility, but will be mandatory in the future. " +
-                    "Please set the property as in \"01-netconf-connector\" initial config file. " +
-                    "New instance will be created for the executor.");
-        }
+    private boolean isHostAddressPresent(Host address) {
+        return address.getDomainName() != null ||
+               address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
     }
 
     @Override
     public java.lang.AutoCloseable createInstance() {
         final RemoteDeviceId id = new RemoteDeviceId(getIdentifier());
 
-        final ExecutorService globalProcessingExecutor = getGlobalProcessingExecutor();
+        final ExecutorService globalProcessingExecutor = getProcessingExecutorDependency().getExecutor();
 
         final Broker domBroker = getDomRegistryDependency();
-        final BindingAwareBroker bindingBroker = getBindingRegistryBackwards();
+        final BindingAwareBroker bindingBroker = getBindingRegistryDependency();
 
         final RemoteDeviceHandler salFacade = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, globalProcessingExecutor);
         final NetconfDevice device =
@@ -123,8 +104,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         final NetconfDeviceCommunicator listener = new NetconfDeviceCommunicator(id, device);
         final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(listener);
 
-        // FIXME BUG-944 remove backwards compatibility
-        final NetconfClientDispatcher dispatcher = getClientDispatcher() == null ? createDispatcher() : getClientDispatcherDependency();
+        final NetconfClientDispatcher dispatcher = getClientDispatcherDependency();
         listener.initializeRemoteConnection(dispatcher, clientConfig);
 
         return new AutoCloseable() {
@@ -136,30 +116,6 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         };
     }
 
-    private BindingAwareBroker getBindingRegistryBackwards() {
-        if(getBindingRegistry() != null) {
-            return getBindingRegistryDependency();
-        } else {
-            // FIXME BUG 944 remove backwards compatibility
-            final ServiceReference<BindingAwareBroker> serviceReference = bundleContext.getServiceReference(BindingAwareBroker.class);
-            Preconditions
-                    .checkNotNull(
-                            serviceReference,
-                            "Unable to retrieve %s from OSGi service registry, use binding-registry config property to inject %s with config subsystem",
-                            BindingAwareBroker.class, BindingAwareBroker.class);
-            return bundleContext.getService(serviceReference);
-        }
-    }
-
-    private ExecutorService getGlobalProcessingExecutor() {
-        if(getProcessingExecutor() != null) {
-            return getProcessingExecutorDependency().getExecutor();
-        } else {
-            // FIXME BUG 944 remove backwards compatibility
-            return Executors.newCachedThreadPool();
-        }
-    }
-
     private synchronized AbstractCachingSchemaSourceProvider<String, InputStream> getGlobalNetconfSchemaProvider() {
         if(GLOBAL_NETCONF_SOURCE_PROVIDER == null) {
             final String storageFile = "cache/schema";
@@ -171,16 +127,6 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         return GLOBAL_NETCONF_SOURCE_PROVIDER;
     }
 
-    // FIXME BUG-944 remove backwards compatibility
-    /**
-     * @deprecated Use getClientDispatcherDependency method instead to retrieve injected dispatcher.
-     * This one creates new instance of NetconfClientDispatcher and will be removed in near future.
-     */
-    @Deprecated
-    private NetconfClientDispatcher createDispatcher() {
-        return new NetconfClientDispatcherImpl(getBossThreadGroupDependency(), getWorkerThreadGroupDependency(), new HashedWheelTimer());
-    }
-
     public void setBundleContext(final BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
@@ -226,15 +172,12 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
     }
 
     private InetSocketAddress getSocketAddress() {
-        /*
-         * Uncomment after Switch to IP Address
-        if(getAddress().getIpv4Address() != null) {
-            addressValue = getAddress().getIpv4Address().getValue();
+        if(getAddress().getDomainName() != null) {
+            return new InetSocketAddress(getAddress().getDomainName().getValue(), getPort().getValue());
         } else {
-            addressValue = getAddress().getIpv6Address().getValue();
+            IpAddress ipAddress = getAddress().getIpAddress();
+            String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
+            return new InetSocketAddress(ip, getPort().getValue());
         }
-         */
-        final InetAddress inetAddress = InetAddresses.forString(getAddress());
-        return new InetSocketAddress(inetAddress, getPort().intValue());
     }
 }
index e78f2b32df0cbc338bad5b28ac1d5063084b9b96..9fa68eeea6f87c7f1a4cb4634b0759a61cc2f83e 100644 (file)
@@ -10,17 +10,21 @@ package org.opendaylight.controller.sal.connect.netconf.listener;
 import java.util.ArrayDeque;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Queue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientSession;
 import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
 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.controller.sal.common.util.RpcErrors;
 import org.opendaylight.controller.sal.common.util.Rpcs;
@@ -35,6 +39,8 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -45,12 +51,9 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfDeviceCommunicator.class);
 
-    private static final RpcResult<NetconfMessage> FAILED_RPC_RESULT = new FailedRpcResult<>(RpcErrors.getRpcError(
-            null, null, null, RpcError.ErrorSeverity.ERROR, "Netconf session disconnected",
-            RpcError.ErrorType.PROTOCOL, null));
-
     private final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice;
     private final RemoteDeviceId id;
+    private final Lock sessionLock = new ReentrantLock();
 
     public NetconfDeviceCommunicator(final RemoteDeviceId id,
             final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice) {
@@ -62,52 +65,101 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
     private NetconfClientSession session;
 
     @Override
-    public synchronized void onSessionUp(final NetconfClientSession session) {
-        logger.debug("{}: Session established", id);
-        this.session = session;
+    public void onSessionUp(final NetconfClientSession session) {
+        sessionLock.lock();
+        try {
+            logger.debug("{}: Session established", id);
+            this.session = session;
 
-        final NetconfSessionCapabilities netconfSessionCapabilities = NetconfSessionCapabilities.fromNetconfSession(session);
-        logger.trace("{}: Session advertised capabilities: {}", id, netconfSessionCapabilities);
+            final NetconfSessionCapabilities netconfSessionCapabilities =
+                                             NetconfSessionCapabilities.fromNetconfSession(session);
+            logger.trace("{}: Session advertised capabilities: {}", id, netconfSessionCapabilities);
 
-        remoteDevice.onRemoteSessionUp(netconfSessionCapabilities, this);
+            remoteDevice.onRemoteSessionUp(netconfSessionCapabilities, this);
+        }
+        finally {
+            sessionLock.unlock();
+        }
     }
 
     public void initializeRemoteConnection(final NetconfClientDispatcher dispatch,
-                                           final NetconfReconnectingClientConfiguration config) {
-        dispatch.createReconnectingClient(config);
+                                           final NetconfClientConfiguration config) {
+        if(config instanceof NetconfReconnectingClientConfiguration) {
+            dispatch.createReconnectingClient((NetconfReconnectingClientConfiguration) config);
+        }
+
+        dispatch.createClient(config);
     }
 
-    private synchronized void tearDown(final Exception e) {
-        remoteDevice.onRemoteSessionDown();
-        session = null;
+    private void tearDown( String reason ) {
+        List<UncancellableFuture<RpcResult<NetconfMessage>>> futuresToCancel = Lists.newArrayList();
+        sessionLock.lock();
+        try {
+            if( session != null ) {
+                session = null;
+
+                /*
+                 * Walk all requests, check if they have been executing
+                 * or cancelled and remove them from the queue.
+                 */
+                final Iterator<Request> it = requests.iterator();
+                while (it.hasNext()) {
+                    final Request r = it.next();
+                    if (r.future.isUncancellable()) {
+                        futuresToCancel.add( r.future );
+                        it.remove();
+                    } else if (r.future.isCancelled()) {
+                        // This just does some house-cleaning
+                        it.remove();
+                    }
+                }
 
-        /*
-         * Walk all requests, check if they have been executing
-         * or cancelled and remove them from the queue.
-         */
-        final Iterator<Request> it = requests.iterator();
-        while (it.hasNext()) {
-            final Request r = it.next();
-            if (r.future.isUncancellable()) {
-                r.future.setException(e);
-                it.remove();
-            } else if (r.future.isCancelled()) {
-                // This just does some house-cleaning
-                it.remove();
+                remoteDevice.onRemoteSessionDown();
+            }
+        }
+        finally {
+            sessionLock.unlock();
+        }
+
+        // Notify pending request futures outside of the sessionLock to avoid unnecessarily
+        // blocking the caller.
+        for( UncancellableFuture<RpcResult<NetconfMessage>> future: futuresToCancel ) {
+            if( Strings.isNullOrEmpty( reason ) ) {
+                future.set( createSessionDownRpcResult() );
+            } else {
+                future.set( createErrorRpcResult( RpcError.ErrorType.TRANSPORT, reason ) );
             }
         }
     }
 
+    private RpcResult<NetconfMessage> createSessionDownRpcResult()
+    {
+        return createErrorRpcResult( RpcError.ErrorType.TRANSPORT,
+                             String.format( "The netconf session to %1$s is disconnected", id.getName() ) );
+    }
+
+    private RpcResult<NetconfMessage> createErrorRpcResult( RpcError.ErrorType errorType, String message )
+    {
+        return new FailedRpcResult<NetconfMessage>( RpcErrors.getRpcError( null,
+                NetconfDocumentedException.ErrorTag.operation_failed.getTagValue(),
+                null, RpcError.ErrorSeverity.ERROR, message, errorType, null ) );
+    }
+
     @Override
     public void onSessionDown(final NetconfClientSession session, final Exception e) {
         logger.warn("{}: Session went down", id, e);
-        tearDown(e);
+        tearDown( null );
     }
 
     @Override
     public void onSessionTerminated(final NetconfClientSession session, final NetconfTerminationReason reason) {
         logger.warn("{}: Session terminated {}", id, reason);
-        tearDown(new RuntimeException(reason.getErrorMessage()));
+        tearDown( reason.getErrorMessage() );
+    }
+
+    @Override
+    public void close() {
+        tearDown( String.format( "The netconf session to %1$s has been closed", id.getName() ) );
     }
 
     @Override
@@ -123,73 +175,109 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
         }
     }
 
-    private synchronized void processMessage(final NetconfMessage message) {
-        final Request r = requests.peek();
-        if (r.future.isUncancellable()) {
-            requests.poll();
+    private void processMessage(final NetconfMessage message) {
+        Request request = null;
+        sessionLock.lock();
+        try {
+            request = requests.peek();
+            if (request.future.isUncancellable()) {
+                requests.poll();
+            }
+            else {
+                request = null;
+                logger.warn("{}: Ignoring unsolicited message {}", id, msgToS(message));
+            }
+        }
+        finally {
+            sessionLock.unlock();
+        }
+
+        if( request != null ) {
 
             logger.debug("{}: Message received {}", id, message);
 
             if(logger.isTraceEnabled()) {
-                logger.trace("{}: Matched request: {} to response: {}", id, msgToS(r.request), msgToS(message));
+                logger.trace( "{}: Matched request: {} to response: {}", id,
+                              msgToS( request.request ), msgToS( message ) );
             }
 
             try {
-                NetconfMessageTransformUtil.checkValidReply(r.request, message);
-            } catch (final IllegalStateException e) {
-                logger.warn("{}: Invalid request-reply match, reply message contains different message-id, request: {}, response: {}", id,
-                        msgToS(r.request), msgToS(message), e);
-                r.future.setException(e);
+                NetconfMessageTransformUtil.checkValidReply( request.request, message );
+            }
+            catch (final NetconfDocumentedException e) {
+                logger.warn( "{}: Invalid request-reply match, reply message contains different message-id, request: {}, response: {}",
+                             id, msgToS( request.request ), msgToS( message ), e );
+
+                request.future.set( new FailedRpcResult<NetconfMessage>(
+                                                           NetconfMessageTransformUtil.toRpcError( e ) ) );
                 return;
             }
 
             try {
                 NetconfMessageTransformUtil.checkSuccessReply(message);
-            } catch (NetconfDocumentedException | IllegalStateException e) {
-                logger.warn("{}: Error reply from remote device, request: {}, response: {}", id,
-                        msgToS(r.request), msgToS(message), e);
-                r.future.setException(e);
+            }
+            catch( NetconfDocumentedException e ) {
+                logger.warn( "{}: Error reply from remote device, request: {}, response: {}", id,
+                             msgToS( request.request ), msgToS( message ), e );
+
+                request.future.set( new FailedRpcResult<NetconfMessage>(
+                                                          NetconfMessageTransformUtil.toRpcError( e ) ) );
                 return;
             }
 
-            r.future.set(Rpcs.getRpcResult(true, message, Collections.<RpcError>emptySet()));
-        } else {
-            logger.warn("{}: Ignoring unsolicited message {}", id, msgToS(message));
+            request.future.set(Rpcs.getRpcResult( true, message, Collections.<RpcError>emptySet() ) );
         }
     }
 
-    @Override
-    public void close() {
-        tearDown(new RuntimeException("Closed"));
-    }
-
     private static String msgToS(final NetconfMessage msg) {
         return XmlUtil.toString(msg.getDocument());
     }
 
     @Override
-    public synchronized ListenableFuture<RpcResult<NetconfMessage>> sendRequest(final NetconfMessage message, final QName rpc) {
+    public ListenableFuture<RpcResult<NetconfMessage>> sendRequest(
+                                               final NetconfMessage message, final QName rpc) {
+        sessionLock.lock();
+        try {
+            return sendRequestWithLock( message, rpc );
+        }
+        finally {
+            sessionLock.unlock();
+        }
+    }
+
+    private ListenableFuture<RpcResult<NetconfMessage>> sendRequestWithLock(
+                                               final NetconfMessage message, final QName rpc) {
         if(logger.isTraceEnabled()) {
             logger.trace("{}: Sending message {}", id, msgToS(message));
         }
 
         if (session == null) {
             logger.warn("{}: Session is disconnected, failing RPC request {}", id, message);
-            return Futures.immediateFuture(FAILED_RPC_RESULT);
+            return Futures.immediateFuture( createSessionDownRpcResult() );
         }
 
-        final Request req = new Request(new UncancellableFuture<RpcResult<NetconfMessage>>(true), message, rpc);
+        final Request req = new Request( new UncancellableFuture<RpcResult<NetconfMessage>>(true),
+                                         message );
         requests.add(req);
 
         session.sendMessage(req.request).addListener(new FutureListener<Void>() {
             @Override
             public void operationComplete(final Future<Void> future) throws Exception {
-                if (!future.isSuccess()) {
+                if( !future.isSuccess() ) {
                     // We expect that a session down will occur at this point
-                    logger.debug("{}: Failed to send request {}", id, XmlUtil.toString(req.request.getDocument()), future.cause());
-                    req.future.setException(future.cause());
-                } else {
-                    logger.trace("{}: Finished sending request {}", id, req.request);
+                    logger.debug( "{}: Failed to send request {}", id,
+                                  XmlUtil.toString(req.request.getDocument()), future.cause() );
+
+                    if( future.cause() != null ) {
+                        req.future.set( createErrorRpcResult( RpcError.ErrorType.TRANSPORT,
+                                                              future.cause().getLocalizedMessage() ) );
+                    } else {
+                        req.future.set( createSessionDownRpcResult() ); // assume session is down
+                    }
+                    req.future.setException( future.cause() );
+                }
+                else {
+                    logger.trace( "Finished sending request {}", req.request );
                 }
             }
         });
@@ -215,12 +303,11 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
     private static final class Request {
         final UncancellableFuture<RpcResult<NetconfMessage>> future;
         final NetconfMessage request;
-        final QName rpc;
 
-        private Request(final UncancellableFuture<RpcResult<NetconfMessage>> future, final NetconfMessage request, final QName rpc) {
+        private Request(final UncancellableFuture<RpcResult<NetconfMessage>> future,
+                        final NetconfMessage request) {
             this.future = future;
             this.request = request;
-            this.rpc = rpc;
         }
     }
 }
index 457b8c36b987996bd28c041cff0d17068547f7a6..8b6ac7d5671643cdad49babaecd0026de338f9c6 100644 (file)
@@ -48,7 +48,7 @@ public final class NetconfDeviceCommitHandler implements DataCommitHandler<Insta
             Thread.currentThread().interrupt();
             throw new RuntimeException(id + ": Interrupted while waiting for response", e);
         } catch (final ExecutionException e) {
-            logger.warn("%s: Error executing pre commit operation on remote device", id, e);
+            logger.warn("{}: Error executing pre commit operation on remote device", id, e);
             return new FailingTransaction(twoPhaseCommit, e);
         }
 
index 2909baccdb0dd0bc8a23e80553a6914c3dd13fe6..3535c96c804e7a97aa7aad1c516dfa224819a95d 100644 (file)
@@ -74,7 +74,7 @@ public final class NetconfDeviceDataReader implements DataReader<InstanceIdentif
     private static Node<?> findNode(final CompositeNode node, final InstanceIdentifier identifier) {
 
         Node<?> current = node;
-        for (final InstanceIdentifier.PathArgument arg : identifier.getPath()) {
+        for (final InstanceIdentifier.PathArgument arg : identifier.getPathArguments()) {
             if (current instanceof SimpleNode<?>) {
                 return null;
             } else if (current instanceof CompositeNode) {
index 41f9fec3c4d5e1f0240cc9adc84b179ac52bc50f..1737b8234a610267c9aa7f82eddd7a1f9912f502 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.connect.netconf.sal;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CONFIG_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DEFAULT_OPERATION_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_ERROR_OPTION_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_OPERATION_QNAME;
@@ -17,6 +18,12 @@ import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessag
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_TARGET_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.ROLLBACK_ON_ERROR_OPTION;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -39,16 +46,13 @@ 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.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 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.ImmutableList;
-import com.google.common.collect.Lists;
-
 /**
  *  Remote transaction that delegates data change to remote device using netconf messages.
  */
@@ -87,17 +91,18 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
     }
 
     private void sendMerge(final InstanceIdentifier key, final CompositeNode value) throws InterruptedException, ExecutionException {
-        sendEditRpc(createEditConfigStructure(key, Optional.<String>absent(), Optional.of(value)));
+        sendEditRpc(createEditConfigStructure(key, Optional.<String>absent(), Optional.of(value)), Optional.<String>absent());
     }
 
     private void sendDelete(final InstanceIdentifier toDelete) throws InterruptedException, ExecutionException {
-        sendEditRpc(createEditConfigStructure(toDelete, Optional.of("delete"), Optional.<CompositeNode>absent()));
+        // FIXME use org.opendaylight.yangtools.yang.data.api.ModifyAction instead of strings
+        // TODO add string lowercase value to ModifyAction enum entries
+        sendEditRpc(createEditConfigStructure(toDelete, Optional.of("delete"), Optional.<CompositeNode>absent()), Optional.of("none"));
     }
 
-    private void sendEditRpc(final CompositeNode editStructure) throws InterruptedException, ExecutionException {
-        final ImmutableCompositeNode editConfigRequest = createEditConfigRequest(editStructure);
+    private void sendEditRpc(final CompositeNode editStructure, final Optional<String> defaultOperation) throws InterruptedException, ExecutionException {
+        final ImmutableCompositeNode editConfigRequest = createEditConfigRequest(editStructure, defaultOperation);
         final RpcResult<CompositeNode> rpcResult = rpc.invokeRpc(NETCONF_EDIT_CONFIG_QNAME, editConfigRequest).get();
-        // TODO 874 add default operation when sending delete
 
         // Check result
         if(rpcResult.isSuccessful() == false) {
@@ -106,23 +111,33 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
         }
     }
 
-    private ImmutableCompositeNode createEditConfigRequest(final CompositeNode editStructure) {
+    private ImmutableCompositeNode createEditConfigRequest(final CompositeNode editStructure, final Optional<String> defaultOperation) {
         final CompositeNodeBuilder<ImmutableCompositeNode> ret = ImmutableCompositeNode.builder();
 
+        // Target
         final Node<?> targetWrapperNode = ImmutableCompositeNode.create(NETCONF_TARGET_QNAME, ImmutableList.<Node<?>>of(targetNode));
         ret.add(targetWrapperNode);
 
+        // Default operation
+        if(defaultOperation.isPresent()) {
+            SimpleNode<String> defOp = NodeFactory.createImmutableSimpleNode(NETCONF_DEFAULT_OPERATION_QNAME, null, defaultOperation.get());
+            ret.add(defOp);
+        }
+
+        // Error option
         if(rollbackSupported) {
             ret.addLeaf(NETCONF_ERROR_OPTION_QNAME, ROLLBACK_ON_ERROR_OPTION);
         }
+
         ret.setQName(NETCONF_EDIT_CONFIG_QNAME);
+        // Edit content
         ret.add(editStructure);
         return ret.toInstance();
     }
 
     private CompositeNode createEditConfigStructure(final InstanceIdentifier dataPath, final Optional<String> operation,
-                                                    final Optional<CompositeNode> lastChildOverride) {
-        Preconditions.checkArgument(dataPath.getPath().isEmpty() == false, "Instance identifier with empty path %s", dataPath);
+            final Optional<CompositeNode> lastChildOverride) {
+        Preconditions.checkArgument(Iterables.isEmpty(dataPath.getPathArguments()) == false, "Instance identifier with empty path %s", dataPath);
 
         List<PathArgument> reversedPath = Lists.reverse(dataPath.getPath());
 
index 2adc1be79e65b35b4bc52312e56d6653b2d7551f..21f94474f893a4b2c4dde263a477cc6336ce39d8 100644 (file)
@@ -70,6 +70,8 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
                     final DataNodeContainer schemaForEdit = NetconfMessageTransformUtil.createSchemaForEdit(schemaContext.get());
                     w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForEdit, codecProvider);
                 } else {
+                    // FIXME get and get-config needs schema as well to transform filter using schema context
+                    // e.g. Identityref nodes in filter fail to serialize properly to xml without schema
                     w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaContext.get(), codecProvider);
                 }
             } else {
index 1284d6d1ce3cd67d8b9355622873db46a46754b5..0ea3d6a35ac74c873d3965a3a1d90e7c514aa99b 100644 (file)
@@ -7,19 +7,30 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.util;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.annotation.Nullable;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.Node;
@@ -33,27 +44,19 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
 public class NetconfMessageTransformUtil {
 
     private NetconfMessageTransformUtil() {
     }
 
-    public static final QName IETF_NETCONF_MONITORING = QName.create(
-            "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "2010-10-04", "ietf-netconf-monitoring");
+    public static final QName IETF_NETCONF_MONITORING = QName.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "2010-10-04", "ietf-netconf-monitoring");
     public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
     public static QName NETCONF_QNAME = QName.create(NETCONF_URI, null, "netconf");
     public static QName NETCONF_DATA_QNAME = QName.create(NETCONF_QNAME, "data");
     public static QName NETCONF_RPC_REPLY_QNAME = QName.create(NETCONF_QNAME, "rpc-reply");
     public static QName NETCONF_ERROR_OPTION_QNAME = QName.create(NETCONF_QNAME, "error-option");
     public static QName NETCONF_RUNNING_QNAME = QName.create(NETCONF_QNAME, "running");
-    static List<Node<?>> RUNNING = Collections.<Node<?>> singletonList(new SimpleNodeTOImpl<>(NETCONF_RUNNING_QNAME,
-            null, null));
+    static List<Node<?>> RUNNING = Collections.<Node<?>> singletonList(new SimpleNodeTOImpl<>(NETCONF_RUNNING_QNAME, null, null));
     public static QName NETCONF_SOURCE_QNAME = QName.create(NETCONF_QNAME, "source");
     public static CompositeNode CONFIG_SOURCE_RUNNING = new CompositeNodeTOImpl(NETCONF_SOURCE_QNAME, null, RUNNING);
     public static QName NETCONF_CANDIDATE_QNAME = QName.create(NETCONF_QNAME, "candidate");
@@ -61,6 +64,7 @@ public class NetconfMessageTransformUtil {
     public static QName NETCONF_CONFIG_QNAME = QName.create(NETCONF_QNAME, "config");
     public static QName NETCONF_COMMIT_QNAME = QName.create(NETCONF_QNAME, "commit");
     public static QName NETCONF_OPERATION_QNAME = QName.create(NETCONF_QNAME, "operation");
+    public static QName NETCONF_DEFAULT_OPERATION_QNAME = QName.create(NETCONF_OPERATION_QNAME, "default-operation");
     public static QName NETCONF_EDIT_CONFIG_QNAME = QName.create(NETCONF_QNAME, "edit-config");
     public static QName NETCONF_GET_CONFIG_QNAME = QName.create(NETCONF_QNAME, "get-config");
     public static QName NETCONF_TYPE_QNAME = QName.create(NETCONF_QNAME, "type");
@@ -73,7 +77,7 @@ public class NetconfMessageTransformUtil {
 
     public static Node<?> toFilterStructure(final InstanceIdentifier identifier) {
         Node<?> previous = null;
-        if (identifier.getPath().isEmpty()) {
+        if (Iterables.isEmpty(identifier.getPathArguments())) {
             return null;
         }
 
@@ -99,28 +103,77 @@ public class NetconfMessageTransformUtil {
         return new CompositeNodeTOImpl(argument.getNodeType(), null, list);
     }
 
-    public static void checkValidReply(final NetconfMessage input, final NetconfMessage output) {
+    public static void checkValidReply(final NetconfMessage input, final NetconfMessage output)
+            throws NetconfDocumentedException {
         final String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id");
         final String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id");
 
         if(inputMsgId.equals(outputMsgId) == false) {
-            final String requestXml = XmlUtil.toString(input.getDocument());
-            final String responseXml = XmlUtil.toString(output.getDocument());
-            throw new IllegalStateException(String.format("Rpc request and reply message IDs must be same. Request: %s, response: %s", requestXml, responseXml));
+            Map<String,String> errorInfo = ImmutableMap.<String,String>builder()
+                    .put( "actual-message-id", outputMsgId )
+                    .put( "expected-message-id", inputMsgId )
+                    .build();
+
+            throw new NetconfDocumentedException( "Response message contained unknown \"message-id\"",
+                    null, NetconfDocumentedException.ErrorType.protocol,
+                    NetconfDocumentedException.ErrorTag.bad_attribute,
+                    NetconfDocumentedException.ErrorSeverity.error, errorInfo );
         }
     }
 
     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())));
+            throw NetconfDocumentedException.fromXMLDocument( output.getDocument() );
+        }
+    }
+
+    public static RpcError toRpcError( final NetconfDocumentedException ex )
+    {
+        StringBuilder infoBuilder = new StringBuilder();
+        Map<String, String> errorInfo = ex.getErrorInfo();
+        if( errorInfo != null )
+        {
+            for( Entry<String,String> e: errorInfo.entrySet() ) {
+                infoBuilder.append( '<' ).append( e.getKey() ).append( '>' ).append( e.getValue() )
+                .append( "</" ).append( e.getKey() ).append( '>' );
+
+            }
+        }
+
+        return RpcErrors.getRpcError( null, ex.getErrorTag().getTagValue(), infoBuilder.toString(),
+                toRpcErrorSeverity( ex.getErrorSeverity() ), ex.getLocalizedMessage(),
+                toRpcErrorType( ex.getErrorType() ), ex.getCause() );
+    }
+
+    private static ErrorSeverity toRpcErrorSeverity( final NetconfDocumentedException.ErrorSeverity severity ) {
+        switch( severity ) {
+        case warning:
+            return RpcError.ErrorSeverity.WARNING;
+        default:
+            return RpcError.ErrorSeverity.ERROR;
+        }
+    }
+
+    private static RpcError.ErrorType toRpcErrorType( final NetconfDocumentedException.ErrorType type )
+    {
+        switch( type ) {
+        case protocol:
+            return RpcError.ErrorType.PROTOCOL;
+        case rpc:
+            return RpcError.ErrorType.RPC;
+        case transport:
+            return RpcError.ErrorType.TRANSPORT;
+        default:
+            return RpcError.ErrorType.APPLICATION;
         }
     }
 
     public static CompositeNode flattenInput(final CompositeNode node) {
         final QName inputQName = QName.create(node.getNodeType(), "input");
         final CompositeNode input = node.getFirstCompositeByName(inputQName);
-        if (input == null)
+        if (input == null) {
             return node;
+        }
         if (input instanceof CompositeNode) {
 
             final List<Node<?>> nodes = ImmutableList.<Node<?>> builder() //
index c59c41c4374838908cf3d7440bc71cef7940b0d3..6bad4798c290524dc04ff2d39611f2a1f0c33453 100644 (file)
@@ -9,6 +9,7 @@ module odl-sal-netconf-connector-cfg {
     import opendaylight-md-sal-dom {prefix dom;}
     import opendaylight-md-sal-binding {prefix md-sal-binding; revision-date 2013-10-28;}
     import odl-netconf-cfg { prefix cfg-net; revision-date 2014-04-08; }
+    import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
 
     description
         "Service definition for Binding Aware MD-SAL.";
@@ -38,11 +39,11 @@ module odl-sal-netconf-connector-cfg {
             when "/config:modules/config:module/config:type = 'sal-netconf-connector'";
 
             leaf address {
-                type string;
+                type inet:host;
             }
 
             leaf port {
-                type uint32;
+                type inet:port-number;
             }
 
             leaf tcp-only {
@@ -69,40 +70,16 @@ module odl-sal-netconf-connector-cfg {
             container binding-registry {
                 uses config:service-ref {
                     refine type {
-                        // FIXME BUG-944 make mandatory (remove backwards compatibility)
-                        mandatory false;
+                        mandatory true;
                         config:required-identity md-sal-binding:binding-broker-osgi-registry;
                     }
                 }
             }
 
-            // FIXME BUG-944 remove backwards compatibility
-            // Deprecated, replaced by client dispatcher.
-            // This dependency will be removed in near future and all configurations of netconf-connector need to be changed to use dispatcher dependency.
-            container boss-thread-group {
-                uses config:service-ref {
-                    refine type {
-                        mandatory false;
-                        config:required-identity netty:netty-threadgroup;
-                    }
-                }
-            }
-
-            // FIXME BUG-944 remove backwards compatibility
-            // Deprecated, replaced by client dispatcher.
-            // This dependency will be removed in near future and all configurations of netconf-connector need to be changed to use dispatcher dependency.
-            container worker-thread-group {
-                uses config:service-ref {
-                    refine type {
-                        mandatory false;
-                        config:required-identity netty:netty-threadgroup;
-                    }
-                }
-            }
-
             container event-executor {
                 uses config:service-ref {
                     refine type {
+                        mandatory true;
                         config:required-identity netty:netty-event-executor;
                     }
                 }
@@ -111,8 +88,7 @@ module odl-sal-netconf-connector-cfg {
             container processing-executor {
                 uses config:service-ref {
                     refine type {
-                        // FIXME BUG-944 make mandatory (remove backwards compatibility)
-                        mandatory false;
+                        mandatory true;
                         config:required-identity th:threadpool;
                     }
                 }
@@ -120,7 +96,6 @@ module odl-sal-netconf-connector-cfg {
                 description "Makes up for flaws in netty threading design";
             }
 
-            // Replaces thread group dependencies
             container client-dispatcher {
                 uses config:service-ref {
                     refine type {
index 5ac32b5b3c918bd83d89764f940654641bfebbdd..c1b9f7b47ba8b8009b620655a729703e1809346f 100644 (file)
@@ -26,7 +26,7 @@ import java.util.concurrent.Executors;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java
new file mode 100644 (file)
index 0000000..391bf9c
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * 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.connect.netconf.listener;
+
+import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
+
+import java.io.ByteArrayInputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
+import org.opendaylight.controller.netconf.client.NetconfClientSession;
+import org.opendaylight.controller.sal.connect.api.RemoteDevice;
+import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class NetconfDeviceCommunicatorTest {
+
+    @Mock
+    NetconfClientSession mockSession;
+
+    @Mock
+    RemoteDevice<NetconfSessionCapabilities, NetconfMessage> mockDevice;
+
+    NetconfDeviceCommunicator communicator;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks( this );
+
+        communicator = new NetconfDeviceCommunicator( new RemoteDeviceId( "test" ), mockDevice );
+    }
+
+    @SuppressWarnings("unchecked")
+    void setupSession()
+    {
+        doReturn( Collections.<String>emptySet() ).when( mockSession ).getServerCapabilities();
+        doNothing().when( mockDevice ).onRemoteSessionUp( any( NetconfSessionCapabilities.class ),
+                                                          any( RemoteDeviceCommunicator.class ) );
+        communicator.onSessionUp( mockSession );
+    }
+
+    private ListenableFuture<RpcResult<NetconfMessage>> sendRequest() throws Exception {
+        return sendRequest( UUID.randomUUID().toString() );
+    }
+
+    @SuppressWarnings("unchecked")
+    private ListenableFuture<RpcResult<NetconfMessage>> sendRequest( String messageID ) throws Exception {
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+        Element element = doc.createElement( "request" );
+        element.setAttribute( "message-id", messageID );
+        doc.appendChild( element );
+        NetconfMessage message = new NetconfMessage( doc );
+
+        ChannelFuture mockChannelFuture = mock( ChannelFuture.class );
+        doReturn( mockChannelFuture ).when( mockChannelFuture )
+            .addListener( any( (GenericFutureListener.class ) ) );
+        doReturn( mockChannelFuture ).when( mockSession ).sendMessage( same( message ) );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture =
+                                      communicator.sendRequest( message, QName.create( "mock rpc" ) );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+        return resultFuture;
+    }
+
+    @Test
+    public void testOnSessionUp() {
+        String testCapability = "urn:opendaylight:params:xml:ns:test?module=test-module&revision=2014-06-02";
+        Collection<String> serverCapabilities =
+                Sets.newHashSet( NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString(),
+                                 NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString(),
+                                 testCapability );
+        doReturn( serverCapabilities ).when( mockSession ).getServerCapabilities();
+
+        ArgumentCaptor<NetconfSessionCapabilities> netconfSessionCapabilities =
+                                              ArgumentCaptor.forClass( NetconfSessionCapabilities.class );
+        doNothing().when( mockDevice ).onRemoteSessionUp( netconfSessionCapabilities.capture(), eq( communicator ) );
+
+        communicator.onSessionUp( mockSession );
+
+        verify( mockSession ).getServerCapabilities();
+        verify( mockDevice ).onRemoteSessionUp( netconfSessionCapabilities.capture(), eq( communicator ) );
+
+        NetconfSessionCapabilities actualCapabilites = netconfSessionCapabilities.getValue();
+        assertEquals( "containsCapability", true, actualCapabilites.containsCapability(
+                                NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString() ) );
+        assertEquals( "containsCapability", true, actualCapabilites.containsCapability( testCapability ) );
+        assertEquals( "getModuleBasedCaps", Sets.newHashSet(
+                            QName.create( "urn:opendaylight:params:xml:ns:test", "2014-06-02", "test-module" )),
+                      actualCapabilites.getModuleBasedCaps() );
+        assertEquals( "isRollbackSupported", true, actualCapabilites.isRollbackSupported() );
+        assertEquals( "isMonitoringSupported", true, actualCapabilites.isMonitoringSupported() );
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(timeout=5000)
+    public void testOnSessionDown() throws Exception {
+        setupSession();
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture1 = sendRequest();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture2 = sendRequest();
+
+        doNothing().when( mockDevice ).onRemoteSessionDown();
+
+        communicator.onSessionDown( mockSession, new Exception( "mock ex" ) );
+
+        verifyErrorRpcResult( resultFuture1.get(), RpcError.ErrorType.TRANSPORT, "operation-failed" );
+        verifyErrorRpcResult( resultFuture2.get(), RpcError.ErrorType.TRANSPORT, "operation-failed" );
+
+        verify( mockDevice ).onRemoteSessionDown();
+
+        reset( mockDevice );
+
+        communicator.onSessionDown( mockSession, new Exception( "mock ex" ) );
+
+        verify( mockDevice, never() ).onRemoteSessionDown();
+    }
+
+    @Test
+    public void testOnSessionTerminated() throws Exception {
+        setupSession();
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = sendRequest();
+
+        doNothing().when( mockDevice ).onRemoteSessionDown();
+
+        String reasonText = "testing terminate";
+        NetconfTerminationReason reason = new NetconfTerminationReason( reasonText );
+        communicator.onSessionTerminated( mockSession, reason );
+
+        RpcError rpcError = verifyErrorRpcResult( resultFuture.get(), RpcError.ErrorType.TRANSPORT,
+                                                  "operation-failed" );
+        assertEquals( "RpcError message", reasonText, rpcError.getMessage() );
+
+        verify( mockDevice ).onRemoteSessionDown();
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        communicator.close();
+        verify( mockDevice, never() ).onRemoteSessionDown();
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testSendRequest() throws Exception {
+        setupSession();
+
+        NetconfMessage message = new NetconfMessage(
+                              DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() );
+        QName rpc = QName.create( "mock rpc" );
+
+        ArgumentCaptor<GenericFutureListener> futureListener =
+                                            ArgumentCaptor.forClass( GenericFutureListener.class );
+
+        ChannelFuture mockChannelFuture = mock( ChannelFuture.class );
+        doReturn( mockChannelFuture ).when( mockChannelFuture ).addListener( futureListener.capture() );
+        doReturn( mockChannelFuture ).when( mockSession ).sendMessage( same( message ) );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = communicator.sendRequest( message, rpc );
+
+        verify( mockSession ).sendMessage( same( message ) );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+
+        verify( mockChannelFuture ).addListener( futureListener.capture() );
+        Future<Void> operationFuture = mock( Future.class );
+        doReturn( true ).when( operationFuture ).isSuccess();
+        doReturn( true ).when( operationFuture ).isDone();
+        futureListener.getValue().operationComplete( operationFuture );
+
+        try {
+            resultFuture.get( 1, TimeUnit.MILLISECONDS ); // verify it's not cancelled or has an error set
+        }
+        catch( TimeoutException e ) {} // expected
+    }
+
+    @Test
+    public void testSendRequestWithNoSession() throws Exception {
+        NetconfMessage message = new NetconfMessage(
+                              DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() );
+        QName rpc = QName.create( "mock rpc" );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = communicator.sendRequest( message, rpc );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+
+        // Should have an immediate result
+        RpcResult<NetconfMessage> rpcResult = resultFuture.get( 3, TimeUnit.MILLISECONDS );
+
+        verifyErrorRpcResult( rpcResult, RpcError.ErrorType.TRANSPORT, "operation-failed" );
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testSendRequestWithWithSendFailure() throws Exception {
+        setupSession();
+
+        NetconfMessage message = new NetconfMessage(
+                              DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() );
+        QName rpc = QName.create( "mock rpc" );
+
+        ArgumentCaptor<GenericFutureListener> futureListener =
+                                            ArgumentCaptor.forClass( GenericFutureListener.class );
+
+        ChannelFuture mockChannelFuture = mock( ChannelFuture.class );
+        doReturn( mockChannelFuture ).when( mockChannelFuture ).addListener( futureListener.capture() );
+        doReturn( mockChannelFuture ).when( mockSession ).sendMessage( same( message ) );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = communicator.sendRequest( message, rpc );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+
+        verify( mockChannelFuture ).addListener( futureListener.capture() );
+
+        Future<Void> operationFuture = mock( Future.class );
+        doReturn( false ).when( operationFuture ).isSuccess();
+        doReturn( true ).when( operationFuture ).isDone();
+        doReturn( new Exception( "mock error" ) ).when( operationFuture ).cause();
+        futureListener.getValue().operationComplete( operationFuture );
+
+        // Should have an immediate result
+        RpcResult<NetconfMessage> rpcResult = resultFuture.get( 3, TimeUnit.MILLISECONDS );
+
+        RpcError rpcError = verifyErrorRpcResult( rpcResult, RpcError.ErrorType.TRANSPORT, "operation-failed" );
+        assertEquals( "RpcError message contains \"mock error\"", true,
+                    rpcError.getMessage().contains( "mock error" ) );
+    }
+
+    private NetconfMessage createSuccessResponseMessage( String messageID ) throws ParserConfigurationException {
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+        Element rpcReply = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_REPLY_KEY );
+        rpcReply.setAttribute( "message-id", messageID );
+        Element element = doc.createElementNS( "ns", "data" );
+        element.setTextContent( messageID );
+        rpcReply.appendChild( element );
+        doc.appendChild( rpcReply );
+
+        return new NetconfMessage( doc );
+    }
+
+    @Test
+    public void testOnSuccessfulResponseMessage() throws Exception {
+        setupSession();
+
+        String messageID1 = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture1 = sendRequest( messageID1 );
+
+        String messageID2 = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture2 = sendRequest( messageID2 );
+
+        communicator.onMessage( mockSession, createSuccessResponseMessage( messageID1 ) );
+        communicator.onMessage( mockSession, createSuccessResponseMessage( messageID2 ) );
+
+        verifyResponseMessage( resultFuture1.get(), messageID1 );
+        verifyResponseMessage( resultFuture2.get(), messageID2 );
+    }
+
+    @Test
+    public void testOnResponseMessageWithError() throws Exception {
+        setupSession();
+
+        String messageID = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = sendRequest( messageID );
+
+        communicator.onMessage( mockSession, createErrorResponseMessage( messageID ) );
+
+        RpcError rpcError = verifyErrorRpcResult( resultFuture.get(), RpcError.ErrorType.RPC,
+                                                  "missing-attribute" );
+        assertEquals( "RpcError message", "Missing attribute", rpcError.getMessage() );
+
+        String errorInfo = rpcError.getInfo();
+        assertNotNull( "RpcError info is null", errorInfo );
+        assertEquals( "Error info contains \"foo\"", true,
+                      errorInfo.contains( "<bad-attribute>foo</bad-attribute>" ) );
+        assertEquals( "Error info contains \"bar\"", true,
+                      errorInfo.contains( "<bad-element>bar</bad-element>" ) );
+    }
+
+    @Test
+    public void testOnResponseMessageWithWrongMessageID() throws Exception {
+        setupSession();
+
+        String messageID = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = sendRequest( messageID );
+
+        communicator.onMessage( mockSession, createSuccessResponseMessage( UUID.randomUUID().toString() ) );
+
+        RpcError rpcError = verifyErrorRpcResult( resultFuture.get(), RpcError.ErrorType.PROTOCOL,
+                                                  "bad-attribute" );
+        assertEquals( "RpcError message non-empty", true,
+                      !Strings.isNullOrEmpty( rpcError.getMessage() ) );
+
+        String errorInfo = rpcError.getInfo();
+        assertNotNull( "RpcError info is null", errorInfo );
+        assertEquals( "Error info contains \"actual-message-id\"", true,
+                      errorInfo.contains( "actual-message-id" ) );
+        assertEquals( "Error info contains \"expected-message-id\"", true,
+                      errorInfo.contains( "expected-message-id" ) );
+    }
+
+    private NetconfMessage createErrorResponseMessage( String messageID ) throws Exception {
+        String xmlStr =
+            "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"" +
+            "           message-id=\"" + messageID + "\">" +
+            "  <rpc-error>" +
+            "    <error-type>rpc</error-type>" +
+            "    <error-tag>missing-attribute</error-tag>" +
+            "    <error-severity>error</error-severity>" +
+            "    <error-message>Missing attribute</error-message>" +
+            "    <error-info>" +
+            "      <bad-attribute>foo</bad-attribute>" +
+            "      <bad-element>bar</bad-element>" +
+            "    </error-info>" +
+            "  </rpc-error>" +
+            "</rpc-reply>";
+
+        ByteArrayInputStream bis = new ByteArrayInputStream( xmlStr.getBytes() );
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( bis );
+        return new NetconfMessage( doc );
+    }
+
+    private void verifyResponseMessage( RpcResult<NetconfMessage> rpcResult, String dataText ) {
+        assertNotNull( "RpcResult is null", rpcResult );
+        assertEquals( "isSuccessful", true, rpcResult.isSuccessful() );
+        NetconfMessage messageResult = rpcResult.getResult();
+        assertNotNull( "getResult", messageResult );
+//        List<SimpleNode<?>> nodes = messageResult.getSimpleNodesByName(
+//                                         QName.create( URI.create( "ns" ), null, "data" ) );
+//        assertNotNull( "getSimpleNodesByName", nodes );
+//        assertEquals( "List<SimpleNode<?>> size", 1, nodes.size() );
+//        assertEquals( "SimpleNode value", dataText, nodes.iterator().next().getValue() );
+    }
+
+    private RpcError verifyErrorRpcResult( RpcResult<NetconfMessage> rpcResult,
+                                           RpcError.ErrorType expErrorType, String expErrorTag ) {
+        assertNotNull( "RpcResult is null", rpcResult );
+        assertEquals( "isSuccessful", false, rpcResult.isSuccessful() );
+        assertNotNull( "RpcResult errors is null", rpcResult.getErrors() );
+        assertEquals( "Errors size", 1, rpcResult.getErrors().size() );
+        RpcError rpcError = rpcResult.getErrors().iterator().next();
+        assertEquals( "getErrorSeverity", RpcError.ErrorSeverity.ERROR, rpcError.getSeverity() );
+        assertEquals( "getErrorType", expErrorType, rpcError.getErrorType() );
+        assertEquals( "getErrorTag", expErrorTag, rpcError.getTag() );
+        assertTrue( "getMessage is empty", StringUtils.isNotEmpty( rpcError.getMessage() ) );
+        return rpcError;
+    }
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/README-FIRST b/opendaylight/md-sal/sal-protocolbuffer-encoding/README-FIRST
new file mode 100644 (file)
index 0000000..778d8c6
--- /dev/null
@@ -0,0 +1,23 @@
+Instructions on generating the protocol buffer Java source files
+
+These instructions are developers who are planning to generate the protocolbuffer java source files.
+
+1. We are using protocol buffer version 2.5.0 - you need to install the exact same version on your box.
+The download link is https://code.google.com/p/protobuf/downloads/list. Download .tar/zip based on
+your OS.
+
+2. Once downloaded the tar/zip and extracted follow the README instructions to compile protoc on your
+machine
+
+3. Create your .proto (IDL) file in resources folder. Give appropriate package name so that the source
+   get generation in proper packages. For more information  check
+   https://developers.google.com/protocol-buffers/docs/javatutorial
+
+   For detailed information https://developers.google.com/protocol-buffers/docs/reference/java-generated
+
+4. To generate the java source files execute in sal-protocolbuffer-encoding directory
+   just run.sh in sal-protocolbuffer-encoding or execute the following command
+
+ protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto
+
+5. Run mvn clean install and resolve any trailing spaces issues & build the .jar
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml b/opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml
new file mode 100644 (file)
index 0000000..671a944
--- /dev/null
@@ -0,0 +1,28 @@
+<?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>
+  </parent>
+
+  <artifactId>sal-protocolbuffer-encoding</artifactId>
+
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.protobuf</groupId>
+      <artifactId>protobuf-java</artifactId>
+      <version>2.5.0</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/run.sh b/opendaylight/md-sal/sal-protocolbuffer-encoding/run.sh
new file mode 100755 (executable)
index 0000000..72e2c87
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+#####################################################################################################
+#Instructions on generating the protocol buffer Java source files
+#
+#These instructions are developers who are planning to generate the protocolbuffer java source files.
+#
+#1. We are using protocol buffer version 2.5.0 - you need to install the exact same version on your box.
+#The download link is https://code.google.com/p/protobuf/downloads/list. Download .tar/zip based on
+#your OS.
+#
+#2. Once downloaded the tar/zip and extracted follow the README instructions to compile protoc on your
+#machine
+#
+#3. Create your .proto (IDL) file in resources folder. Give appropriate package name so that the source
+#   get generation in proper packages. For more information  check
+#   https://developers.google.com/protocol-buffers/docs/javatutorial
+#
+#   For detailed information https://developers.google.com/protocol-buffers/docs/reference/java-generated
+#
+#4. To generate the java source files execute in sal-protocolbuffer-encoding execute ./run.sh i.e. this script
+# or run command
+#       protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto
+#
+#5. Run mvn clean install and resolve any trailing spaces issues & build the .jar
+########################################################################################################
+
+protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto
+
+echo "Done generating Java source files."
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/registration/ListenerRegistrationMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/registration/ListenerRegistrationMessages.java
new file mode 100644 (file)
index 0000000..afcb455
--- /dev/null
@@ -0,0 +1,681 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: ListenerRegistration.proto
+
+package org.opendaylight.controller.cluster.datastore.registration;
+
+public final class ListenerRegistrationMessages {
+  private ListenerRegistrationMessages() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface CloseOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.Close}
+   */
+  public static final class Close extends
+      com.google.protobuf.GeneratedMessage
+      implements CloseOrBuilder {
+    // Use Close.newBuilder() to construct.
+    private Close(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private Close(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final Close defaultInstance;
+    public static Close getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public Close getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private Close(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_Close_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_Close_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close.class, org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<Close> PARSER =
+        new com.google.protobuf.AbstractParser<Close>() {
+      public Close parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new Close(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<Close> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.Close}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_Close_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_Close_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close.class, org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_Close_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close build() {
+        org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close buildPartial() {
+        org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close result = new org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close other) {
+        if (other == org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.Close) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.Close)
+    }
+
+    static {
+      defaultInstance = new Close(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.Close)
+  }
+
+  public interface CloseReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CloseReply}
+   */
+  public static final class CloseReply extends
+      com.google.protobuf.GeneratedMessage
+      implements CloseReplyOrBuilder {
+    // Use CloseReply.newBuilder() to construct.
+    private CloseReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CloseReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CloseReply defaultInstance;
+    public static CloseReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CloseReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CloseReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_CloseReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_CloseReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply.class, org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CloseReply> PARSER =
+        new com.google.protobuf.AbstractParser<CloseReply>() {
+      public CloseReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CloseReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CloseReply> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CloseReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_CloseReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_CloseReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply.class, org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.internal_static_org_opendaylight_controller_mdsal_CloseReply_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply build() {
+        org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply buildPartial() {
+        org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply result = new org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply other) {
+        if (other == org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.registration.ListenerRegistrationMessages.CloseReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CloseReply)
+    }
+
+    static {
+      defaultInstance = new CloseReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CloseReply)
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_Close_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_Close_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CloseReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CloseReply_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\032ListenerRegistration.proto\022!org.openda" +
+      "ylight.controller.mdsal\"\007\n\005Close\"\014\n\nClos" +
+      "eReplyBZ\n:org.opendaylight.controller.cl" +
+      "uster.datastore.registrationB\034ListenerRe" +
+      "gistrationMessages"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+        public com.google.protobuf.ExtensionRegistry assignDescriptors(
+            com.google.protobuf.Descriptors.FileDescriptor root) {
+          descriptor = root;
+          internal_static_org_opendaylight_controller_mdsal_Close_descriptor =
+            getDescriptor().getMessageTypes().get(0);
+          internal_static_org_opendaylight_controller_mdsal_Close_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_Close_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_CloseReply_descriptor =
+            getDescriptor().getMessageTypes().get(1);
+          internal_static_org_opendaylight_controller_mdsal_CloseReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CloseReply_descriptor,
+              new java.lang.String[] { });
+          return null;
+        }
+      };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/shard/ShardManagerMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/shard/ShardManagerMessages.java
new file mode 100644 (file)
index 0000000..a8f1bf0
--- /dev/null
@@ -0,0 +1,1172 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: ShardManager.proto
+
+package org.opendaylight.controller.cluster.datastore.shard;
+
+public final class ShardManagerMessages {
+  private ShardManagerMessages() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface FindPrimaryOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string shardName = 1;
+    /**
+     * <code>required string shardName = 1;</code>
+     */
+    boolean hasShardName();
+    /**
+     * <code>required string shardName = 1;</code>
+     */
+    java.lang.String getShardName();
+    /**
+     * <code>required string shardName = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getShardNameBytes();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.FindPrimary}
+   */
+  public static final class FindPrimary extends
+      com.google.protobuf.GeneratedMessage
+      implements FindPrimaryOrBuilder {
+    // Use FindPrimary.newBuilder() to construct.
+    private FindPrimary(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private FindPrimary(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final FindPrimary defaultInstance;
+    public static FindPrimary getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public FindPrimary getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private FindPrimary(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              shardName_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_FindPrimary_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_FindPrimary_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary.class, org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<FindPrimary> PARSER =
+        new com.google.protobuf.AbstractParser<FindPrimary>() {
+      public FindPrimary parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new FindPrimary(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<FindPrimary> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required string shardName = 1;
+    public static final int SHARDNAME_FIELD_NUMBER = 1;
+    private java.lang.Object shardName_;
+    /**
+     * <code>required string shardName = 1;</code>
+     */
+    public boolean hasShardName() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string shardName = 1;</code>
+     */
+    public java.lang.String getShardName() {
+      java.lang.Object ref = shardName_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          shardName_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string shardName = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getShardNameBytes() {
+      java.lang.Object ref = shardName_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        shardName_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      shardName_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasShardName()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getShardNameBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getShardNameBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.FindPrimary}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimaryOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_FindPrimary_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_FindPrimary_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary.class, org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        shardName_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_FindPrimary_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary build() {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary buildPartial() {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary result = new org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.shardName_ = shardName_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary other) {
+        if (other == org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary.getDefaultInstance()) return this;
+        if (other.hasShardName()) {
+          bitField0_ |= 0x00000001;
+          shardName_ = other.shardName_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasShardName()) {
+
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.FindPrimary) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required string shardName = 1;
+      private java.lang.Object shardName_ = "";
+      /**
+       * <code>required string shardName = 1;</code>
+       */
+      public boolean hasShardName() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required string shardName = 1;</code>
+       */
+      public java.lang.String getShardName() {
+        java.lang.Object ref = shardName_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          shardName_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string shardName = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getShardNameBytes() {
+        java.lang.Object ref = shardName_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          shardName_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string shardName = 1;</code>
+       */
+      public Builder setShardName(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        shardName_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string shardName = 1;</code>
+       */
+      public Builder clearShardName() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        shardName_ = getDefaultInstance().getShardName();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string shardName = 1;</code>
+       */
+      public Builder setShardNameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        shardName_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.FindPrimary)
+    }
+
+    static {
+      defaultInstance = new FindPrimary(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.FindPrimary)
+  }
+
+  public interface PrimaryFoundOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.PrimaryFound}
+   */
+  public static final class PrimaryFound extends
+      com.google.protobuf.GeneratedMessage
+      implements PrimaryFoundOrBuilder {
+    // Use PrimaryFound.newBuilder() to construct.
+    private PrimaryFound(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private PrimaryFound(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final PrimaryFound defaultInstance;
+    public static PrimaryFound getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public PrimaryFound getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private PrimaryFound(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryFound_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryFound_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound.class, org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<PrimaryFound> PARSER =
+        new com.google.protobuf.AbstractParser<PrimaryFound>() {
+      public PrimaryFound parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new PrimaryFound(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<PrimaryFound> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.PrimaryFound}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFoundOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryFound_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryFound_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound.class, org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryFound_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound build() {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound buildPartial() {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound result = new org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound other) {
+        if (other == org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryFound) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.PrimaryFound)
+    }
+
+    static {
+      defaultInstance = new PrimaryFound(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.PrimaryFound)
+  }
+
+  public interface PrimaryNotFoundOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.PrimaryNotFound}
+   */
+  public static final class PrimaryNotFound extends
+      com.google.protobuf.GeneratedMessage
+      implements PrimaryNotFoundOrBuilder {
+    // Use PrimaryNotFound.newBuilder() to construct.
+    private PrimaryNotFound(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private PrimaryNotFound(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final PrimaryNotFound defaultInstance;
+    public static PrimaryNotFound getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public PrimaryNotFound getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private PrimaryNotFound(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound.class, org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<PrimaryNotFound> PARSER =
+        new com.google.protobuf.AbstractParser<PrimaryNotFound>() {
+      public PrimaryNotFound parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new PrimaryNotFound(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<PrimaryNotFound> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.PrimaryNotFound}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFoundOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound.class, org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound build() {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound buildPartial() {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound result = new org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound other) {
+        if (other == org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages.PrimaryNotFound) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.PrimaryNotFound)
+    }
+
+    static {
+      defaultInstance = new PrimaryNotFound(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.PrimaryNotFound)
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_FindPrimary_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_FindPrimary_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_PrimaryFound_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_PrimaryFound_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\022ShardManager.proto\022!org.opendaylight.c" +
+      "ontroller.mdsal\" \n\013FindPrimary\022\021\n\tshardN" +
+      "ame\030\001 \002(\t\"\016\n\014PrimaryFound\"\021\n\017PrimaryNotF" +
+      "oundBK\n3org.opendaylight.controller.clus" +
+      "ter.datastore.shardB\024ShardManagerMessage" +
+      "s"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+        public com.google.protobuf.ExtensionRegistry assignDescriptors(
+            com.google.protobuf.Descriptors.FileDescriptor root) {
+          descriptor = root;
+          internal_static_org_opendaylight_controller_mdsal_FindPrimary_descriptor =
+            getDescriptor().getMessageTypes().get(0);
+          internal_static_org_opendaylight_controller_mdsal_FindPrimary_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_FindPrimary_descriptor,
+              new java.lang.String[] { "ShardName", });
+          internal_static_org_opendaylight_controller_mdsal_PrimaryFound_descriptor =
+            getDescriptor().getMessageTypes().get(1);
+          internal_static_org_opendaylight_controller_mdsal_PrimaryFound_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_PrimaryFound_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_descriptor =
+            getDescriptor().getMessageTypes().get(2);
+          internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_PrimaryNotFound_descriptor,
+              new java.lang.String[] { });
+          return null;
+        }
+      };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/transaction/ShardTransactionChainMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/transaction/ShardTransactionChainMessages.java
new file mode 100644 (file)
index 0000000..5de32c8
--- /dev/null
@@ -0,0 +1,1493 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: ShardTransactionChainMessages.proto
+
+package org.opendaylight.controller.cluster.datastore.transaction;
+
+public final class ShardTransactionChainMessages {
+  private ShardTransactionChainMessages() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface CloseTransactionChainOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransactionChain}
+   */
+  public static final class CloseTransactionChain extends
+      com.google.protobuf.GeneratedMessage
+      implements CloseTransactionChainOrBuilder {
+    // Use CloseTransactionChain.newBuilder() to construct.
+    private CloseTransactionChain(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CloseTransactionChain(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CloseTransactionChain defaultInstance;
+    public static CloseTransactionChain getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CloseTransactionChain getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CloseTransactionChain(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CloseTransactionChain> PARSER =
+        new com.google.protobuf.AbstractParser<CloseTransactionChain>() {
+      public CloseTransactionChain parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CloseTransactionChain(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CloseTransactionChain> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransactionChain}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChain) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CloseTransactionChain)
+    }
+
+    static {
+      defaultInstance = new CloseTransactionChain(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CloseTransactionChain)
+  }
+
+  public interface CloseTransactionChainReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransactionChainReply}
+   */
+  public static final class CloseTransactionChainReply extends
+      com.google.protobuf.GeneratedMessage
+      implements CloseTransactionChainReplyOrBuilder {
+    // Use CloseTransactionChainReply.newBuilder() to construct.
+    private CloseTransactionChainReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CloseTransactionChainReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CloseTransactionChainReply defaultInstance;
+    public static CloseTransactionChainReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CloseTransactionChainReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CloseTransactionChainReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CloseTransactionChainReply> PARSER =
+        new com.google.protobuf.AbstractParser<CloseTransactionChainReply>() {
+      public CloseTransactionChainReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CloseTransactionChainReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CloseTransactionChainReply> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransactionChainReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CloseTransactionChainReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CloseTransactionChainReply)
+    }
+
+    static {
+      defaultInstance = new CloseTransactionChainReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CloseTransactionChainReply)
+  }
+
+  public interface CreateTransactionChainOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransactionChain}
+   */
+  public static final class CreateTransactionChain extends
+      com.google.protobuf.GeneratedMessage
+      implements CreateTransactionChainOrBuilder {
+    // Use CreateTransactionChain.newBuilder() to construct.
+    private CreateTransactionChain(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CreateTransactionChain(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CreateTransactionChain defaultInstance;
+    public static CreateTransactionChain getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CreateTransactionChain getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CreateTransactionChain(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CreateTransactionChain> PARSER =
+        new com.google.protobuf.AbstractParser<CreateTransactionChain>() {
+      public CreateTransactionChain parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CreateTransactionChain(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CreateTransactionChain> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransactionChain}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChain) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CreateTransactionChain)
+    }
+
+    static {
+      defaultInstance = new CreateTransactionChain(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CreateTransactionChain)
+  }
+
+  public interface CreateTransactionChainReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string transactionChainPath = 1;
+    /**
+     * <code>required string transactionChainPath = 1;</code>
+     */
+    boolean hasTransactionChainPath();
+    /**
+     * <code>required string transactionChainPath = 1;</code>
+     */
+    java.lang.String getTransactionChainPath();
+    /**
+     * <code>required string transactionChainPath = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getTransactionChainPathBytes();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransactionChainReply}
+   */
+  public static final class CreateTransactionChainReply extends
+      com.google.protobuf.GeneratedMessage
+      implements CreateTransactionChainReplyOrBuilder {
+    // Use CreateTransactionChainReply.newBuilder() to construct.
+    private CreateTransactionChainReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CreateTransactionChainReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CreateTransactionChainReply defaultInstance;
+    public static CreateTransactionChainReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CreateTransactionChainReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CreateTransactionChainReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              transactionChainPath_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CreateTransactionChainReply> PARSER =
+        new com.google.protobuf.AbstractParser<CreateTransactionChainReply>() {
+      public CreateTransactionChainReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CreateTransactionChainReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CreateTransactionChainReply> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required string transactionChainPath = 1;
+    public static final int TRANSACTIONCHAINPATH_FIELD_NUMBER = 1;
+    private java.lang.Object transactionChainPath_;
+    /**
+     * <code>required string transactionChainPath = 1;</code>
+     */
+    public boolean hasTransactionChainPath() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string transactionChainPath = 1;</code>
+     */
+    public java.lang.String getTransactionChainPath() {
+      java.lang.Object ref = transactionChainPath_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          transactionChainPath_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string transactionChainPath = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getTransactionChainPathBytes() {
+      java.lang.Object ref = transactionChainPath_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        transactionChainPath_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      transactionChainPath_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasTransactionChainPath()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getTransactionChainPathBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getTransactionChainPathBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransactionChainReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        transactionChainPath_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.transactionChainPath_ = transactionChainPath_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply.getDefaultInstance()) return this;
+        if (other.hasTransactionChainPath()) {
+          bitField0_ |= 0x00000001;
+          transactionChainPath_ = other.transactionChainPath_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasTransactionChainPath()){
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionChainMessages.CreateTransactionChainReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required string transactionChainPath = 1;
+      private java.lang.Object transactionChainPath_ = "";
+      /**
+       * <code>required string transactionChainPath = 1;</code>
+       */
+      public boolean hasTransactionChainPath() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required string transactionChainPath = 1;</code>
+       */
+      public java.lang.String getTransactionChainPath() {
+        java.lang.Object ref = transactionChainPath_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          transactionChainPath_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string transactionChainPath = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getTransactionChainPathBytes() {
+        java.lang.Object ref = transactionChainPath_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          transactionChainPath_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string transactionChainPath = 1;</code>
+       */
+      public Builder setTransactionChainPath(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        transactionChainPath_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string transactionChainPath = 1;</code>
+       */
+      public Builder clearTransactionChainPath() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        transactionChainPath_ = getDefaultInstance().getTransactionChainPath();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string transactionChainPath = 1;</code>
+       */
+      public Builder setTransactionChainPathBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        transactionChainPath_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CreateTransactionChainReply)
+    }
+
+    static {
+      defaultInstance = new CreateTransactionChainReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CreateTransactionChainReply)
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n#ShardTransactionChainMessages.proto\022!o" +
+      "rg.opendaylight.controller.mdsal\"\027\n\025Clos" +
+      "eTransactionChain\"\034\n\032CloseTransactionCha" +
+      "inReply\"\030\n\026CreateTransactionChain\";\n\033Cre" +
+      "ateTransactionChainReply\022\034\n\024transactionC" +
+      "hainPath\030\001 \002(\tBZ\n9org.opendaylight.contr" +
+      "oller.cluster.datastore.transactionB\035Sha" +
+      "rdTransactionChainMessages"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+        public com.google.protobuf.ExtensionRegistry assignDescriptors(
+            com.google.protobuf.Descriptors.FileDescriptor root) {
+          descriptor = root;
+          internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_descriptor =
+            getDescriptor().getMessageTypes().get(0);
+          internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CloseTransactionChain_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_descriptor =
+            getDescriptor().getMessageTypes().get(1);
+          internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CloseTransactionChainReply_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_descriptor =
+            getDescriptor().getMessageTypes().get(2);
+          internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CreateTransactionChain_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_descriptor =
+            getDescriptor().getMessageTypes().get(3);
+          internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CreateTransactionChainReply_descriptor,
+              new java.lang.String[] { "TransactionChainPath", });
+          return null;
+        }
+      };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/transaction/ShardTransactionMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/transaction/ShardTransactionMessages.java
new file mode 100644 (file)
index 0000000..3a226db
--- /dev/null
@@ -0,0 +1,3606 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: ShardTransactionMessages.proto
+
+package org.opendaylight.controller.cluster.datastore.transaction;
+
+public final class ShardTransactionMessages {
+  private ShardTransactionMessages() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface CloseTransactionOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransaction}
+   */
+  public static final class CloseTransaction extends
+      com.google.protobuf.GeneratedMessage
+      implements CloseTransactionOrBuilder {
+    // Use CloseTransaction.newBuilder() to construct.
+    private CloseTransaction(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CloseTransaction(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CloseTransaction defaultInstance;
+    public static CloseTransaction getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CloseTransaction getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CloseTransaction(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransaction_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CloseTransaction> PARSER =
+        new com.google.protobuf.AbstractParser<CloseTransaction>() {
+      public CloseTransaction parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CloseTransaction(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CloseTransaction> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransaction}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransaction_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransaction) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CloseTransaction)
+    }
+
+    static {
+      defaultInstance = new CloseTransaction(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CloseTransaction)
+  }
+
+  public interface CloseTransactionReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransactionReply}
+   */
+  public static final class CloseTransactionReply extends
+      com.google.protobuf.GeneratedMessage
+      implements CloseTransactionReplyOrBuilder {
+    // Use CloseTransactionReply.newBuilder() to construct.
+    private CloseTransactionReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CloseTransactionReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CloseTransactionReply defaultInstance;
+    public static CloseTransactionReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CloseTransactionReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CloseTransactionReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CloseTransactionReply> PARSER =
+        new com.google.protobuf.AbstractParser<CloseTransactionReply>() {
+      public CloseTransactionReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CloseTransactionReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CloseTransactionReply> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CloseTransactionReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CloseTransactionReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CloseTransactionReply)
+    }
+
+    static {
+      defaultInstance = new CloseTransactionReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CloseTransactionReply)
+  }
+
+  public interface CreateTransactionOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransaction}
+   */
+  public static final class CreateTransaction extends
+      com.google.protobuf.GeneratedMessage
+      implements CreateTransactionOrBuilder {
+    // Use CreateTransaction.newBuilder() to construct.
+    private CreateTransaction(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CreateTransaction(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CreateTransaction defaultInstance;
+    public static CreateTransaction getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CreateTransaction getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CreateTransaction(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransaction_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CreateTransaction> PARSER =
+        new com.google.protobuf.AbstractParser<CreateTransaction>() {
+      public CreateTransaction parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CreateTransaction(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CreateTransaction> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransaction}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransaction_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransaction) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CreateTransaction)
+    }
+
+    static {
+      defaultInstance = new CreateTransaction(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CreateTransaction)
+  }
+
+  public interface CreateTransactionReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string transactionPath = 1;
+    /**
+     * <code>required string transactionPath = 1;</code>
+     */
+    boolean hasTransactionPath();
+    /**
+     * <code>required string transactionPath = 1;</code>
+     */
+    java.lang.String getTransactionPath();
+    /**
+     * <code>required string transactionPath = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getTransactionPathBytes();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransactionReply}
+   */
+  public static final class CreateTransactionReply extends
+      com.google.protobuf.GeneratedMessage
+      implements CreateTransactionReplyOrBuilder {
+    // Use CreateTransactionReply.newBuilder() to construct.
+    private CreateTransactionReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CreateTransactionReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CreateTransactionReply defaultInstance;
+    public static CreateTransactionReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CreateTransactionReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CreateTransactionReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              transactionPath_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CreateTransactionReply> PARSER =
+        new com.google.protobuf.AbstractParser<CreateTransactionReply>() {
+      public CreateTransactionReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CreateTransactionReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CreateTransactionReply> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required string transactionPath = 1;
+    public static final int TRANSACTIONPATH_FIELD_NUMBER = 1;
+    private java.lang.Object transactionPath_;
+    /**
+     * <code>required string transactionPath = 1;</code>
+     */
+    public boolean hasTransactionPath() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string transactionPath = 1;</code>
+     */
+    public java.lang.String getTransactionPath() {
+      java.lang.Object ref = transactionPath_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          transactionPath_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string transactionPath = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getTransactionPathBytes() {
+      java.lang.Object ref = transactionPath_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        transactionPath_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      transactionPath_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasTransactionPath()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getTransactionPathBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getTransactionPathBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransactionReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        transactionPath_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.transactionPath_ = transactionPath_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply.getDefaultInstance()) return this;
+        if (other.hasTransactionPath()) {
+          bitField0_ |= 0x00000001;
+          transactionPath_ = other.transactionPath_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasTransactionPath()) {
+
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.CreateTransactionReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required string transactionPath = 1;
+      private java.lang.Object transactionPath_ = "";
+      /**
+       * <code>required string transactionPath = 1;</code>
+       */
+      public boolean hasTransactionPath() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required string transactionPath = 1;</code>
+       */
+      public java.lang.String getTransactionPath() {
+        java.lang.Object ref = transactionPath_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          transactionPath_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string transactionPath = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getTransactionPathBytes() {
+        java.lang.Object ref = transactionPath_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          transactionPath_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string transactionPath = 1;</code>
+       */
+      public Builder setTransactionPath(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        transactionPath_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string transactionPath = 1;</code>
+       */
+      public Builder clearTransactionPath() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        transactionPath_ = getDefaultInstance().getTransactionPath();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string transactionPath = 1;</code>
+       */
+      public Builder setTransactionPathBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        transactionPath_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CreateTransactionReply)
+    }
+
+    static {
+      defaultInstance = new CreateTransactionReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.CreateTransactionReply)
+  }
+
+  public interface ReadyTransactionOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.ReadyTransaction}
+   */
+  public static final class ReadyTransaction extends
+      com.google.protobuf.GeneratedMessage
+      implements ReadyTransactionOrBuilder {
+    // Use ReadyTransaction.newBuilder() to construct.
+    private ReadyTransaction(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReadyTransaction(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReadyTransaction defaultInstance;
+    public static ReadyTransaction getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReadyTransaction getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReadyTransaction(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReadyTransaction> PARSER =
+        new com.google.protobuf.AbstractParser<ReadyTransaction>() {
+      public ReadyTransaction parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReadyTransaction(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReadyTransaction> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.ReadyTransaction}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransaction) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.ReadyTransaction)
+    }
+
+    static {
+      defaultInstance = new ReadyTransaction(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.ReadyTransaction)
+  }
+
+  public interface ReadyTransactionReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string actorPath = 1;
+    /**
+     * <code>required string actorPath = 1;</code>
+     */
+    boolean hasActorPath();
+    /**
+     * <code>required string actorPath = 1;</code>
+     */
+    java.lang.String getActorPath();
+    /**
+     * <code>required string actorPath = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getActorPathBytes();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.ReadyTransactionReply}
+   */
+  public static final class ReadyTransactionReply extends
+      com.google.protobuf.GeneratedMessage
+      implements ReadyTransactionReplyOrBuilder {
+    // Use ReadyTransactionReply.newBuilder() to construct.
+    private ReadyTransactionReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReadyTransactionReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReadyTransactionReply defaultInstance;
+    public static ReadyTransactionReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReadyTransactionReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReadyTransactionReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              actorPath_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReadyTransactionReply> PARSER =
+        new com.google.protobuf.AbstractParser<ReadyTransactionReply>() {
+      public ReadyTransactionReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReadyTransactionReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReadyTransactionReply> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required string actorPath = 1;
+    public static final int ACTORPATH_FIELD_NUMBER = 1;
+    private java.lang.Object actorPath_;
+    /**
+     * <code>required string actorPath = 1;</code>
+     */
+    public boolean hasActorPath() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string actorPath = 1;</code>
+     */
+    public java.lang.String getActorPath() {
+      java.lang.Object ref = actorPath_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          actorPath_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string actorPath = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getActorPathBytes() {
+      java.lang.Object ref = actorPath_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        actorPath_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      actorPath_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasActorPath()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getActorPathBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getActorPathBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.ReadyTransactionReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        actorPath_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.actorPath_ = actorPath_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply.getDefaultInstance()) return this;
+        if (other.hasActorPath()) {
+          bitField0_ |= 0x00000001;
+          actorPath_ = other.actorPath_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasActorPath()) {
+
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadyTransactionReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required string actorPath = 1;
+      private java.lang.Object actorPath_ = "";
+      /**
+       * <code>required string actorPath = 1;</code>
+       */
+      public boolean hasActorPath() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required string actorPath = 1;</code>
+       */
+      public java.lang.String getActorPath() {
+        java.lang.Object ref = actorPath_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          actorPath_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string actorPath = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getActorPathBytes() {
+        java.lang.Object ref = actorPath_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          actorPath_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string actorPath = 1;</code>
+       */
+      public Builder setActorPath(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        actorPath_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string actorPath = 1;</code>
+       */
+      public Builder clearActorPath() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        actorPath_ = getDefaultInstance().getActorPath();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string actorPath = 1;</code>
+       */
+      public Builder setActorPathBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        actorPath_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.ReadyTransactionReply)
+    }
+
+    static {
+      defaultInstance = new ReadyTransactionReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.ReadyTransactionReply)
+  }
+
+  public interface DeleteDataOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string instanceIdentifierPath = 1;
+    /**
+     * <code>required string instanceIdentifierPath = 1;</code>
+     */
+    boolean hasInstanceIdentifierPath();
+    /**
+     * <code>required string instanceIdentifierPath = 1;</code>
+     */
+    java.lang.String getInstanceIdentifierPath();
+    /**
+     * <code>required string instanceIdentifierPath = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getInstanceIdentifierPathBytes();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.DeleteData}
+   */
+  public static final class DeleteData extends
+      com.google.protobuf.GeneratedMessage
+      implements DeleteDataOrBuilder {
+    // Use DeleteData.newBuilder() to construct.
+    private DeleteData(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private DeleteData(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final DeleteData defaultInstance;
+    public static DeleteData getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public DeleteData getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private DeleteData(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              instanceIdentifierPath_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteData_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteData_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<DeleteData> PARSER =
+        new com.google.protobuf.AbstractParser<DeleteData>() {
+      public DeleteData parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new DeleteData(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<DeleteData> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required string instanceIdentifierPath = 1;
+    public static final int INSTANCEIDENTIFIERPATH_FIELD_NUMBER = 1;
+    private java.lang.Object instanceIdentifierPath_;
+    /**
+     * <code>required string instanceIdentifierPath = 1;</code>
+     */
+    public boolean hasInstanceIdentifierPath() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string instanceIdentifierPath = 1;</code>
+     */
+    public java.lang.String getInstanceIdentifierPath() {
+      java.lang.Object ref = instanceIdentifierPath_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          instanceIdentifierPath_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string instanceIdentifierPath = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getInstanceIdentifierPathBytes() {
+      java.lang.Object ref = instanceIdentifierPath_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        instanceIdentifierPath_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      instanceIdentifierPath_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasInstanceIdentifierPath()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getInstanceIdentifierPathBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getInstanceIdentifierPathBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.DeleteData}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteData_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteData_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        instanceIdentifierPath_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteData_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.instanceIdentifierPath_ = instanceIdentifierPath_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData.getDefaultInstance()) return this;
+        if (other.hasInstanceIdentifierPath()) {
+          bitField0_ |= 0x00000001;
+          instanceIdentifierPath_ = other.instanceIdentifierPath_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasInstanceIdentifierPath()) {
+
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteData) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required string instanceIdentifierPath = 1;
+      private java.lang.Object instanceIdentifierPath_ = "";
+      /**
+       * <code>required string instanceIdentifierPath = 1;</code>
+       */
+      public boolean hasInstanceIdentifierPath() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required string instanceIdentifierPath = 1;</code>
+       */
+      public java.lang.String getInstanceIdentifierPath() {
+        java.lang.Object ref = instanceIdentifierPath_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          instanceIdentifierPath_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string instanceIdentifierPath = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getInstanceIdentifierPathBytes() {
+        java.lang.Object ref = instanceIdentifierPath_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          instanceIdentifierPath_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string instanceIdentifierPath = 1;</code>
+       */
+      public Builder setInstanceIdentifierPath(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        instanceIdentifierPath_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string instanceIdentifierPath = 1;</code>
+       */
+      public Builder clearInstanceIdentifierPath() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        instanceIdentifierPath_ = getDefaultInstance().getInstanceIdentifierPath();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string instanceIdentifierPath = 1;</code>
+       */
+      public Builder setInstanceIdentifierPathBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        instanceIdentifierPath_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.DeleteData)
+    }
+
+    static {
+      defaultInstance = new DeleteData(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.DeleteData)
+  }
+
+  public interface DeleteDataReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.DeleteDataReply}
+   */
+  public static final class DeleteDataReply extends
+      com.google.protobuf.GeneratedMessage
+      implements DeleteDataReplyOrBuilder {
+    // Use DeleteDataReply.newBuilder() to construct.
+    private DeleteDataReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private DeleteDataReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final DeleteDataReply defaultInstance;
+    public static DeleteDataReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public DeleteDataReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private DeleteDataReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<DeleteDataReply> PARSER =
+        new com.google.protobuf.AbstractParser<DeleteDataReply>() {
+      public DeleteDataReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new DeleteDataReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<DeleteDataReply> getParserForType() {
+      return PARSER;
+    }
+
+    private void initFields() {
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.DeleteDataReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply(this);
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply.getDefaultInstance()) return this;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.DeleteDataReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.DeleteDataReply)
+    }
+
+    static {
+      defaultInstance = new DeleteDataReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.DeleteDataReply)
+  }
+
+  public interface ReadDataOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string intanceIdentifier = 1;
+    /**
+     * <code>required string intanceIdentifier = 1;</code>
+     */
+    boolean hasIntanceIdentifier();
+    /**
+     * <code>required string intanceIdentifier = 1;</code>
+     */
+    java.lang.String getIntanceIdentifier();
+    /**
+     * <code>required string intanceIdentifier = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getIntanceIdentifierBytes();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.ReadData}
+   */
+  public static final class ReadData extends
+      com.google.protobuf.GeneratedMessage
+      implements ReadDataOrBuilder {
+    // Use ReadData.newBuilder() to construct.
+    private ReadData(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReadData(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReadData defaultInstance;
+    public static ReadData getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReadData getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReadData(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              intanceIdentifier_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadData_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadData_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReadData> PARSER =
+        new com.google.protobuf.AbstractParser<ReadData>() {
+      public ReadData parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReadData(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReadData> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required string intanceIdentifier = 1;
+    public static final int INTANCEIDENTIFIER_FIELD_NUMBER = 1;
+    private java.lang.Object intanceIdentifier_;
+    /**
+     * <code>required string intanceIdentifier = 1;</code>
+     */
+    public boolean hasIntanceIdentifier() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string intanceIdentifier = 1;</code>
+     */
+    public java.lang.String getIntanceIdentifier() {
+      java.lang.Object ref = intanceIdentifier_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          intanceIdentifier_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string intanceIdentifier = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getIntanceIdentifierBytes() {
+      java.lang.Object ref = intanceIdentifier_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        intanceIdentifier_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      intanceIdentifier_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasIntanceIdentifier()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getIntanceIdentifierBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getIntanceIdentifierBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.ReadData}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadDataOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadData_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadData_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData.class, org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        intanceIdentifier_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_ReadData_descriptor;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData getDefaultInstanceForType() {
+        return org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData build() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData buildPartial() {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData result = new org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.intanceIdentifier_ = intanceIdentifier_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData) {
+          return mergeFrom((org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData other) {
+        if (other == org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData.getDefaultInstance()) return this;
+        if (other.hasIntanceIdentifier()) {
+          bitField0_ |= 0x00000001;
+          intanceIdentifier_ = other.intanceIdentifier_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasIntanceIdentifier()) {
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.cluster.datastore.transaction.ShardTransactionMessages.ReadData) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required string intanceIdentifier = 1;
+      private java.lang.Object intanceIdentifier_ = "";
+      /**
+       * <code>required string intanceIdentifier = 1;</code>
+       */
+      public boolean hasIntanceIdentifier() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required string intanceIdentifier = 1;</code>
+       */
+      public java.lang.String getIntanceIdentifier() {
+        java.lang.Object ref = intanceIdentifier_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          intanceIdentifier_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string intanceIdentifier = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getIntanceIdentifierBytes() {
+        java.lang.Object ref = intanceIdentifier_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b =
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          intanceIdentifier_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string intanceIdentifier = 1;</code>
+       */
+      public Builder setIntanceIdentifier(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        intanceIdentifier_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string intanceIdentifier = 1;</code>
+       */
+      public Builder clearIntanceIdentifier() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        intanceIdentifier_ = getDefaultInstance().getIntanceIdentifier();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string intanceIdentifier = 1;</code>
+       */
+      public Builder setIntanceIdentifierBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        intanceIdentifier_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.ReadData)
+    }
+
+    static {
+      defaultInstance = new ReadData(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.ReadData)
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CloseTransaction_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CreateTransaction_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_DeleteData_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_DeleteData_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_ReadData_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_ReadData_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\036ShardTransactionMessages.proto\022!org.op" +
+      "endaylight.controller.mdsal\"\022\n\020CloseTran" +
+      "saction\"\027\n\025CloseTransactionReply\"\023\n\021Crea" +
+      "teTransaction\"1\n\026CreateTransactionReply\022" +
+      "\027\n\017transactionPath\030\001 \002(\t\"\022\n\020ReadyTransac" +
+      "tion\"*\n\025ReadyTransactionReply\022\021\n\tactorPa" +
+      "th\030\001 \002(\t\",\n\nDeleteData\022\036\n\026instanceIdenti" +
+      "fierPath\030\001 \002(\t\"\021\n\017DeleteDataReply\"%\n\010Rea" +
+      "dData\022\031\n\021intanceIdentifier\030\001 \002(\tBU\n9org." +
+      "opendaylight.controller.cluster.datastor",
+      "e.transactionB\030ShardTransactionMessages"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+        public com.google.protobuf.ExtensionRegistry assignDescriptors(
+            com.google.protobuf.Descriptors.FileDescriptor root) {
+          descriptor = root;
+          internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor =
+            getDescriptor().getMessageTypes().get(0);
+          internal_static_org_opendaylight_controller_mdsal_CloseTransaction_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_descriptor =
+            getDescriptor().getMessageTypes().get(1);
+          internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CloseTransactionReply_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor =
+            getDescriptor().getMessageTypes().get(2);
+          internal_static_org_opendaylight_controller_mdsal_CreateTransaction_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor =
+            getDescriptor().getMessageTypes().get(3);
+          internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor,
+              new java.lang.String[] { "TransactionPath", });
+          internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_descriptor =
+            getDescriptor().getMessageTypes().get(4);
+          internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_ReadyTransaction_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_descriptor =
+            getDescriptor().getMessageTypes().get(5);
+          internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_ReadyTransactionReply_descriptor,
+              new java.lang.String[] { "ActorPath", });
+          internal_static_org_opendaylight_controller_mdsal_DeleteData_descriptor =
+            getDescriptor().getMessageTypes().get(6);
+          internal_static_org_opendaylight_controller_mdsal_DeleteData_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_DeleteData_descriptor,
+              new java.lang.String[] { "InstanceIdentifierPath", });
+          internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_descriptor =
+            getDescriptor().getMessageTypes().get(7);
+          internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_DeleteDataReply_descriptor,
+              new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_ReadData_descriptor =
+            getDescriptor().getMessageTypes().get(8);
+          internal_static_org_opendaylight_controller_mdsal_ReadData_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_ReadData_descriptor,
+              new java.lang.String[] { "IntanceIdentifier", });
+          return null;
+        }
+      };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ListenerRegistration.proto b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ListenerRegistration.proto
new file mode 100644 (file)
index 0000000..ec8046f
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.mdsal;
+
+option java_package = "org.opendaylight.controller.cluster.datastore.registration";
+option java_outer_classname = "ListenerRegistrationMessages";
+
+message Close {
+
+}
+
+message CloseReply{
+
+}
+
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardManager.proto b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardManager.proto
new file mode 100644 (file)
index 0000000..31e8c58
--- /dev/null
@@ -0,0 +1,14 @@
+package org.opendaylight.controller.mdsal;
+
+option java_package = "org.opendaylight.controller.cluster.datastore.shard";
+option java_outer_classname = "ShardManagerMessages";
+
+message FindPrimary {
+  required string shardName = 1;
+}
+
+message PrimaryFound {
+}
+
+message PrimaryNotFound {
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransaction.proto b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransaction.proto
new file mode 100644 (file)
index 0000000..0b260c8
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.mdsal;
+
+option java_package = "org.opendaylight.controller.cluster.datastore.transaction";
+option java_outer_classname = "ShardTransactionMessages";
+
+message CloseTransaction{
+}
+
+message CloseTransactionReply{
+
+}
+
+message CreateTransaction{
+
+}
+
+message CreateTransactionReply{
+required string transactionPath = 1;
+
+}
+
+message ReadyTransaction{
+
+}
+
+message ReadyTransactionReply{
+required string actorPath = 1;
+}
+
+message DeleteData {
+required string instanceIdentifierPath = 1;
+}
+
+message DeleteDataReply{
+
+}
+message ReadData {
+required string intanceIdentifier=1;
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransactionChain.proto b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransactionChain.proto
new file mode 100644 (file)
index 0000000..73a9aa1
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.controller.mdsal;
+
+option java_package = "org.opendaylight.controller.cluster.datastore.transaction";
+option java_outer_classname = "ShardTransactionChainMessages";
+
+message CloseTransactionChain {
+
+}
+
+message CloseTransactionChainReply{
+
+
+}
+
+message CreateTransactionChain {
+
+}
+
+message CreateTransactionChainReply{
+required string transactionChainPath = 1;
+
+}
+
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/messages/ShardManagerMessagesTest.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/messages/ShardManagerMessagesTest.java
new file mode 100644 (file)
index 0000000..f57cfc9
--- /dev/null
@@ -0,0 +1,43 @@
+package org.opendaylight.controller.cluster.datastore.messages;
+
+/**
+ * This test case is present to ensure that if others have
+ * used proper version of protocol buffer.
+ *
+ * If a different version of protocol buffer is used then it would
+ * generate different java sources and would result in
+ * breaking of this test case.
+ *
+ * @author: syedbahm
+ * Date: 6/20/14
+ *
+ */
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.shard.ShardManagerMessages;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+public class ShardManagerMessagesTest {
+
+  @Test
+  public void verifySerialization()throws Exception{
+   ShardManagerMessages.FindPrimary.Builder builder = ShardManagerMessages.FindPrimary.newBuilder();
+   builder.setShardName("Inventory");
+   File testFile = new File("./test");
+   FileOutputStream output = new FileOutputStream(testFile);
+   builder.build().writeTo(output);
+   output.close();
+
+   //Here we will read the same and check we got back what we had saved
+    ShardManagerMessages.FindPrimary findPrimary
+             =  ShardManagerMessages.FindPrimary.parseFrom(new FileInputStream(testFile));
+    Assert.assertEquals("Inventory", findPrimary.getShardName());
+
+    testFile.delete();
+
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModule.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModule.java
deleted file mode 100644 (file)
index e3ac9ba..0000000
+++ /dev/null
@@ -1,69 +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.config.yang.md.sal.remote.rpc;
-
-import org.opendaylight.controller.sal.connector.remoterpc.ClientImpl;
-import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcProvider;
-import org.opendaylight.controller.sal.connector.remoterpc.RoutingTableProvider;
-import org.opendaylight.controller.sal.connector.remoterpc.ServerImpl;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.osgi.framework.BundleContext;
-
-/**
- *
- */
-public final class ZeroMQServerModule
-extends org.opendaylight.controller.config.yang.md.sal.remote.rpc.AbstractZeroMQServerModule {
-
-    private static final Integer ZEROMQ_ROUTER_PORT = 5554;
-    private BundleContext bundleContext;
-
-    public ZeroMQServerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-        super(identifier, dependencyResolver);
-    }
-
-    public ZeroMQServerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
-            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
-            final ZeroMQServerModule oldModule, final java.lang.AutoCloseable oldInstance) {
-
-        super(identifier, dependencyResolver, oldModule, oldInstance);
-    }
-
-    @Override
-    protected void customValidation() {
-        // Add custom validation for module attributes here.
-    }
-
-    @Override
-    public java.lang.AutoCloseable createInstance() {
-
-        Broker broker = getDomBrokerDependency();
-
-        final int port = getPort() != null ? getPort() : ZEROMQ_ROUTER_PORT;
-
-        ServerImpl serverImpl = new ServerImpl(port);
-
-        ClientImpl clientImpl = new ClientImpl();
-
-        RoutingTableProvider provider = new RoutingTableProvider(bundleContext);//,serverImpl);
-
-        RemoteRpcProvider facade = new RemoteRpcProvider(serverImpl, clientImpl);
-        facade.setRoutingTableProvider(provider);
-        facade.setContext(bundleContext);
-        facade.setRpcProvisionRegistry((RpcProvisionRegistry) broker);
-
-        broker.registerProvider(facade, bundleContext);
-        return facade;
-    }
-
-    public void setBundleContext(final BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModuleFactory.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModuleFactory.java
deleted file mode 100644 (file)
index 0c2a370..0000000
+++ /dev/null
@@ -1,35 +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.config.yang.md.sal.remote.rpc;
-
-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 ZeroMQServerModuleFactory extends org.opendaylight.controller.config.yang.md.sal.remote.rpc.AbstractZeroMQServerModuleFactory
-{
-
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
-        ZeroMQServerModule module = (ZeroMQServerModule) super.createModule(instanceName, dependencyResolver, bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-
-    @Override
-    public Module createModule(String instanceName, DependencyResolver dependencyResolver,
-            DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
-        ZeroMQServerModule module = (ZeroMQServerModule) super.createModule(instanceName, dependencyResolver, old,bundleContext);
-        module.setBundleContext(bundleContext);
-        return module;
-    }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/CapturedMessageHandler.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/CapturedMessageHandler.java
deleted file mode 100644 (file)
index 2dc5eee..0000000
+++ /dev/null
@@ -1,37 +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.connector.remoterpc;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
-public class CapturedMessageHandler implements Runnable {
-
-  private Logger _logger = LoggerFactory.getLogger(CapturedMessageHandler.class);
-
-  private ZMQ.Socket socket;
-
-  public CapturedMessageHandler(ZMQ.Socket socket){
-    this.socket = socket;
-  }
-
-  @Override
-  public void run(){
-
-    try {
-      while (!Thread.currentThread().isInterrupted()){
-        String message = socket.recvStr();
-        _logger.debug("Captured [{}]", message);
-      }
-    } catch (Exception e) {
-      _logger.error("Exception raised [{}]", e.getMessage());
-    }
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImpl.java
deleted file mode 100644 (file)
index 200ebae..0000000
+++ /dev/null
@@ -1,254 +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.connector.remoterpc;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-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.Message;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
-import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
-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;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * An implementation of {@link org.opendaylight.controller.sal.core.api.RpcImplementation} that makes
- * remote RPC calls
- */
-public class ClientImpl implements RemoteRpcClient {
-
-  private final Logger _logger = LoggerFactory.getLogger(ClientImpl.class);
-
-  private final ZMQ.Context context = ZMQ.context(1);
-  private final ClientRequestHandler handler;
-  private RoutingTableProvider routingTableProvider;
-
-  public ClientImpl(){
-    handler = new ClientRequestHandler(context);
-    start();
-  }
-
-  public ClientImpl(ClientRequestHandler handler){
-    this.handler = handler;
-    start();
-  }
-
-  public RoutingTableProvider getRoutingTableProvider() {
-    return routingTableProvider;
-  }
-
-  @Override
-  public void setRoutingTableProvider(RoutingTableProvider routingTableProvider) {
-    this.routingTableProvider = routingTableProvider;
-  }
-
-  @Override
-  public void start() {/*NOOPS*/}
-
-  @Override
-  public void stop() {
-    closeZmqContext();
-    handler.close();
-    _logger.info("Stopped");
-  }
-
-  @Override
-  public void close(){
-    stop();
-  }
-
-  /**
-   * Finds remote server that can execute this rpc and sends a message to it
-   * requesting execution.
-   * The call blocks until a response from remote server is received. Its upto
-   * the client of this API to implement a timeout functionality.
-   *
-   * @param rpc   remote service to be executed
-   * @param input payload for the remote service
-   * @return
-   */
-  public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-    routeId.setType(rpc);
-
-    String address = lookupRemoteAddressForGlobalRpc(routeId);
-    return sendMessage(input, routeId, address);
-  }
-
-  /**
-   * Finds remote server that can execute this routed rpc and sends a message to it
-   * requesting execution.
-   * The call blocks until a response from remote server is received. Its upto
-   * the client of this API to implement a timeout functionality.
-   *
-   * @param rpc
-   *          rpc to be called
-   * @param identifier
-   *          instance identifier on which rpc is to be executed
-   * @param input
-   *          payload
-   * @return
-   */
-  public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
-
-    RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-    routeId.setType(rpc);
-    routeId.setRoute(identifier);
-
-    String address = lookupRemoteAddressForRpc(routeId);
-
-    return sendMessage(input, routeId, address);
-  }
-
-  private ListenableFuture<RpcResult<CompositeNode>> sendMessage(CompositeNode input, RouteIdentifierImpl routeId, String address) {
-    Message request = new Message.MessageBuilder()
-        .type(Message.MessageType.REQUEST)
-        .sender(Context.getInstance().getLocalUri())
-        .recipient(address)
-        .route(routeId)
-        .payload(XmlUtils.compositeNodeToXml(input))
-        .build();
-
-    List<RpcError> errors = new ArrayList<RpcError>();
-
-    try{
-      Message response = handler.handle(request);
-      CompositeNode payload = null;
-
-      if ( response != null ) {
-
-        _logger.info("Received response [{}]", response);
-
-        Object rawPayload = response.getPayload();
-        switch (response.getType()) {
-          case ERROR:
-            if ( rawPayload instanceof List )
-              errors = (List) rawPayload;
-              break;
-
-          case RESPONSE:
-            payload = XmlUtils.xmlToCompositeNode((String) rawPayload);
-            break;
-
-          default:
-            errors.add(
-                RpcErrors.getRpcError(null, null,null,null,"Unable to get response from remote controller", null, null)
-            );
-            break;
-
-        }
-      }
-      return Futures.immediateFuture(Rpcs.getRpcResult(true, payload, errors));
-
-    } catch (Exception e){
-      collectErrors(e, errors);
-      return Futures.immediateFuture(Rpcs.<CompositeNode>getRpcResult(false, null, errors));
-    }
-  }
-
-  /**
-   * Find address for the given route identifier in routing table
-   * @param  routeId route identifier
-   * @return         remote network address
-   */
-  private String lookupRemoteAddressForGlobalRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
-    checkNotNull(routeId, "route must not be null");
-
-    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
-    checkNotNull(routingTable.isPresent(), "Routing table is null");
-
-    String address = null;
-    try {
-      address = routingTable.get().getGlobalRoute(routeId);
-    } catch (RoutingTableException|SystemException e) {
-      _logger.error("Exception caught while looking up remote address " + e);
-    }
-    checkState(address != null, "Address not found for route [%s]", routeId);
-
-    return address;
-  }
-
-  /**
-   * Find address for the given route identifier in routing table
-   * @param  routeId route identifier
-   * @return         remote network address
-   */
-  private String lookupRemoteAddressForRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
-    checkNotNull(routeId, "route must not be null");
-
-    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
-    checkNotNull(routingTable.isPresent(), "Routing table is null");
-
-    String address = routingTable.get().getLastAddedRoute(routeId);
-    checkState(address != null, "Address not found for route [%s]", routeId);
-
-    return address;
-  }
-
-  private void collectErrors(Exception e, List<RpcError> errors){
-    if (e == null) return;
-    if (errors == null) errors = new ArrayList<RpcError>();
-
-    errors.add(RpcErrors.getRpcError(null, null, null, null, e.getMessage(), null, e.getCause()));
-    for (Throwable t : e.getSuppressed()) {
-      errors.add(RpcErrors.getRpcError(null, null, null, null, t.getMessage(), null, t));
-    }
-  }
-
-  /**
-   * Closes ZMQ Context. It tries to gracefully terminate the context. If
-   * termination takes more than a second, its forcefully shutdown.
-   */
-  private void closeZmqContext() {
-    ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
-
-      @Override
-      public void run() {
-        try {
-          if (context != null)
-            context.term();
-          _logger.debug("ZMQ Context terminated");
-        } catch (Exception e) {
-          _logger.debug("ZMQ Context termination threw exception [{}]. Continuing shutdown...", e);
-        }
-      }
-    }, null);
-
-    exec.execute(zmqTermination);
-
-    try {
-      zmqTermination.get(1L, TimeUnit.SECONDS);
-    } catch (Exception e) {/*ignore and continue with shutdown*/}
-
-    exec.shutdownNow();
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandler.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandler.java
deleted file mode 100644 (file)
index fe70fb7..0000000
+++ /dev/null
@@ -1,194 +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.connector.remoterpc;
-
-import com.google.common.base.Preconditions;
-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.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- */
-class ClientRequestHandler implements AutoCloseable{
-
-  private Logger _logger = LoggerFactory.getLogger(ClientRequestHandler.class);
-  private final String DEFAULT_NAME = "remoterpc-client-worker";
-  private final String INPROC_PROTOCOL_PREFIX = "inproc://";
-  private final String TCP_PROTOCOL_PREFIX = "tcp://";
-
-  private ZMQ.Context context;
-
-  /*
-   * Worker thread pool. Each thread runs a ROUTER-DEALER pair
-   */
-  private ExecutorService workerPool;
-
-  /*
-   * Set of remote servers this client is currently connected to
-   */
-  private Map<String, String> connectedServers;
-
-  protected ClientRequestHandler(ZMQ.Context context) {
-    this.context = context;
-    connectedServers = new ConcurrentHashMap<String, String>();
-    start();
-  }
-
-  /**
-   * Starts a pool of worker as needed. A worker thread that has not been used for 5 min
-   * is terminated and removed from the pool. If thread dies due to an exception, its
-   * restarted.
-   */
-  private void start(){
-
-    workerPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
-        5L, TimeUnit.MINUTES,
-        new SynchronousQueue<Runnable>()){
-
-      @Override
-      protected void afterExecute(Runnable r, Throwable t) {
-        if (isTerminating() || isTerminated() || isShutdown())
-          return;
-
-        Worker worker = (Worker) r;
-        Preconditions.checkState( worker != null );
-        String remoteServerAddress = worker.getRemoteServerAddress();
-        connectedServers.remove(remoteServerAddress);
-
-        if ( t != null ){
-          _logger.debug("Exception caught while terminating worker [{},{}]. " +
-              "Restarting worker...", t.getClass(), t.getMessage());
-
-          connectedServers.put(remoteServerAddress, remoteServerAddress);
-          this.execute(r);
-        }
-        super.afterExecute(r, null);
-      }
-    };
-  }
-
-  public Message handle(Message request) throws IOException, ClassNotFoundException, InterruptedException {
-
-    String remoteServerAddress = request.getRecipient();
-    //if we already have router-dealer bridge setup for this address the send request
-    //otherwise first create the bridge and then send request
-    if ( connectedServers.containsKey(remoteServerAddress) )
-      return sendMessage(request, remoteServerAddress);
-
-    else{
-      workerPool.execute(new Worker(remoteServerAddress));
-      connectedServers.put(remoteServerAddress, remoteServerAddress);
-      //give little time for sockets to get initialized
-      //TODO: Add socket ping-pong message to ensure socket init rather than thread.sleep.
-      Thread.sleep(1000);
-      return sendMessage(request, remoteServerAddress);
-    }
-  }
-
-  private Message sendMessage(Message request, String address) throws IOException, ClassNotFoundException {
-    Message response = null;
-    ZMQ.Socket socket = context.socket(ZMQ.REQ);
-
-    try {
-      String inProcessSocketAddress = INPROC_PROTOCOL_PREFIX + address;
-      socket.connect( inProcessSocketAddress );
-      _logger.debug("Sending request [{}]", request);
-      socket.send(Message.serialize(request));
-      _logger.info("Request sent. Waiting for reply...");
-      byte[] reply = socket.recv(0);
-      _logger.info("Response received");
-      response = (Message) Message.deserialize(reply);
-      _logger.debug("Response [{}]", response);
-    } finally {
-      socket.close();
-    }
-    return response;
-  }
-
-  /**
-   * This gets called automatically if used with try-with-resources
-   */
-  @Override
-  public void close(){
-    workerPool.shutdown();
-    _logger.info("Request Handler closed");
-  }
-
-  /**
-   * Total number of workers in the pool. Number of workers represent
-   * number of remote servers {@link org.opendaylight.controller.sal.connector.remoterpc.ClientImpl} is connected to.
-   *
-   * @return worker count
-   */
-  public int getWorkerCount(){
-
-    if (workerPool == null) return 0;
-
-    return ((ThreadPoolExecutor)workerPool).getActiveCount();
-  }
-  /**
-   * Handles RPC request
-   */
-  private class Worker implements Runnable {
-    private String name;
-    private String remoteServer;  //<serverip:rpc-port>
-
-    public Worker(String address){
-      this.name = DEFAULT_NAME + "[" + address + "]";
-      this.remoteServer = address;
-    }
-
-    public String getRemoteServerAddress(){
-      return this.remoteServer;
-    }
-
-    @Override
-    public void run() {
-      Thread.currentThread().setName(name);
-      _logger.debug("Starting ... ");
-
-      ZMQ.Socket router = context.socket(ZMQ.ROUTER);
-      ZMQ.Socket dealer = context.socket(ZMQ.DEALER);
-
-      try {
-        int success = router.bind(INPROC_PROTOCOL_PREFIX + remoteServer);
-        Preconditions.checkState(-1 != success, "Could not bind to " + remoteServer);
-
-        dealer.connect(TCP_PROTOCOL_PREFIX + remoteServer);
-
-        _logger.info("Worker started for [{}]", remoteServer);
-
-        //TODO: Add capture handler
-        //This code will block until the zmq context is terminated.
-        ZMQ.proxy(router, dealer, null);
-
-      } catch (Exception e) {
-        _logger.debug("Ignoring exception [{}, {}]", e.getClass(), e.getMessage());
-      } finally {
-        try {
-          router.close();
-          dealer.close();
-        } catch (Exception x) {
-          _logger.debug("Exception while closing socket [{}]", x);
-        }
-        _logger.debug("Closing...");
-      }
-    }
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java
deleted file mode 100644 (file)
index 37bff7b..0000000
+++ /dev/null
@@ -1,92 +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.connector.remoterpc;
-
-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 final ZMQ.Context zmqContext = ZMQ.context(1);
-  private String uri;
-  private final String DEFAULT_RPC_PORT = "5554";
-
-  private static Context _instance = new Context();
-
-  private Context() {}
-
-  public static Context getInstance(){
-    return _instance;
-  }
-
-  public ZMQ.Context getZmqContext(){
-    return this.zmqContext;
-  }
-
-  public String getLocalUri(){
-    uri = (uri != null) ? uri
-            : new StringBuilder().append(getIpAddress()).append(":")
-              .append(getRpcPort()).toString();
-
-    return uri;
-  }
-
-  public String getRpcPort(){
-    String rpcPort = (System.getProperty("rpc.port") != null)
-        ? System.getProperty("rpc.port")
-        : DEFAULT_RPC_PORT;
-
-    return rpcPort;
-  }
-
-  private String getIpAddress(){
-    String ipAddress = (System.getProperty("local.ip") != null)
-        ? System.getProperty("local.ip")
-        : findIpAddress();
-
-    return ipAddress;
-  }
-
-  /**
-   * Finds IPv4 address of the local VM
-   * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
-   * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
-   * Should we use IP or hostname?
-   *
-   * @return
-   */
-  private String findIpAddress() {
-    String hostAddress = null;
-    Enumeration<?> e = null;
-    try {
-      e = NetworkInterface.getNetworkInterfaces();
-    } catch (SocketException e1) {
-      e1.printStackTrace();
-    }
-    while (e.hasMoreElements()) {
-
-      NetworkInterface n = (NetworkInterface) e.nextElement();
-
-      Enumeration<?> ee = n.getInetAddresses();
-      while (ee.hasMoreElements()) {
-        InetAddress i = (InetAddress) ee.nextElement();
-        if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
-          hostAddress = i.getHostAddress();
-      }
-    }
-    return hostAddress;
-
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java
deleted file mode 100644 (file)
index 94e3232..0000000
+++ /dev/null
@@ -1,18 +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.connector.remoterpc;
-
-public interface RemoteRpcClient extends AutoCloseable{
-
-    void setRoutingTableProvider(RoutingTableProvider provider);
-
-    void stop();
-
-    void start();
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java
deleted file mode 100644 (file)
index 76df256..0000000
+++ /dev/null
@@ -1,295 +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.connector.remoterpc;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-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.Provider;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.osgi.framework.BundleContext;
-import org.osgi.util.tracker.ServiceTracker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-
-public class RemoteRpcProvider implements
-    RpcImplementation,
-    RoutedRpcDefaultImplementation,
-    AutoCloseable,
-    Provider {
-
-  private final Logger _logger = LoggerFactory.getLogger(RemoteRpcProvider.class);
-
-  private final ServerImpl server;
-  private final ClientImpl client;
-  private RoutingTableProvider routingTableProvider;
-  private final RpcListener listener = new RpcListener();
-  private final RoutedRpcListener routeChangeListener = new RoutedRpcListener();
-  private ProviderSession brokerSession;
-  private RpcProvisionRegistry rpcProvisionRegistry;
-  private BundleContext context;
-  private ServiceTracker<?, ?> clusterTracker;
-
-  public RemoteRpcProvider(ServerImpl server, ClientImpl client) {
-    this.server = server;
-    this.client = client;
-  }
-
-  public void setRoutingTableProvider(RoutingTableProvider provider) {
-    this.routingTableProvider = provider;
-    client.setRoutingTableProvider(provider);
-  }
-
-  public void setContext(BundleContext context){
-    this.context = context;
-  }
-
-  public void setRpcProvisionRegistry(RpcProvisionRegistry rpcProvisionRegistry){
-    this.rpcProvisionRegistry = rpcProvisionRegistry;
-  }
-
-  @Override
-  public void onSessionInitiated(ProviderSession session) {
-    brokerSession = session;
-    server.setBrokerSession(session);
-    start();
-  }
-
-  @Override
-  public Set<QName> getSupportedRpcs() {
-    //TODO: Ask Tony if we need to get this from routing table
-    return Collections.emptySet();
-  }
-
-  @Override
-  public Collection<ProviderFunctionality> getProviderFunctionality() {
-    // TODO Auto-generated method stub
-    return null;
-  }
-
-  @Override
-  public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
-    return client.invokeRpc(rpc, input);
-  }
-
-  @Override
-  public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
-    return client.invokeRpc(rpc, identifier, input);
-  }
-
-  public void start() {
-    server.start();
-    client.start();
-    brokerSession.addRpcRegistrationListener(listener);
-    rpcProvisionRegistry.setRoutedRpcDefaultDelegate(this);
-    rpcProvisionRegistry.registerRouteChangeListener(routeChangeListener);
-
-    announceSupportedRpcs();
-    announceSupportedRoutedRpcs();
-  }
-
-  @Override
-  public void close() throws Exception {
-    unregisterSupportedRpcs();
-    unregisterSupportedRoutedRpcs();
-    server.close();
-    client.close();
-  }
-
-  public void stop() {
-    server.stop();
-    client.stop();
-  }
-
-  /**
-   * Add all the locally registered RPCs in the clustered routing table
-   */
-  private void announceSupportedRpcs(){
-    Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
-    for (QName rpc : currentlySupported) {
-      listener.onRpcImplementationAdded(rpc);
-    }
-  }
-
-  /**
-   * Add all the locally registered Routed RPCs in the clustered routing table
-   */
-  private void announceSupportedRoutedRpcs(){
-
-    //TODO: announce all routed RPCs as well
-
-  }
-
-  /**
-   * Un-Register all the supported RPCs from clustered routing table
-   */
-  private void unregisterSupportedRpcs(){
-    Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
-    //TODO: remove all routed RPCs as well
-    for (QName rpc : currentlySupported) {
-      listener.onRpcImplementationRemoved(rpc);
-    }
-  }
-
-  /**
-   * Un-Register all the locally supported Routed RPCs from clustered routing table
-   */
-  private void unregisterSupportedRoutedRpcs(){
-
-    //TODO: remove all routed RPCs as well
-
-  }
-
-  private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> getRoutingTable(){
-    Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable =
-        routingTableProvider.getRoutingTable();
-
-    checkState(routingTable.isPresent(), "Routing table is null");
-
-    return routingTable.get();
-  }
-
-  /**
-   * Listener for rpc registrations in broker
-   */
-  private class RpcListener implements RpcRegistrationListener {
-
-    @Override
-    public void onRpcImplementationAdded(QName rpc) {
-
-      _logger.debug("Adding registration for [{}]", rpc);
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-      routeId.setType(rpc);
-
-      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
-
-      try {
-        routingTable.addGlobalRoute(routeId, server.getServerAddress());
-        _logger.debug("Route added [{}-{}]", routeId, server.getServerAddress());
-
-      } catch (RoutingTableException | SystemException e) {
-        //TODO: This can be thrown when route already exists in the table. Broker
-        //needs to handle this.
-        _logger.error("Unhandled exception while adding global route to routing table [{}]", e);
-
-      }
-    }
-
-    @Override
-    public void onRpcImplementationRemoved(QName rpc) {
-
-      _logger.debug("Removing registration for [{}]", rpc);
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-      routeId.setType(rpc);
-
-      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
-
-      try {
-        routingTable.removeGlobalRoute(routeId);
-      } catch (RoutingTableException | SystemException e) {
-        _logger.error("Route delete failed {}", e);
-      }
-    }
-  }
-
-  /**
-   * Listener for Routed Rpc registrations in broker
-   */
-  private class RoutedRpcListener
-      implements RouteChangeListener<RpcRoutingContext, InstanceIdentifier> {
-
-    /**
-     *
-     * @param routeChange
-     */
-    @Override
-    public void onRouteChange(RouteChange<RpcRoutingContext, InstanceIdentifier> routeChange) {
-      Map<RpcRoutingContext, Set<InstanceIdentifier>> announcements = routeChange.getAnnouncements();
-      announce(getRouteIdentifiers(announcements));
-
-      Map<RpcRoutingContext, Set<InstanceIdentifier>> removals = routeChange.getRemovals();
-      remove(getRouteIdentifiers(removals));
-    }
-
-    /**
-     *
-     * @param announcements
-     */
-    private void announce(Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements) {
-      _logger.debug("Announcing [{}]", announcements);
-      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
-      try {
-        routingTable.addRoutes(announcements, server.getServerAddress());
-      } catch (RoutingTableException | SystemException e) {
-        _logger.error("Route announcement failed {}", e);
-      }
-    }
-
-    /**
-     *
-     * @param removals
-     */
-    private void remove(Set<RpcRouter.RouteIdentifier<?, ?, ?>> removals){
-      _logger.debug("Removing [{}]", removals);
-      RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
-      try {
-        routingTable.removeRoutes(removals, server.getServerAddress());
-      } catch (RoutingTableException | SystemException e) {
-        _logger.error("Route removal failed {}", e);
-      }
-    }
-
-    /**
-     *
-     * @param changes
-     * @return
-     */
-    private Set<RpcRouter.RouteIdentifier<?, ?, ?>> getRouteIdentifiers(Map<RpcRoutingContext, Set<InstanceIdentifier>> changes) {
-      RouteIdentifierImpl routeId = null;
-      Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdSet = new HashSet<>();
-
-      for (RpcRoutingContext context : changes.keySet()){
-        routeId = new RouteIdentifierImpl();
-        routeId.setType(context.getRpc());
-        //routeId.setContext(context.getContext());
-
-        for (InstanceIdentifier instanceId : changes.get(context)){
-          routeId.setRoute(instanceId);
-          routeIdSet.add(routeId);
-        }
-      }
-      return routeIdSet;
-    }
-
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java
deleted file mode 100644 (file)
index d960303..0000000
+++ /dev/null
@@ -1,56 +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.connector.remoterpc;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-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;
-
-    //final private RouteChangeListener routeChangeListener;
-
-
-    public RoutingTableProvider(BundleContext ctx){//,RouteChangeListener rcl) {
-        @SuppressWarnings("rawtypes")
-        ServiceTracker<RoutingTable, RoutingTable> rawTracker = new ServiceTracker<>(ctx, RoutingTable.class, null);
-        tracker = rawTracker;
-        tracker.open();
-
-        //routeChangeListener = rcl;
-    }
-
-    public Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> getRoutingTable() {
-        @SuppressWarnings("unchecked")
-        RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> tracked = tracker.getService();
-
-        if(tracked instanceof RoutingTableImpl){
-            if(routingTableImpl != tracked){
-             routingTableImpl= (RoutingTableImpl<?, ?>)tracked;
-             //routingTableImpl.setRouteChangeListener(routeChangeListener);
-            }
-        }
-
-        return Optional.fromNullable(tracked);
-    }
-
-    @Override
-    public void close() throws Exception {
-        tracker.close();
-    }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java
deleted file mode 100644 (file)
index 3acea35..0000000
+++ /dev/null
@@ -1,264 +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.connector.remoterpc;
-
-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.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-
-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 final Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
-
-  private ExecutorService serverPool;
-  protected ServerRequestHandler handler;
-
-  private Set<QName> remoteServices;
-  private ProviderSession brokerSession;
-  private ZMQ.Context context;
-
-  private final String HANDLER_INPROC_ADDRESS = "inproc://rpc-request-handler";
-  private final int HANDLER_WORKER_COUNT = 2;
-  private final int HWM = 200;//high water mark on sockets
-  private volatile State status = State.STOPPED;
-
-  private String serverAddress;
-  private final int port;
-
-  public static enum State {
-    STARTING, STARTED, STOPPED;
-  }
-
-  public ServerImpl(int port) {
-    this.port = port;
-  }
-
-  public State getStatus() {
-    return this.status;
-  }
-
-  public Optional<ServerRequestHandler> getHandler() {
-    return Optional.fromNullable(this.handler);
-  }
-
-  public void setBrokerSession(ProviderSession session) {
-    this.brokerSession = session;
-  }
-
-  public Optional<ProviderSession> getBrokerSession() {
-    return Optional.fromNullable(this.brokerSession);
-  }
-
-  public Optional<ZMQ.Context> getZmqContext() {
-    return Optional.fromNullable(this.context);
-  }
-
-  public String getServerAddress() {
-    return serverAddress;
-  }
-
-  public String getHandlerAddress() {
-    return HANDLER_INPROC_ADDRESS;
-  }
-
-  /**
-   *
-   */
-  public void start() {
-    Preconditions.checkState(State.STOPPED == this.getStatus(),
-        "Remote RPC Server is already running");
-
-    status = State.STARTING;
-    _logger.debug("Remote RPC Server is starting...");
-
-    String hostIpAddress = findIpAddress();
-
-    //Log and silently die as per discussion in the bug (bug-362)
-    //https://bugs.opendaylight.org/show_bug.cgi?id=362
-    //
-    // A tracking enhancement defect (bug-366) is created to properly fix this issue
-    //https://bugs.opendaylight.org/show_bug.cgi?id=366
-    //checkState(hostIpAddress != null, "Remote RPC Server could not acquire host ip address");
-
-    if (hostIpAddress == null) {
-      _logger.error("Remote RPC Server could not acquire host ip address. Stopping...");
-      stop();
-      return;
-    }
-
-    this.serverAddress = new StringBuilder(hostIpAddress).
-        append(":").
-        append(port).
-        toString();
-
-    context = ZMQ.context(1);
-    remoteServices = new HashSet<QName>();//
-    serverPool = Executors.newSingleThreadExecutor();//main server thread
-    serverPool.execute(receive()); // Start listening rpc requests
-
-    status = State.STARTED;
-    _logger.info("Remote RPC Server started [{}]", getServerAddress());
-  }
-
-  public void stop(){
-    close();
-  }
-
-  /**
-   *
-   */
-  @Override
-  public void close() {
-
-    if (State.STOPPED == this.getStatus()) return; //do nothing
-
-    if (serverPool != null)
-      serverPool.shutdown();
-
-    closeZmqContext();
-
-    status = State.STOPPED;
-    _logger.info("Remote RPC Server stopped");
-  }
-
-  /**
-   * Closes ZMQ Context. It tries to gracefully terminate the context. If
-   * termination takes more than 5 seconds, its forcefully shutdown.
-   */
-  private void closeZmqContext() {
-    ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
-
-      @Override
-      public void run() {
-        try {
-          if (context != null)
-            context.term();
-          _logger.debug("ZMQ Context terminated gracefully!");
-        } catch (Exception e) {
-          _logger.debug("ZMQ Context termination threw exception [{}]. Continuing shutdown...", e);
-        }
-      }
-    }, null);
-
-    exec.execute(zmqTermination);
-
-    try {
-      zmqTermination.get(5L, TimeUnit.SECONDS);
-    } catch (Exception e) {/*ignore and continue with shutdown*/}
-
-    exec.shutdownNow();
-  }
-
-  /**
-   * Main listener thread that spawns {@link ServerRequestHandler} as workers.
-   *
-   * @return
-   */
-  private Runnable receive() {
-    return new Runnable() {
-
-      @Override
-      public void run() {
-        Thread.currentThread().setName("remote-rpc-server");
-        _logger.debug("Remote RPC Server main thread starting...");
-
-        //socket clients connect to (frontend)
-        ZMQ.Socket clients = context.socket(ZMQ.ROUTER);
-
-        //socket RequestHandlers connect to (backend)
-        ZMQ.Socket workers = context.socket(ZMQ.DEALER);
-
-        try (SocketPair capturePair = new SocketPair();
-             ServerRequestHandler requestHandler = new ServerRequestHandler(context,
-                 brokerSession,
-                 HANDLER_WORKER_COUNT,
-                 HANDLER_INPROC_ADDRESS,
-                 getServerAddress());) {
-
-          handler = requestHandler;
-          clients.setHWM(HWM);
-          clients.bind("tcp://*:" + port);
-          workers.setHWM(HWM);
-          workers.bind(HANDLER_INPROC_ADDRESS);
-          //start worker threads
-          _logger.debug("Remote RPC Server worker threads starting...");
-          requestHandler.start();
-          //start capture thread
-          // handlerPool.execute(new CaptureHandler(capturePair.getReceiver()));
-          //  Connect work threads to client threads via a queue
-          ZMQ.proxy(clients, workers, null);//capturePair.getSender());
-
-        } catch (Exception e) {
-          _logger.debug("Unhandled exception [{}, {}]", e.getClass(), e.getMessage());
-        } finally {
-          if (clients != null) clients.close();
-          if (workers != null) workers.close();
-          _logger.info("Remote RPC Server stopped");
-        }
-      }
-    };
-  }
-
-  /**
-   * Finds IPv4 address of the local VM
-   * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
-   * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
-   * Should we use IP or hostname?
-   *
-   * @return
-   */
-  private String findIpAddress() {
-    Enumeration<?> e = null;
-    try {
-      e = NetworkInterface.getNetworkInterfaces();
-    } catch (SocketException e1) {
-      _logger.error("Failed to get list of interfaces", e1);
-      return null;
-    }
-    while (e.hasMoreElements()) {
-
-      NetworkInterface n = (NetworkInterface) e.nextElement();
-
-      Enumeration<?> ee = n.getInetAddresses();
-      while (ee.hasMoreElements()) {
-        InetAddress i = (InetAddress) ee.nextElement();
-        _logger.debug("Trying address {}", i);
-        if ((i instanceof Inet4Address) && (!i.isLoopbackAddress())) {
-          String hostAddress = i.getHostAddress();
-          _logger.debug("Settled on host address {}", hostAddress);
-          return hostAddress;
-        }
-      }
-    }
-
-    _logger.error("Failed to find a suitable host address");
-    return null;
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandler.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandler.java
deleted file mode 100644 (file)
index a25387d..0000000
+++ /dev/null
@@ -1,292 +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.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.util.XmlUtils;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.yangtools.yang.common.QName;
-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;
-
-/**
- *
- */
-public class ServerRequestHandler implements AutoCloseable{
-
-  private final Logger _logger = LoggerFactory.getLogger(ServerRequestHandler.class);
-  private final String DEFAULT_NAME = "remote-rpc-worker";
-  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();
-
-  public ServerRequestHandler(ZMQ.Context context,
-                              Broker.ProviderSession session,
-                              int workerCount,
-                              String dealerAddress,
-                              String serverAddress) {
-    this.context       = context;
-    this.dealerAddress = dealerAddress;
-    this.serverAddress = serverAddress;
-    this.broker        = session;
-    this.workerCount   = workerCount;
-  }
-
-  public ThreadPoolExecutor getWorkerPool(){
-    return workerPool;
-  }
-
-  public void start(){
-    workerPool = new RequestHandlerThreadPool(
-        workerCount, workerCount,
-        0L, TimeUnit.MILLISECONDS,
-        new LinkedBlockingQueue<Runnable>());
-    //unbound is ok. Task will never be submitted
-
-    for (int i=0;i<workerCount;i++){
-      workerPool.execute(new Worker(threadId.incrementAndGet()));
-    }
-  }
-
-  /**
-   * This gets called automatically if used with try-with-resources
-   * @throws Exception
-   */
-  @Override
-  public void close() throws Exception {
-    if (workerPool != null)
-      workerPool.shutdown();
-    _logger.info("Request Handler closed");
-  }
-
-  /**
-   * Worker to handles RPC request
-   */
-  private class Worker implements Runnable {
-    private final String name;
-
-    public Worker(int id){
-      this.name = DEFAULT_NAME + "-" + id;
-    }
-
-    @Override
-    public void run() {
-      Thread.currentThread().setName(name);
-      _logger.debug("Starting... ");
-      ZMQ.Socket socket = null;
-
-      try {
-        socket = context.socket(ZMQ.REP);
-        socket.connect(dealerAddress);
-
-        while (!Thread.currentThread().isInterrupted()) {
-
-          MessageHandler handler = new MessageHandler(socket);
-          handler.receiveMessage();
-
-          if (handler.hasMessageForBroker()) {
-
-            Message request = handler.getMessage();
-            Future<RpcResult<CompositeNode>> rpc = null;
-            RpcResult<CompositeNode> result = null;
-
-            //TODO Call this in a new thread with timeout
-            try {
-              rpc = broker.rpc(
-                  (QName) request.getRoute().getType(),
-                  XmlUtils.xmlToCompositeNode((String) request.getPayload()));
-
-              result = (rpc != null) ? rpc.get() : null;
-
-              handler.sendResponse(result);
-
-            } catch (Exception e) {
-              _logger.debug("Broker threw  [{}]", e);
-              handler.sendError(e.getMessage());
-            }
-          }
-
-        }
-      } catch (Exception e) {
-        printException(e);
-      } finally {
-        closeSocket(socket);
-      }
-    }
-
-    private void printException(Exception e) {
-      try (StringWriter s = new StringWriter();
-           PrintWriter p = new PrintWriter(s)) {
-        e.printStackTrace(p);
-        _logger.debug(s.toString());
-      } catch (IOException e1) {/*Ignore and continue*/ }
-    }
-
-    private void closeSocket(ZMQ.Socket socket) {
-      try {
-        if (socket != null) socket.close();
-      } catch (Exception x) {
-        _logger.debug("Exception while closing socket [{}]", x);
-      } finally {
-        if (socket != null) socket.close();
-      }
-      _logger.debug("Closing...");
-    }
-  }
-
-
-  /**
-   *
-   */
-  public class RequestHandlerThreadPool extends ThreadPoolExecutor{
-
-    public RequestHandlerThreadPool(int corePoolSize,
-                                    int maximumPoolSize,
-                                    long keepAliveTime,
-                                    TimeUnit unit,
-                                    BlockingQueue<Runnable> workQueue) {
-      super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
-    }
-
-    @Override
-    protected void afterExecute(Runnable r, Throwable t) {
-      if (isTerminating() || isTerminated() || isShutdown())
-        return;
-
-      if ( t != null ){
-        _logger.debug("Exception caught while terminating worker [{},{}]", t.getClass(), t.getMessage());
-      }
-
-      this.execute(new Worker(threadId.incrementAndGet()));
-      super.afterExecute(r, null);
-    }
-  }
-
-  class MessageHandler{
-    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
-
-    public MessageHandler(ZMQ.Socket socket){
-      this.socket = socket;
-    }
-
-    void receiveMessage(){
-      byte[] bytes = socket.recv(); //this blocks
-      _logger.debug("Received bytes:[{}]", bytes.length);
-
-      Object objectRecvd = null;
-      try{
-        objectRecvd = Message.deserialize(bytes);
-      }catch (Exception e){
-        sendError(e.getMessage());
-        return;
-      }
-
-      if (!(objectRecvd instanceof Message)) {
-        sendError("Invalid message received");
-        return;
-      }
-
-      message = (Message) objectRecvd;
-
-      _logger.info("Received request [{}]", message);
-
-      if (Message.MessageType.PING == message.getType()){
-        sendPong();
-        return;
-      }
-
-      messageForBroker = true;
-    }
-
-    boolean hasMessageForBroker(){
-      return messageForBroker;
-    }
-
-    Message getMessage(){
-      return message;
-    }
-
-    void sendResponse(RpcResult<CompositeNode> result){
-      CompositeNode payload = (result != null) ? result.getResult() : null;
-
-      String recipient = null;
-      RpcRouter.RouteIdentifier<?, ?, ?> routeId = null;
-
-      if (message != null) {
-        recipient = message.getSender();
-        routeId   = message.getRoute();
-      }
-
-      Message response = new Message.MessageBuilder()
-          .type(Message.MessageType.RESPONSE)
-          .sender(serverAddress)
-          .recipient(recipient)
-          .route(routeId)
-          .payload(XmlUtils.compositeNodeToXml(payload))
-          .build();
-
-      send(response);
-    }
-
-    private void sendError(String msg){
-      Message errorResponse = new Message.MessageBuilder()
-          .type(Message.MessageType.ERROR)
-          .sender(serverAddress)
-          .payload(msg)
-          .build();
-
-      send(errorResponse);
-    }
-
-    private void sendPong(){
-      Message pong = new Message.MessageBuilder()
-          .type(Message.MessageType.PONG)
-          .sender(serverAddress)
-          .build();
-
-      send(pong);
-    }
-
-    private void send(Message msg){
-      byte[] serializedMessage = null;
-      try {
-        serializedMessage = Message.serialize(msg);
-      } catch (Exception e) {
-        _logger.debug("Unexpected error during serialization of response [{}]", msg);
-        return;
-      }
-
-      if (serializedMessage != null)
-        if (socket.send(serializedMessage))
-          _logger.info("Response sent [{}]", msg);
-        else  _logger.debug("Failed to send serialized message");
-    }
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketPair.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketPair.java
deleted file mode 100644 (file)
index f569944..0000000
+++ /dev/null
@@ -1,48 +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.connector.remoterpc;
-
-import org.zeromq.ZMQ;
-
-import java.util.UUID;
-
-/**
- *
- */
-public class SocketPair implements AutoCloseable{
-  private ZMQ.Socket sender;
-  private ZMQ.Socket receiver;
-
-  private static final String INPROC_PREFIX = "inproc://";
-
-  public SocketPair(){
-    String address = new StringBuilder(INPROC_PREFIX)
-                         .append(UUID.randomUUID())
-                         .toString();
-
-    receiver = Context.getInstance().getZmqContext().socket(ZMQ.PAIR);
-    receiver.bind(address);
-
-    sender = Context.getInstance().getZmqContext().socket(ZMQ.PAIR);
-    sender.connect(address);
-  }
-
-  public ZMQ.Socket getSender(){
-    return this.sender;
-  }
-
-  public ZMQ.Socket getReceiver(){
-    return this.receiver;
-  }
-
-  @Override
-  public void close() throws Exception {
-    sender.close();
-    receiver.close();
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java
deleted file mode 100644 (file)
index cbcfe3e..0000000
+++ /dev/null
@@ -1,191 +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.connector.remoterpc.dto;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-
-public class Message implements Serializable {
-    private static final long serialVersionUID = 1L;
-
- public static enum MessageType {
-    PING((byte) 0),
-    PONG((byte) 1),
-    REQUEST((byte) 2),
-    RESPONSE((byte) 3),
-    ERROR((byte)4);
-
-    private final byte type;
-
-    MessageType(byte type) {
-      this.type = type;
-    }
-
-    public byte getType(){
-      return this.type;
-    }
-  }
-
-  private MessageType type;
-  private String sender;
-  private String recipient;
-  private RpcRouter.RouteIdentifier<?, ?, ?> route;
-  private Object payload;
-
-  public MessageType getType() {
-    return type;
-  }
-
-  public void setType(MessageType type) {
-    this.type = type;
-  }
-
-  public String getSender() {
-    return sender;
-  }
-
-  public void setSender(String sender) {
-    this.sender = sender;
-  }
-
-  public RpcRouter.RouteIdentifier<?, ?, ?> getRoute() {
-    return route;
-  }
-
-  public void setRoute(RpcRouter.RouteIdentifier<?, ?, ?> route) {
-    this.route = route;
-  }
-
-  public Object getPayload() {
-    return payload;
-  }
-
-  public void setPayload(Object payload) {
-    this.payload = payload;
-  }
-
-  public String getRecipient() {
-    return recipient;
-  }
-
-  public void setRecipient(String recipient) {
-    this.recipient = recipient;
-  }
-
-  @Override
-  public String toString() {
-    return "Message{" +
-        "type=" + type +
-        ", sender='" + sender + '\'' +
-        ", recipient='" + recipient + '\'' +
-        ", route=" + route +
-        ", payload=" + payload +
-        '}';
-  }
-
-  /**
-   * Converts any {@link Serializable} object to byte[]
-   *
-   * @param obj
-   * @return
-   * @throws IOException
-   */
-  public static byte[] serialize(Object obj) throws IOException {
-    ByteArrayOutputStream b = new ByteArrayOutputStream();
-    ObjectOutputStream o = new ObjectOutputStream(b);
-    o.writeObject(obj);
-    return b.toByteArray();
-  }
-
-  /**
-   * Converts byte[] to a java object
-   *
-   * @param bytes
-   * @return
-   * @throws IOException
-   * @throws ClassNotFoundException
-   */
-  public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
-    ByteArrayInputStream b = new ByteArrayInputStream(bytes);
-    ObjectInputStream o = new ObjectInputStream(b);
-    return o.readObject();
-  }
-
-  public static class Response extends Message implements RpcRouter.RpcReply<Object> {
-    private static final long serialVersionUID = 1L;
-    private ResponseCode code; // response code
-
-    public static enum ResponseCode {
-      SUCCESS(200), BADREQUEST(400), TIMEOUT(408), GONE(410), SERVERERROR(500), SERVICEUNAVAILABLE(503);
-
-      private final int code;
-
-      ResponseCode(int code) {
-        this.code = code;
-      }
-    }
-
-    public ResponseCode getCode() {
-      return code;
-    }
-
-    public void setCode(ResponseCode code) {
-      this.code = code;
-    }
-  }
-
-  /**
-   * Builds a {@link Message} object
-   */
-  public static class MessageBuilder{
-
-    private final Message message;
-
-    public MessageBuilder(){
-      message = new Message();
-    }
-
-
-    public MessageBuilder type(MessageType type){
-      message.setType(type);
-      return this;
-    }
-
-    public MessageBuilder sender(String sender){
-      message.setSender(sender);
-      return this;
-    }
-
-    public MessageBuilder recipient(String recipient){
-      message.setRecipient(recipient);
-      return this;
-    }
-
-    public MessageBuilder route(RpcRouter.RouteIdentifier<?, ?, ?> route){
-      message.setRoute(route);
-      return this;
-    }
-
-    public MessageBuilder payload(Object obj){
-      message.setPayload(obj);
-      return this;
-    }
-
-    public Message build(){
-      return message;
-    }
-  }
-}
-
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/MessageWrapper.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/MessageWrapper.java
deleted file mode 100644 (file)
index 85f4113..0000000
+++ /dev/null
@@ -1,32 +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.connector.remoterpc.dto;
-
-import org.zeromq.ZMQ;
-
-/**
- * A class encapsulating {@link Message} and the {@link ZMQ.Socket} over which it is transmitted
- */
-public class MessageWrapper {
-
-  private Message _message;
-  private ZMQ.Socket _receiveSocket;
-
-  public MessageWrapper(Message message, ZMQ.Socket receiveSocket) {
-    this._message = message;
-    this._receiveSocket = receiveSocket;
-  }
-
-  public Message getMessage() {
-    return _message;
-  }
-
-  public ZMQ.Socket getReceiveSocket() {
-    return _receiveSocket;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java
deleted file mode 100644 (file)
index 53c7cc0..0000000
+++ /dev/null
@@ -1,93 +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.connector.remoterpc.dto;
-
-import java.io.Serializable;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>,Serializable {
-  private static final long serialVersionUID = 1L;
-
-  private QName context;
-  private QName type;
-  private InstanceIdentifier route;
-
-  @Override
-  public QName getContext() {
-    return this.context;
-  }
-
-  @Override
-  public QName getType() {
-    return this.type;
-  }
-
-  @Override
-  public InstanceIdentifier getRoute() {
-    return this.route;
-  }
-
-  public void setContext(QName context) {
-    this.context = context;
-  }
-
-  public void setType(QName type) {
-    this.type = type;
-  }
-
-  public void setRoute(InstanceIdentifier route) {
-    this.route = route;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
-
-    RouteIdentifierImpl that = (RouteIdentifierImpl) o;
-
-    if (context == null){
-      if (that.getContext() != null)  return false;
-    }else
-      if (!context.equals(that.context)) return false;
-
-    if (route == null){
-      if (that.getRoute() != null) return false;
-    }else
-      if (!route.equals(that.route)) return false;
-
-    if (type == null){
-      if (that.getType() != null) return false;
-    }else
-      if (!type.equals(that.type)) return false;
-
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int prime = 31;
-    int result = 0;
-    result = prime * result + (context == null ? 0:context.hashCode());
-    result = prime * result + (type    == null ? 0:type.hashCode());
-    result = prime * result + (route   == null ? 0:route.hashCode());
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "RouteIdentifierImpl{" +
-        "context=" + context +
-        ", type=" + type +
-        ", route=" + route +
-        '}';
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/util/XmlUtils.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/util/XmlUtils.java
deleted file mode 100644 (file)
index 3bc3963..0000000
+++ /dev/null
@@ -1,71 +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.connector.remoterpc.util;
-
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-
-import javax.xml.stream.XMLStreamException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.ByteArrayInputStream;
-import java.io.StringWriter;
-
-public class XmlUtils {
-
-  private static final Logger _logger = LoggerFactory.getLogger(XmlUtils.class);
-
-  public static String compositeNodeToXml(CompositeNode cNode){
-    if (cNode == null) return new String();
-
-    Document domTree = NodeUtils.buildShadowDomTree(cNode);
-    StringWriter writer = new StringWriter();
-    try {
-      TransformerFactory tf = TransformerFactory.newInstance();
-      Transformer transformer = tf.newTransformer();
-      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
-      transformer.transform(new DOMSource(domTree), new StreamResult(writer));
-    } catch (TransformerException e) {
-      _logger.error("Error during translation of Document to OutputStream", e);
-    }
-
-    return writer.toString();
-  }
-
-  public static CompositeNode xmlToCompositeNode(String xml){
-    if (xml==null || xml.length()==0) return null;
-
-    Node<?> dataTree;
-    try {
-      dataTree = XmlTreeBuilder.buildDataTree(new ByteArrayInputStream(xml.getBytes()));
-    } catch (XMLStreamException e) {
-      _logger.error("Error during building data tree from XML", e);
-      return null;
-    }
-    if (dataTree == null) {
-      _logger.error("data tree is null");
-      return null;
-    }
-    if (dataTree instanceof SimpleNode) {
-      _logger.error("RPC XML was resolved as SimpleNode");
-      return null;
-    }
-    return (CompositeNode) dataTree;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/yang/odl-sal-dom-rpc-remote-cfg.yang b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/yang/odl-sal-dom-rpc-remote-cfg.yang
deleted file mode 100644 (file)
index beeb936..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-module odl-sal-dom-rpc-remote-cfg {
-       yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc";
-    prefix "rpc-cluster";
-
-    import config { prefix config; revision-date 2013-04-05; }
-    import opendaylight-md-sal-dom {prefix dom;}
-    
-    description
-        "Service definition for Binding Aware MD-SAL.";
-    revision "2013-10-28" {
-        description
-            "Initial revision";
-    }
-
-    identity remote-rpc-server {
-        base config:service-type;
-        config:java-class "org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcServer";
-    }
-
-    identity remote-rpc-client {
-        base config:service-type;
-        config:java-class "org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcClient";
-    }
-
-    identity remote-zeromq-rpc-server {
-        base config:module-type;
-        config:java-name-prefix ZeroMQServer;
-    }
-
-    augment "/config:modules/config:module/config:configuration" {
-        case remote-zeromq-rpc-server {
-            when "/config:modules/config:module/config:type = 'remote-zeromq-rpc-server'";
-            
-            container dom-broker {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity dom:dom-broker-osgi-registry;
-                    }
-                }
-            }
-            
-            leaf port {
-                type uint16;
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImplTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImplTest.java
deleted file mode 100644 (file)
index f8d14ce..0000000
+++ /dev/null
@@ -1,107 +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.connector.remoterpc;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-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.dto.Message;
-import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.base.Optional;
-
-/**
- *
- */
-public class ClientImplTest {
-  RoutingTableProvider routingTableProvider;
-  ClientImpl client;
-  ClientRequestHandler mockHandler;
-
-  @Before
-  public void setUp() throws Exception {
-
-    //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);
-    when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
-
-    //mock ClientRequestHandler
-    mockHandler = mock(ClientRequestHandler.class);
-
-    client = new ClientImpl(mockHandler);
-    client.setRoutingTableProvider(routingTableProvider);
-
-  }
-
-  @After
-  public void tearDown() throws Exception {
-
-  }
-
-  @Test
-  public void getRoutingTableProvider_Call_ShouldReturnMockProvider() throws Exception {
-    Assert.assertEquals(routingTableProvider, client.getRoutingTableProvider());
-
-  }
-
-  @Test
-  public void testStart() throws Exception {
-
-  }
-
-  @Test
-  public void testStop() throws Exception {
-
-  }
-
-  @Test
-  public void testClose() throws Exception {
-
-  }
-
-  //@Test
-  public void invokeRpc_NormalCall_ShouldReturnSuccess() throws Exception {
-
-    when(mockHandler.handle(any(Message.class))).
-            thenReturn(MessagingUtil.createEmptyMessage());
-
-    RpcResult<CompositeNode> result = client.invokeRpc(null, null).get();
-
-    Assert.assertTrue(result.isSuccessful());
-    Assert.assertTrue(result.getErrors().isEmpty());
-    Assert.assertNull(result.getResult());
-  }
-
-  //@Test
-  public void invokeRpc_HandlerThrowsException_ShouldReturnError() throws Exception {
-
-    when(mockHandler.handle(any(Message.class))).
-            thenThrow(new IOException());
-
-    RpcResult<CompositeNode> result = client.invokeRpc(null, null).get();
-
-    Assert.assertFalse(result.isSuccessful());
-    Assert.assertFalse(result.getErrors().isEmpty());
-    Assert.assertNull(result.getResult());
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java
deleted file mode 100644 (file)
index 0918868..0000000
+++ /dev/null
@@ -1,124 +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.connector.remoterpc;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-
-import junit.framework.Assert;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
-/**
- *
- */
-public class ClientRequestHandlerTest {
-
-  private final Logger _logger = LoggerFactory.getLogger(ClientRequestHandlerTest.class);
-
-  ZMQ.Context context;
-  ExecutorService serverThread;
-  final String SERVER_ADDRESS = "localhost:5553";
-
-  ClientRequestHandler handler;
-
-  @Before
-  public void setUp() throws Exception {
-    context = ZMQ.context(1);
-    serverThread = Executors.newCachedThreadPool();
-    handler = new ClientRequestHandler(context);
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    serverThread.shutdown();
-    MessagingUtil.closeZmqContext(context);
-    handler.close();
-  }
-
- @Test
-  public void handle_SingleRemote_ShouldReturnResponse() throws Exception {
-    serverThread.execute(MessagingUtil.startReplyServer(context, SERVER_ADDRESS, 1));
-    Message request = new Message();
-    request.setRecipient(SERVER_ADDRESS);
-    Message response = handleMessageWithTimeout(request);
-    Assert.assertNotNull(response);
-    //should be connected to only 1 remote server
-    Assert.assertEquals(1, handler.getWorkerCount());
-    Assert.assertEquals(response.getRecipient(), SERVER_ADDRESS);
-  }
-
- // @Test
-  public void handle_MultiRemote_ShouldReturnResponses() throws Exception {
-    ExecutorService threadPool = Executors.newCachedThreadPool();
-    final int port = 5555;
-    String serverAddress = null;
-    for (int i = 0; i < 5; i++) {
-      serverAddress = "localhost:" + (port + i);
-      serverThread.execute(MessagingUtil.startReplyServer(context, serverAddress, 1));
-      threadPool.execute(createEmptyMessageTaskAndHandle(handler, serverAddress));
-    }
-    Thread.sleep(5000);//wait for all messages to get processed
-    //should be connected to 5 remote server
-    Assert.assertEquals(5, handler.getWorkerCount());
-  }
-
-  private Runnable createEmptyMessageTaskAndHandle(final ClientRequestHandler handler, final String serverAddress) {
-
-    return new Runnable() {
-      @Override
-      public void run() {
-        Message request = new Message();
-        request.setRecipient(serverAddress);
-        try {
-          Message response = handleMessageWithTimeout(request);
-          Assert.assertNotNull(response);
-          Assert.assertEquals(response.getRecipient(), serverAddress);
-        } catch (Exception e) {
-          throw new RuntimeException(e);
-        }
-      }
-    };
-  }
-
-  private Message handleMessageWithTimeout(final Message request) {
-    Message response = null;
-
-    FutureTask<?> task = new FutureTask<Message>(new Callable<Message>() {
-
-      @Override
-      public Message call() {
-        try {
-          return handler.handle(request);
-        } catch (Exception e) {
-          _logger.debug("Client handler failed to handle request. Exception is [{}]", e);
-        }
-        return null;
-      }
-    });
-
-    serverThread.execute(task);
-
-    try {
-      response = (Message) task.get(5L, TimeUnit.SECONDS); //wait for max 5 sec for server to respond
-    } catch (Exception e) {/*ignore and continue*/}
-
-    return response;
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/MockRoutingTable.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/MockRoutingTable.java
deleted file mode 100644 (file)
index 179051e..0000000
+++ /dev/null
@@ -1,79 +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.connector.remoterpc;
-
-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;
-
-/**
- * Mock implementation of routing table
- */
-public class MockRoutingTable<K, V> implements RoutingTable {
-
-
-  @Override
-  public void addRoute(Object o, Object o2) throws RoutingTableException, SystemException {
-
-  }
-
-  @Override
-  public void addGlobalRoute(Object o, Object o2) throws RoutingTableException, SystemException {
-
-  }
-
-  @Override
-  public void removeRoute(Object o, Object o2) {
-
-  }
-
-  @Override
-  public void addRoutes(Set set, Object o) throws RoutingTableException, SystemException {
-    //To change body of implemented methods use File | Settings | File Templates.
-  }
-
-  @Override
-  public void removeRoutes(Set set, Object o) throws RoutingTableException, SystemException {
-    //To change body of implemented methods use File | Settings | File Templates.
-  }
-
-  @Override
-  public void removeGlobalRoute(Object o) throws RoutingTableException, SystemException {
-
-  }
-
-  @Override
-  public Object getGlobalRoute(Object o) throws RoutingTableException, SystemException {
-    return null;  //To change body of implemented methods use File | Settings | File Templates.
-  }
-
-  @Override
-  public Set<String> getRoutes(Object o) {
-    Set<String> routes = new HashSet<String>();
-    routes.add("localhost:5554");
-    return routes;
-  }
-
-  @Override
-  public Object getLastAddedRoute(Object o) {
-    return null;  //To change body of implemented methods use File | Settings | File Templates.
-  }
-
-//  @Override
-//  public Set<Map.Entry> getAllRoutes() {
-//    return Collections.emptySet();
-//  }
-
-//  @Override
-//  public Object getARoute(Object o) {
-//    return null;
-//  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProviderTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProviderTest.java
deleted file mode 100644 (file)
index 06360aa..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.opendaylight.controller.sal.connector.remoterpc;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class RemoteRpcProviderTest {
-  @Before
-  public void setUp() throws Exception {
-
-  }
-
-  @After
-  public void tearDown() throws Exception {
-
-  }
-
-  @Test
-  public void testSetRoutingTableProvider() throws Exception {
-
-  }
-
-  @Test
-  public void testOnSessionInitiated() throws Exception {
-
-  }
-
-  @Test
-  public void testGetSupportedRpcs() throws Exception {
-
-  }
-
-  @Test
-  public void testGetProviderFunctionality() throws Exception {
-
-  }
-
-  @Test
-  public void testInvokeRpc() throws Exception {
-
-  }
-
-  @Test
-  public void testInvokeRoutedRpc() throws Exception {
-
-  }
-
-  @Test
-  public void testStart() throws Exception {
-
-  }
-
-  @Test
-  public void testClose() throws Exception {
-
-  }
-
-  @Test
-  public void testStop() throws Exception {
-
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SerilizationTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SerilizationTest.java
deleted file mode 100644 (file)
index 41422fd..0000000
+++ /dev/null
@@ -1,85 +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.connector.remoterpc;
-
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-
-import javax.xml.stream.XMLStreamException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.StringWriter;
-
-public class SerilizationTest {
-
-  private static final Logger _logger = LoggerFactory.getLogger(SerilizationTest.class);
-
-  public void fromXml() {
-  }
-
-  @Test
-  public void toXml() throws FileNotFoundException {
-
-    //InputStream xmlStream = SerilizationTest.class.getResourceAsStream("/FourSimpleChildren.xml");
-    InputStream xmlStream = SerilizationTest.class.getResourceAsStream("/AddFlow.xml");
-    StringWriter writer = new StringWriter();
-
-    CompositeNode data = loadCompositeNode(xmlStream);
-    Document domTree = NodeUtils.buildShadowDomTree(data);
-    try {
-      TransformerFactory tf = TransformerFactory.newInstance();
-      Transformer transformer = tf.newTransformer();
-      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
-      //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");
-      transformer.transform(new DOMSource(domTree), new StreamResult(writer));
-    } catch (TransformerException e) {
-      _logger.error("Error during translation of Document to OutputStream", e);
-    }
-
-    _logger.info("Parsed xml [{}]", writer.toString());
-  }
-
-  // Figure out how to include TestUtils through pom ...was getting errors
-  private CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
-    if (xmlInputStream == null) {
-      throw new IllegalArgumentException();
-    }
-    Node<?> dataTree;
-    try {
-      dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
-    } catch (XMLStreamException e) {
-      _logger.error("Error during building data tree from XML", e);
-      return null;
-    }
-    if (dataTree == null) {
-      _logger.error("data tree is null");
-      return null;
-    }
-    if (dataTree instanceof SimpleNode) {
-      _logger.error("RPC XML was resolved as SimpleNode");
-      return null;
-    }
-    return (CompositeNode) dataTree;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImplTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImplTest.java
deleted file mode 100644 (file)
index 7ffdf17..0000000
+++ /dev/null
@@ -1,195 +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.connector.remoterpc;
-
-
-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.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 com.google.common.base.Optional;
-
-public class ServerImplTest {
-
-  private static ZMQ.Context context;
-  private ServerImpl server;
-  private Broker.ProviderSession brokerSession;
-  private RoutingTableProvider routingTableProvider;
-  private RpcRegistrationListener listener;
-
-  ExecutorService pool;
-
-  //Server configuration
-  private final int HANDLER_COUNT = 2;
-  private final int HWM = 200;
-  private final int port = 5554;
-  //server address
-  private final String SERVER_ADDRESS = "tcp://localhost:5554";
-
-  //@BeforeClass
-  public static void init() {
-    context = ZMQ.context(1);
-  }
-
-  //@AfterClass
-  public static void destroy() {
-    MessagingUtil.closeZmqContext(context);
-  }
-
-  @Before
-  public void setup() throws InterruptedException {
-    context = ZMQ.context(1);
-    brokerSession = mock(Broker.ProviderSession.class);
-    routingTableProvider = mock(RoutingTableProvider.class);
-    listener = mock(RpcRegistrationListener.class);
-
-    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);
-    when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
-
-    when(brokerSession.addRpcRegistrationListener(listener)).thenReturn(null);
-    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
-  }
-
-  @After
-  public void tearDown() throws InterruptedException {
-
-    if (pool != null)
-      pool.shutdown();
-
-    if (server != null)
-      server.stop();
-
-    MessagingUtil.closeZmqContext(context);
-
-    Thread.sleep(5000);//wait for server to stop
-    Assert.assertEquals(ServerImpl.State.STOPPED, server.getStatus());
-  }
-
-  @Test
-  public void getBrokerSession_Call_ShouldReturnBrokerSession() throws Exception {
-    Optional<Broker.ProviderSession> mayBeBroker = server.getBrokerSession();
-
-    if (mayBeBroker.isPresent())
-      Assert.assertEquals(brokerSession, mayBeBroker.get());
-    else
-      Assert.fail("Broker does not exist in Remote RPC Server");
-
-  }
-
-  @Test
-  public void start_Call_ShouldSetServerStatusToStarted() throws Exception {
-    Assert.assertEquals(ServerImpl.State.STARTED, server.getStatus());
-
-  }
-
-  @Test
-  public void start_Call_ShouldCreateNZmqSockets() throws Exception {
-    final int EXPECTED_COUNT = 2 + HANDLER_COUNT; //1 ROUTER + 1 DEALER + HANDLER_COUNT
-
-    Optional<ZMQ.Context> mayBeContext = server.getZmqContext();
-    if (mayBeContext.isPresent())
-      Assert.assertEquals(EXPECTED_COUNT, findSocketCount(mayBeContext.get()));
-    else
-      Assert.fail("ZMQ Context does not exist in Remote RPC Server");
-  }
-
-  @Test
-  public void start_Call_ShouldCreate1ServerThread() {
-    final String SERVER_THREAD_NAME = "remote-rpc-server";
-    final int EXPECTED_COUNT = 1;
-    List<Thread> serverThreads = findThreadsWithName(SERVER_THREAD_NAME);
-    Assert.assertEquals(EXPECTED_COUNT, serverThreads.size());
-  }
-
-  @Test
-  public void start_Call_ShouldCreateNHandlerThreads() {
-    //final String WORKER_THREAD_NAME = "remote-rpc-worker";
-    final int EXPECTED_COUNT = HANDLER_COUNT;
-
-    Optional<ServerRequestHandler> serverRequestHandlerOptional = server.getHandler();
-    if (serverRequestHandlerOptional.isPresent()){
-      ServerRequestHandler handler = serverRequestHandlerOptional.get();
-      ThreadPoolExecutor workerPool = handler.getWorkerPool();
-      Assert.assertEquals(EXPECTED_COUNT, workerPool.getPoolSize());
-    } else {
-      Assert.fail("Server is in illegal state. ServerHandler does not exist");
-    }
-
-  }
-
-  @Test
-  public void testStop() throws Exception {
-
-  }
-
-  @Test
-  public void testOnRouteUpdated() throws Exception {
-
-  }
-
-  @Test
-  public void testOnRouteDeleted() throws Exception {
-
-  }
-
-  private int findSocketCount(ZMQ.Context context)
-      throws NoSuchFieldException, IllegalAccessException {
-    Field ctxField = context.getClass().getDeclaredField("ctx");
-    ctxField.setAccessible(true);
-    Ctx ctx = Ctx.class.cast(ctxField.get(context));
-
-    Field socketListField = ctx.getClass().getDeclaredField("sockets");
-    socketListField.setAccessible(true);
-    List<SocketBase> sockets = List.class.cast(socketListField.get(ctx));
-
-    return sockets.size();
-  }
-
-  private List<Thread> findThreadsWithName(String name) {
-    Thread[] threads = new Thread[Thread.activeCount()];
-    Thread.enumerate(threads);
-
-    List<Thread> foundThreads = new ArrayList<Thread>();
-    for (Thread t : threads) {
-      if (t.getName().startsWith(name))
-        foundThreads.add(t);
-    }
-
-    return foundThreads;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandlerTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ServerRequestHandlerTest.java
deleted file mode 100644 (file)
index e5fbc76..0000000
+++ /dev/null
@@ -1,110 +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.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;
-import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.zeromq.ZMQ;
-
-public class ServerRequestHandlerTest {
-
-  ServerRequestHandler handler;
-  ZMQ.Context context;
-  ExecutorService executorService = Executors.newCachedThreadPool();
-  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 {
-    context = ZMQ.context(1);
-    String mockServerAddress = mockServerIp + ":" + mockServerPort;
-    Broker.ProviderSession mockSession = mock(Broker.ProviderSession.class);
-    handler = new ServerRequestHandler(context, mockSession, workerCount, mockDealerAddress, mockServerAddress);
-    handler.start();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    executorService.shutdown();
-    MessagingUtil.closeZmqContext(context);
-    handler.close();
-  }
-
-  @Test
-  public void testStart() throws Exception {
-    //should start workers == workerCount
-    Assert.assertEquals(workerCount, handler.getWorkerPool().getPoolSize());
-
-    //killing a thread should recreate another one
-
-    //start router-dealer bridge
-    executorService.execute(MessagingUtil.createRouterDealerBridge(context, mockDealerAddress, mockServerPort));
-    Thread.sleep(1000); //give sometime for socket initialization
-
-    //this will kill the thread
-    final String WORKER_THREAD_NAME = "remote-rpc-worker";
-    interruptAThreadWithName(WORKER_THREAD_NAME);
-
-    //send 4 message to router
-    for (int i = 0; i < 4; i++)
-      executorService.execute(MessagingUtil.sendAnEmptyMessage(context, "tcp://" + mockServerIp + ":" + mockServerPort));
-
-    //worker pool size should not change.
-    Assert.assertEquals(workerCount, handler.getWorkerPool().getPoolSize());
-
-    Thread.sleep(10000); //wait for processing to complete
-  }
-
-  @Test
-  public void testClose() throws Exception {
-
-  }
-
-  /**
-   * Interrupts the first thread found whose name starts with the provided name
-   *
-   * @param name
-   */
-  private void interruptAThreadWithName(String name) {
-    List<Thread> workerThreads = findThreadsWithName(name);
-    if (workerThreads.size() > 0) workerThreads.get(0).interrupt();
-  }
-
-  /**
-   * Find all threads that start with the given name
-   *
-   * @param name
-   * @return
-   */
-  private List<Thread> findThreadsWithName(String name) {
-    Thread[] threads = new Thread[Thread.activeCount()];
-    Thread.enumerate(threads);
-
-    List<Thread> foundThreads = new ArrayList<Thread>();
-    for (Thread t : threads) {
-      if (t.getName().startsWith(name))
-        foundThreads.add(t);
-    }
-
-    return foundThreads;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/MessagingUtil.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/MessagingUtil.java
deleted file mode 100644 (file)
index 883aa52..0000000
+++ /dev/null
@@ -1,186 +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.connector.remoterpc.utils;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.concurrent.ExecutorService;
-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);
-
-  public static Runnable startReplyServer(final ZMQ.Context context,
-                                          final String serverAddress,
-                                          final int numRequests /*number of requests after which server shuts down*/) {
-    return new Runnable() {
-
-      @Override
-      public void run() {
-        final ZMQ.Socket socket = context.socket(ZMQ.REP);
-        try {
-          int returnCode = socket.bind("tcp://" + serverAddress);
-          Assert.assertNotSame(-1, returnCode);
-          _logger.info(" Starting reply server[{}] for test...", serverAddress);
-
-          //for (int i=0;i<numRequests;i++) {
-          while (!Thread.currentThread().isInterrupted()) {
-            byte[] bytes = socket.recv();
-            _logger.debug(" Got request ");
-            socket.send(bytes);
-            _logger.debug(" Sent response ");
-          }
-        } catch (Exception x) {
-          StringWriter w = new StringWriter();
-          PrintWriter p = new PrintWriter(w);
-          x.printStackTrace(p);
-          _logger.debug(w.toString());
-        } finally {
-          socket.close();
-          _logger.info("Shutting down reply server");
-        }
-      }
-    };
-  }
-
-  public static Runnable createRouterDealerBridge(final ZMQ.Context context, final String dealerAddress, final int routerPort) {
-    return new Runnable() {
-      @Override
-      public void run() {
-        ZMQ.Socket router = null;
-        ZMQ.Socket dealer = null;
-        try {
-          router = context.socket(ZMQ.ROUTER);
-          dealer = context.socket(ZMQ.DEALER);
-          router.bind("tcp://*:" + routerPort);
-          dealer.bind(dealerAddress);
-          ZMQ.proxy(router, dealer, null);
-        } catch (Exception e) {/*Ignore*/} finally {
-          if (router != null) router.close();
-          if (dealer != null) dealer.close();
-        }
-      }
-    };
-  }
-
-  public static Runnable sendAMessage(final ZMQ.Context context, final String serverAddress, final Message msg)
-      throws IOException, ClassNotFoundException, InterruptedException {
-
-    return new Runnable() {
-      @Override
-      public void run() {
-        final ZMQ.Socket socket = context.socket(ZMQ.REQ);
-        try {
-
-          socket.connect(serverAddress);
-          System.out.println(Thread.currentThread().getName() + " Sending message");
-          try {
-            socket.send(Message.serialize(msg));
-          } catch (IOException e) {
-            e.printStackTrace();
-          }
-          byte[] bytes = socket.recv();
-          Message response = null;
-          try {
-            response = (Message) Message.deserialize(bytes);
-          } catch (IOException e) {
-            e.printStackTrace();
-          } catch (ClassNotFoundException e) {
-            e.printStackTrace();
-          }
-          System.out.println(Thread.currentThread().getName() + " Got response " + response);
-        } catch (Exception x) {
-          x.printStackTrace();
-        } finally {
-          socket.close();
-        }
-      }
-    };
-  }
-
-  public static Runnable sendAnEmptyMessage(final ZMQ.Context context, final String serverAddress)
-          throws IOException, ClassNotFoundException, InterruptedException {
-
-    return new Runnable() {
-      @Override
-      public void run() {
-        final ZMQ.Socket socket = context.socket(ZMQ.REQ);
-        try {
-
-          socket.connect(serverAddress);
-          System.out.println(Thread.currentThread().getName() + " Sending message");
-          try {
-            socket.send(Message.serialize(new Message()));
-          } catch (IOException e) {
-            e.printStackTrace();
-          }
-          byte[] bytes = socket.recv();
-          Message response = null;
-          try {
-            response = (Message) Message.deserialize(bytes);
-          } catch (IOException e) {
-            e.printStackTrace();
-          } catch (ClassNotFoundException e) {
-            e.printStackTrace();
-          }
-          System.out.println(Thread.currentThread().getName() + " Got response " + response);
-        } catch (Exception x) {
-          x.printStackTrace();
-        } finally {
-          socket.close();
-        }
-      }
-    };
-  }
-
-  public static Message createEmptyMessage() {
-    return new Message();
-  }
-
-  /**
-   * Closes ZMQ Context. It tries to gracefully terminate the context. If
-   * termination takes more than a second, its forcefully shutdown.
-   */
-  public static void closeZmqContext(final ZMQ.Context context) {
-    if (context == null) return;
-
-    ExecutorService exec = Executors.newSingleThreadExecutor();
-    FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
-
-      @Override
-      public void run() {
-        try {
-          if (context != null)
-            context.term();
-            _logger.debug("ZMQ Context terminated gracefully!");
-        } catch (Exception e) {/*Ignore and continue shutdown*/}
-      }
-    }, null);
-
-    exec.execute(zmqTermination);
-
-    try {
-      zmqTermination.get(1L, TimeUnit.SECONDS);
-    } catch (Exception e) {
-      _logger.debug("ZMQ Context terminated forcefully!");
-    }
-
-    exec.shutdownNow();
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/RemoteServerTestClient.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/utils/RemoteServerTestClient.java
deleted file mode 100644 (file)
index 7a4f4a5..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-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;
-
-public class RemoteServerTestClient {
-
-
-
-  public static void main(String args[]) throws Exception{
-    String serverAddress = "tcp://10.195.128.108:5666";
-    ZMQ.Context ctx = ZMQ.context(1);
-    ExecutorService executor = Executors.newSingleThreadExecutor();
-    RemoteServerTestClient client = new RemoteServerTestClient();
-    executor.execute(
-        MessagingUtil.sendAMessage(ctx, serverAddress, client.createPingMessage(serverAddress))
-    );
-    MessagingUtil.sendAMessage(ctx, serverAddress, client.createPingMessage(serverAddress));
-
-    Thread.sleep(5000);
-    MessagingUtil.closeZmqContext(ctx);
-    executor.shutdown();
-  }
-
-  public Message createPingMessage(String serverAddress){
-    Message ping = new Message.MessageBuilder()
-        .type(Message.MessageType.PING)
-        .sender("localhost:5444")
-        .recipient(serverAddress)
-        .build();
-
-    return ping;
-  }
-  public Message createAddFlowMessage(String serverAddress ){
-
-    RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier = getAddFlowRpcIdentifier();
-
-    Message addFlow = new Message.MessageBuilder()
-        .type(Message.MessageType.REQUEST)
-        .sender("localhost:5444")
-        .recipient(serverAddress)
-        .route(routeIdentifier)
-        .payload(getAddFlowPayload(1,1))
-        .build();
-
-    return addFlow;
-  }
-
-  private RpcRouter.RouteIdentifier<?, ?, ?> getAddFlowRpcIdentifier(){
-    throw new UnsupportedOperationException();
-  }
-
-  private CompositeNode getAddFlowPayload(int flowId, int tableId){
-    final String xml =
-    "<flow xmlns=\"urn:opendaylight:flow:inventory\">"
-    + "<priority>5</priority>"
-    + "<flow-name>Foo</flow-name>"
-    + "<match>"
-    + "<ethernet-match>"
-    + "<ethernet-type>"
-    + "<type>2048</type>"
-    + "</ethernet-type>"
-    + "</ethernet-match>"
-    + "<ipv4-destination>10.0.10.2/24</ipv4-destination>"
-    + "</match>"
-    + "<id>" + flowId + "</id>"
-    + "<table_id>" + tableId + "</table_id>"
-    + "<instructions>"
-    + "<instruction>"
-    + "<order>0</order>"
-    + "<apply-actions>"
-    + "<action>"
-    + "<order>0</order>"
-    + "<dec-nw-ttl/>"
-    + "</action>"
-    + "</apply-actions>"
-    + "</instruction>"
-    + "</instructions>"
-    + "</flow>";
-
-    return XmlUtils.xmlToCompositeNode(xml);
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/AddFlow.xml b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/AddFlow.xml
deleted file mode 100644 (file)
index b042b8f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<add-flow xmlns="urn:opendaylight:flow:service">
-  <input>
-    <transaction-uri>BA-7</transaction-uri>
-    <table_id>4</table_id>
-    <priority>5</priority>
-    <node>
-      /(urn:opendaylight:inventory?revision=2013-08-19)nodes/(urn:opendaylight:inventory?revision=2013-08-19)node[{(urn:opendaylight:inventory?revision=2013-08-19)id=openflow:1}]
-    </node>
-    <match>
-      <ipv4-destination>10.0.10.2/24</ipv4-destination>
-      <ethernet-match>
-        <ethernet-type>
-          <type>2048</type>
-        </ethernet-type>
-      </ethernet-match>
-    </match>
-    <instructions>
-      <instruction>
-        <order>0</order>
-        <apply-actions>
-          <action>
-            <order>0</order>
-            <dec-nw-ttl/>
-          </action>
-        </apply-actions>
-      </instruction>
-    </instructions>
-    <flow-table>
-      /(urn:opendaylight:inventory?revision=2013-08-19)nodes/(urn:opendaylight:inventory?revision=2013-08-19)node[{(urn:opendaylight:inventory?revision=2013-08-19)id=openflow:1}]/(urn:opendaylight:flow:inventory?revision=2013-08-19)table[{(urn:opendaylight:flow:inventory?revision=2013-08-19)id=4}]
-    </flow-table>
-    <flow-ref>
-      /(urn:opendaylight:inventory?revision=2013-08-19)nodes/(urn:opendaylight:inventory?revision=2013-08-19)node[{(urn:opendaylight:inventory?revision=2013-08-19)id=openflow:1}]/(urn:opendaylight:flow:inventory?revision=2013-08-19)table[{(urn:opendaylight:flow:inventory?revision=2013-08-19)id=4}]/(urn:opendaylight:flow:inventory?revision=2013-08-19)flow[{(urn:opendaylight:flow:inventory?revision=2013-08-19)id=4}]
-    </flow-ref>
-    <flow-name>Foo</flow-name>
-  </input>
-</add-flow>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/FourSimpleChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/FourSimpleChildren.xml
deleted file mode 100644 (file)
index 5ac991b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<rpc>
-    <name>eth0</name>
-    <type>ethernetCsmacd</type>
-    <enabled>false</enabled>
-    <description>some interface</description>
-</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/logback-test.xml b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/logback-test.xml
deleted file mode 100644 (file)
index 7eb75b9..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/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml
deleted file mode 100644 (file)
index 89695c1..0000000
+++ /dev/null
@@ -1,83 +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.tests</groupId>
-    <artifactId>sal-remoterpc-connector-test-parent</artifactId>
-    <version>1.1-SNAPSHOT</version>
-  </parent>
-  <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
-  <packaging>bundle</packaging>
-
-  <dependencies>
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>containermanager</artifactId>
-      <version>0.5.2-SNAPSHOT</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.8.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-core-api</artifactId>
-      <version>1.1-SNAPSHOT</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.yangtools</groupId>
-      <artifactId>yang-data-impl</artifactId>
-      <version>${yangtools.version}</version>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Bundle-Activator>org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer</Bundle-Activator>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <scm>
-    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-  </scm>
-</project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java
deleted file mode 100644 (file)
index aac6da4..0000000
+++ /dev/null
@@ -1,128 +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.sample.zeromq.consumer;
-
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Hashtable;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.sal.core.api.AbstractConsumer;
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-
-import javax.xml.stream.XMLStreamException;
-
-public class ExampleConsumer extends AbstractConsumer {
-
-  private final URI namespace = URI.create("http://cisco.com/example");
-  private final QName QNAME = new QName(namespace, "heartbeat");
-
-  private ConsumerSession session;
-
-  private ServiceRegistration<ExampleConsumer> thisReg;
-  private Logger _logger = LoggerFactory.getLogger(ExampleConsumer.class);
-
-  @Override
-  public void onSessionInitiated(ConsumerSession session) {
-    this.session = session;
-  }
-
-  public RpcResult<CompositeNode> invokeRpc(QName qname, CompositeNode input) {
-    _logger.info("Invoking RPC:[{}] with Input:[{}]", qname.getLocalName(), input);
-    RpcResult<CompositeNode> result = null;
-    Future<RpcResult<CompositeNode>> future = ExampleConsumer.this.session.rpc(qname, input);
-    try {
-      result = future.get();
-    } catch (Exception e) {
-      e.printStackTrace();
-    }
-    _logger.info("Returning Result:[{}]", result);
-    return result;
-  }
-
-  @Override
-  protected void startImpl(BundleContext context){
-    thisReg = context.registerService(ExampleConsumer.class, this, new Hashtable<String,String>());
-  }
-  @Override
-  protected void stopImpl(BundleContext context) {
-    super.stopImpl(context);
-    thisReg.unregister();
-  }
-
-  public CompositeNode getValidCompositeNodeWithOneSimpleChild() throws FileNotFoundException {
-    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/OneSimpleChild.xml");
-    return loadCompositeNode(xmlStream);
-  }
-
-  public CompositeNode getValidCompositeNodeWithTwoSimpleChildren() throws FileNotFoundException {
-    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/TwoSimpleChildren.xml");
-    return loadCompositeNode(xmlStream);
-  }
-
-  public CompositeNode getValidCompositeNodeWithFourSimpleChildren() throws FileNotFoundException {
-    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/FourSimpleChildren.xml");
-    return loadCompositeNode(xmlStream);
-  }
-
-  public CompositeNode getValidCompositeNodeWithOneSimpleOneCompositeChild() throws FileNotFoundException {
-    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/OneSimpleOneCompositeChild.xml");
-    return loadCompositeNode(xmlStream);
-  }
-
-  public CompositeNode getValidCompositeNodeWithTwoCompositeChildren() throws FileNotFoundException {
-    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/TwoCompositeChildren.xml");
-    return loadCompositeNode(xmlStream);
-  }
-
-  public CompositeNode getInvalidCompositeNodeSimpleChild() throws FileNotFoundException {
-    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/InvalidSimpleChild.xml");
-    return loadCompositeNode(xmlStream);
-  }
-
-  public CompositeNode getInvalidCompositeNodeCompositeChild() throws FileNotFoundException {
-    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/InvalidCompositeChild.xml");
-    return loadCompositeNode(xmlStream);
-  }
-
-  //Note to self:  Stolen from TestUtils
-  ///Users/alefan/odl/controller4/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
-  // Figure out how to include TestUtils through pom ...was getting errors
-  private CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
-    if (xmlInputStream == null) {
-      throw new IllegalArgumentException();
-    }
-    Node<?> dataTree;
-    try {
-      dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
-    } catch (XMLStreamException e) {
-      _logger.error("Error during building data tree from XML", e);
-      return null;
-    }
-    if (dataTree == null) {
-      _logger.error("data tree is null");
-      return null;
-    }
-    if (dataTree instanceof SimpleNode) {
-      _logger.error("RPC XML was resolved as SimpleNode");
-      return null;
-    }
-    return (CompositeNode) dataTree;
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/FourSimpleChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/FourSimpleChildren.xml
deleted file mode 100644 (file)
index 5ac991b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<rpc>
-    <name>eth0</name>
-    <type>ethernetCsmacd</type>
-    <enabled>false</enabled>
-    <description>some interface</description>
-</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidCompositeChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidCompositeChild.xml
deleted file mode 100644 (file)
index 3979d02..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<rpc>
-    <innerinterface1>
-        <name>eth1</name>
-        <type>ethernet</type>
-        <enabled>false</enabled>
-        <description>some interface</description>
-    </innerinterface1>
-    <innerinterface2>
-        <name>error</name>
-        <type>ethernet</type>
-        <enabled>true</enabled>
-        <description>some interface</description>
-    </innerinterface2>
-</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidSimpleChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidSimpleChild.xml
deleted file mode 100644 (file)
index 6082d72..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<rpc>
-    <name>error</name>
-</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleChild.xml
deleted file mode 100644 (file)
index f431b04..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<rpc>
-    <name>eth0</name>
-</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleOneCompositeChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleOneCompositeChild.xml
deleted file mode 100644 (file)
index bca7682..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<rpc>
-    <name>eth0</name>
-    <innerinterface>
-        <name>eth1</name>
-        <type>ethernetCsmacd</type>
-        <enabled>false</enabled>
-        <description>some interface</description>
-    </innerinterface>
-</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoCompositeChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoCompositeChildren.xml
deleted file mode 100644 (file)
index c49407e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<rpc>
-    <innerinterface1>
-        <name>eth1</name>
-        <type>ethernet</type>
-        <enabled>false</enabled>
-        <description>some interface</description>
-    </innerinterface1>
-    <innerinterface2>
-        <name>eth2</name>
-        <type>ethernet</type>
-        <enabled>true</enabled>
-        <description>some interface</description>
-    </innerinterface2>
-</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoSimpleChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoSimpleChildren.xml
deleted file mode 100644 (file)
index 5f4729c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<rpc>
-    <name>eth0</name>
-    <type>ethernetCsmacd</type>
-</rpc>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/pom.xml
deleted file mode 100644 (file)
index 3f47700..0000000
+++ /dev/null
@@ -1,26 +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>
-  <groupId>org.opendaylight.controller.tests</groupId>
-  <artifactId>sal-remoterpc-connector-test-parent</artifactId>
-  <packaging>pom</packaging>
-
-  <modules>
-    <module>consumer-service</module>
-    <module>provider-service</module>
-    <module>test-it</module>
-    <module>test-nb</module>
-  </modules>
-  <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>
-
-</project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml
deleted file mode 100644 (file)
index bd0e43b..0000000
+++ /dev/null
@@ -1,89 +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-remoterpc-connector-test-parent</artifactId>
-        <groupId>org.opendaylight.controller.tests</groupId>
-        <version>1.1-SNAPSHOT</version>
-  </parent>
-  <artifactId>sal-remoterpc-connector-test-provider</artifactId>
-  <packaging>bundle</packaging>
-  <scm>
-    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-  </scm>
-
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Bundle-Activator>org.opendaylight.controller.sample.zeromq.provider.ExampleProvider</Bundle-Activator>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-core-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>containermanager</artifactId>
-      <version>0.5.2-SNAPSHOT</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.8.1-SNAPSHOT</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.yangtools</groupId>
-      <artifactId>yang-data-impl</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-remoterpc-connector</artifactId>
-      <version>1.1-SNAPSHOT</version>
-    </dependency>
-
-  </dependencies>
-</project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java
deleted file mode 100644 (file)
index ff930db..0000000
+++ /dev/null
@@ -1,130 +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.sample.zeromq.provider;
-
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-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 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.CompositeNodeTOImpl;
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class ExampleProvider extends AbstractProvider implements RpcImplementation {
-
-  private final URI namespace = URI.create("http://cisco.com/example");
-  private final QName QNAME = new QName(namespace, "heartbeat");
-  private RpcRegistration reg;
-
-  private ServiceRegistration thisReg;
-
-  private ProviderSession session;
-  private Logger _logger = LoggerFactory.getLogger(ExampleProvider.class);
-
-  @Override
-  public void onSessionInitiated(ProviderSession session) {
-    this.session = session;
-  }
-
-  @Override
-  public Set<QName> getSupportedRpcs() {
-    Set<QName> supportedRpcs = new HashSet<QName>();
-    supportedRpcs.add(QNAME);
-    return supportedRpcs;
-  }
-
-  @Override
-  public RpcResult<CompositeNode> invokeRpc(final QName rpc, CompositeNode input) {
-    boolean success = false;
-    CompositeNode output = null;
-    Collection<RpcError> errors = new ArrayList<>();
-
-    // Only handle supported RPC calls
-    if (getSupportedRpcs().contains(rpc))  {
-      if (input == null) {
-        errors.add(RpcErrors.getRpcError("app", "tag", "info", RpcError.ErrorSeverity.WARNING, "message:null input", RpcError.ErrorType.RPC, null));
-      }
-      else {
-        if (isErroneousInput(input)) {
-          errors.add(RpcErrors.getRpcError("app", "tag", "info", RpcError.ErrorSeverity.ERROR, "message:error", RpcError.ErrorType.RPC, null));
-        }
-        else {
-          success = true;
-          output = addSuccessNode(input);
-        }
-      }
-    }
-    return Rpcs.getRpcResult(success, output, errors);
-  }
-
-  // Examines input -- dives into CompositeNodes and finds any value equal to "error"
-  private boolean isErroneousInput(CompositeNode input) {
-    for (Node<?> n : input.getChildren()) {
-      if (n instanceof CompositeNode) {
-        if (isErroneousInput((CompositeNode)n)) {
-          return true;
-        }
-      }
-      else {  //SimpleNode
-        if ((input.getChildren().get(0).getValue()).equals("error")) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  // Adds a child SimpleNode containing the value "success" to the input CompositeNode
-  private CompositeNode addSuccessNode(CompositeNode input) {
-    List<Node<?>> list = new ArrayList<Node<?>>(input.getChildren());
-    SimpleNodeTOImpl<String> simpleNode = new SimpleNodeTOImpl<String>(QNAME, input, "success");
-    list.add(simpleNode);
-    return new CompositeNodeTOImpl(QNAME, null, list);
-  }
-
-  @Override
-  protected void startImpl(BundleContext context) {
-    thisReg = context.registerService(ExampleProvider.class, this, new Hashtable<String, String>());
-  }
-
-  @Override
-  protected void stopImpl(BundleContext context) {
-    if (reg != null) {
-      try {
-        reg.close();
-        thisReg.unregister();
-      } catch (Exception e) {
-        // TODO Auto-generated catch block
-        e.printStackTrace();
-      }
-    }
-  }
-
-  public void announce(QName name) {
-    _logger.debug("Announcing [{}]\n\n\n", name);
-    reg = this.session.addRpcImplementation(name, this);
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml
deleted file mode 100644 (file)
index 84e9d29..0000000
+++ /dev/null
@@ -1,533 +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-remoterpc-connector-test-parent</artifactId>
-        <groupId>org.opendaylight.controller.tests</groupId>
-        <version>1.1-SNAPSHOT</version>
-    </parent>
-    <artifactId>sal-remoterpc-connector-test-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>
-
-    <properties>
-        <jackson.version>2.3.0</jackson.version>
-        <exam.version>3.0.0</exam.version>
-        <url.version>1.5.0</url.version>
-    </properties>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>commons-codec</groupId>
-                <artifactId>commons-codec</artifactId>
-                <version>1.7</version>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-
-    <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.yangtools.thirdparty</groupId>
-            <artifactId>xtend-lib-osgi</artifactId>
-            <version>2.4.3</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.tests</groupId>
-            <artifactId>sal-remoterpc-connector-test-provider</artifactId>
-            <version>1.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.tests</groupId>
-            <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
-            <version>1.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-broker-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
-        </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.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>1.5.2</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</groupId>
-            <artifactId>sal-remoterpc-connector</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>containermanager</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.osgi</groupId>
-                    <artifactId>org.osgi.compendium</artifactId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>commons-io</artifactId>
-                    <groupId>commons-io</groupId>
-                </exclusion>
-            </exclusions>
-        </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.yangtools</groupId> <artifactId>yang-data-impl</artifactId>
-            <version>${yangtools.version}</version> </dependency -->
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-parser-impl</artifactId>
-            <version>${yangtools.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-            <version>4.0</version>
-        </dependency>
-
-        <!-- routing table dependencies -->
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>zeromq-routingtable.implementation</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>clustering.services</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.osgi</groupId>
-                    <artifactId>org.osgi.compendium</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal.implementation</artifactId>
-            <version>0.4.0-SNAPSHOT</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>commons-io</artifactId>
-                    <groupId>commons-io</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>containermanager</artifactId>
-            <version>0.5.0-SNAPSHOT</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.osgi</groupId>
-                    <artifactId>org.osgi.compendium</artifactId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>commons-io</artifactId>
-                    <groupId>commons-io</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>containermanager.it.implementation</artifactId>
-            <version>0.5.0-SNAPSHOT</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>commons-io</artifactId>
-                    <groupId>commons-io</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>clustering.stub</artifactId>
-            <version>0.4.0-SNAPSHOT</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>commons-io</artifactId>
-                    <groupId>commons-io</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
-            <version>3.0.1</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.osgi</groupId>
-                    <artifactId>org.osgi.compendium</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>eclipselink</groupId>
-            <artifactId>javax.resource</artifactId>
-            <version>1.5.0.v200906010428</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>ietf-netconf-monitoring</artifactId>
-          <version>0.2.5-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-binding</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.model</groupId>
-            <artifactId>yang-ext</artifactId>
-            <version>2013.09.07.3</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.model</groupId>
-            <artifactId>opendaylight-l2-types</artifactId>
-            <version>2013.08.27.3</version>
-        </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-binding-config</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.opendaylight.controller.model</groupId>
-            <artifactId>model-inventory</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-common</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-connector-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>clustering.services</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
-        </dependency>
-
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-            <version>${jackson.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-annotations</artifactId>
-            <version>${jackson.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-            <version>${jackson.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.zeromq</groupId>
-            <artifactId>jeromq</artifactId>
-            <version>0.3.1</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>
-            <scope>test</scope>
-        </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>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>netconf-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam</artifactId>
-            <version>${exam.version}</version>
-            <!-- Compile scope here is intentional, it is used in TestHelper
-                class which could be downloaded via nexus and reused in other integration
-                tests. -->
-            <scope>compile</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.mockito</groupId>
-            <artifactId>mockito-all</artifactId>
-            <scope>test</scope>
-        </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>
-            <exclusions>
-                <exclusion>
-                    <artifactId>commons-io</artifactId>
-                    <groupId>commons-io</groupId>
-                </exclusion>
-            </exclusions>
-        </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>
-</project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/RouterTest.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/RouterTest.java
deleted file mode 100644 (file)
index e02e290..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.sample.zeromq.test.it;
-
-import junit.framework.Assert;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcClient;
-
-import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer;
-import org.opendaylight.controller.sample.zeromq.provider.ExampleProvider;
-
-import org.opendaylight.controller.test.sal.binding.it.TestHelper;
-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.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.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceReference;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
-import javax.inject.Inject;
-
-import java.io.IOException;
-import java.net.URI;
-
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.baseModelBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.bindingAwareSalBundles;
-
-//import static org.ops4j.pax.exam.CoreOptions.*;
-
-@RunWith(PaxExam.class)
-public class RouterTest {
-
-  private Logger _logger = LoggerFactory.getLogger(RouterTest.class);
-
-  public static final String ODL = "org.opendaylight.controller";
-  public static final String YANG = "org.opendaylight.yangtools";
-  public static final String SAMPLE = "org.opendaylight.controller.tests";
-  private final URI namespace = URI.create("http://cisco.com/example");
-  private final QName QNAME = new QName(namespace, "heartbeat");
-
-
-  @Inject
-  org.osgi.framework.BundleContext ctx;
-
-  @Inject
-  @Filter(timeout=60*1000)
-  Broker broker;
-
-  private ZMQ.Context zmqCtx = ZMQ.context(1);
-  //private Server router;
-  //private ExampleProvider provider;
-
-  //@Test
-  public void testInvokeRpc() throws Exception{
-    //Thread.sleep(1000);
-    //Send announcement
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    Assert.assertNotNull(providerRef);
-
-    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-    Assert.assertNotNull(provider);
-
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    Assert.assertNotNull(consumerRef);
-    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-    Assert.assertNotNull(consumer);
-
-
-    _logger.debug("Provider sends announcement [{}]", "heartbeat");
-    provider.announce(QNAME);
-    ServiceReference routerRef = ctx.getServiceReference(RemoteRpcClient.class);
-    RemoteRpcClient router = (RemoteRpcClient) ctx.getService(routerRef);
-    _logger.debug("Found router[{}]", router);
-    _logger.debug("Invoking RPC [{}]", QNAME);
-    for (int i = 0; i < 3; i++) {
-      RpcResult<CompositeNode> result = router.invokeRpc(QNAME, consumer.getValidCompositeNodeWithOneSimpleChild());
-      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-      Assert.assertNotNull(result);
-    }
-  }
-
-  @Test
-  public void testInvokeRpcWithValidSimpleNode() throws Exception{
-    //Thread.sleep(1500);
-
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    Assert.assertNotNull(providerRef);
-    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-    Assert.assertNotNull(provider);
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    Assert.assertNotNull(consumerRef);
-    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-    Assert.assertNotNull(consumer);
-
-    // Provider sends announcement
-    _logger.debug("Provider sends announcement [{}]", "heartbeat");
-    provider.announce(QNAME);
-    // Consumer invokes RPC
-    _logger.debug("Invoking RPC [{}]", QNAME);
-    CompositeNode input = consumer.getValidCompositeNodeWithOneSimpleChild();
-    for (int i = 0; i < 3; i++) {
-      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
-      Assert.assertNotNull(result);
-      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-      Assert.assertTrue(result.isSuccessful());
-      Assert.assertNotNull(result.getResult());
-      Assert.assertEquals(0, result.getErrors().size());
-      Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
-    }
-  }
-
-  @Test
-  public void testInvokeRpcWithValidSimpleNodes() throws Exception{
-    //Thread.sleep(1500);
-
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    Assert.assertNotNull(providerRef);
-    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-    Assert.assertNotNull(provider);
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    Assert.assertNotNull(consumerRef);
-    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-    Assert.assertNotNull(consumer);
-
-    // Provider sends announcement
-    _logger.debug("Provider sends announcement [{}]", "heartbeat");
-    provider.announce(QNAME);
-    // Consumer invokes RPC
-    _logger.debug("Invoking RPC [{}]", QNAME);
-    CompositeNode input = consumer.getValidCompositeNodeWithFourSimpleChildren();
-    for (int i = 0; i < 3; i++) {
-      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
-      Assert.assertNotNull(result);
-      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-      Assert.assertTrue(result.isSuccessful());
-      Assert.assertNotNull(result.getResult());
-      Assert.assertEquals(0, result.getErrors().size());
-      Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
-    }
-  }
-
-  @Test
-  public void testInvokeRpcWithValidCompositeNode() throws Exception{
-    //Thread.sleep(1500);
-
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    Assert.assertNotNull(providerRef);
-    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-    Assert.assertNotNull(provider);
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    Assert.assertNotNull(consumerRef);
-    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-    Assert.assertNotNull(consumer);
-
-    // Provider sends announcement
-    _logger.debug("Provider sends announcement [{}]", "heartbeat");
-    provider.announce(QNAME);
-    // Consumer invokes RPC
-    _logger.debug("Invoking RPC [{}]", QNAME);
-    CompositeNode input = consumer.getValidCompositeNodeWithTwoCompositeChildren();
-    for (int i = 0; i < 3; i++) {
-      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
-      Assert.assertNotNull(result);
-      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-      Assert.assertTrue(result.isSuccessful());
-      Assert.assertNotNull(result.getResult());
-      Assert.assertEquals(0, result.getErrors().size());
-      Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
-    }
-  }
-
-  @Test
-  public void testInvokeRpcWithNullInput() throws Exception{
-    //Thread.sleep(1500);
-
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    Assert.assertNotNull(providerRef);
-    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-    Assert.assertNotNull(provider);
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    Assert.assertNotNull(consumerRef);
-    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-    Assert.assertNotNull(consumer);
-
-    // Provider sends announcement
-    _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
-    provider.announce(QNAME);
-    // Consumer invokes RPC
-    _logger.debug("Invoking RPC [{}]", QNAME);
-    for (int i = 0; i < 3; i++) {
-      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, null);
-      Assert.assertNotNull(result);
-      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-      Assert.assertFalse(result.isSuccessful());
-      Assert.assertNull(result.getResult());
-      Assert.assertEquals(1, result.getErrors().size());
-      Assert.assertEquals(RpcError.ErrorSeverity.WARNING, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
-    }
-  }
-
-  @Test
-  public void testInvokeRpcWithInvalidSimpleNode() throws Exception{
-    //Thread.sleep(1500);
-
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    Assert.assertNotNull(providerRef);
-    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-    Assert.assertNotNull(provider);
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    Assert.assertNotNull(consumerRef);
-    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-    Assert.assertNotNull(consumer);
-
-    // Provider sends announcement
-    _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
-    provider.announce(QNAME);
-    // Consumer invokes RPC
-    _logger.debug("Invoking RPC [{}]", QNAME);
-    CompositeNode input = consumer.getInvalidCompositeNodeSimpleChild();
-    for (int i = 0; i < 3; i++) {
-      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
-      Assert.assertNotNull(result);
-      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-      Assert.assertFalse(result.isSuccessful());
-      Assert.assertNull(result.getResult());
-      Assert.assertEquals(1, result.getErrors().size());
-      Assert.assertEquals(RpcError.ErrorSeverity.ERROR, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
-    }
-  }
-
-  @Test
-  public void testInvokeRpcWithInvalidCompositeNode() throws Exception{
-    //Thread.sleep(1500);
-
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    Assert.assertNotNull(providerRef);
-    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-    Assert.assertNotNull(provider);
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    Assert.assertNotNull(consumerRef);
-    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-    Assert.assertNotNull(consumer);
-
-    // Provider sends announcement
-    _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
-    provider.announce(QNAME);
-    // Consumer invokes RPC
-    _logger.debug("Invoking RPC [{}]", QNAME);
-    CompositeNode input = consumer.getInvalidCompositeNodeCompositeChild();
-    for (int i = 0; i < 3; i++) {
-      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
-      Assert.assertNotNull(result);
-      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-      Assert.assertFalse(result.isSuccessful());
-      Assert.assertNull(result.getResult());
-      Assert.assertEquals(1, result.getErrors().size());
-      Assert.assertEquals(RpcError.ErrorSeverity.ERROR, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
-    }
-  }
-
-  //@Test
-  // This method is UNTESTED -- need to get around the bundling issues before I know if this even work
-//  public void testInvokeRpcWithValidCompositeNode() throws Exception{
-//    Thread.sleep(10000);
-//    //Send announcement
-//    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-//    Assert.assertNotNull(providerRef);
-//
-//    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
-//    Assert.assertNotNull(provider);
-//
-//    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-//    Assert.assertNotNull(consumerRef);
-//
-//    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
-//    Assert.assertNotNull(consumer);
-//
-//    _logger.debug("Provider sends announcement [{}]", "heartbeat");
-//    provider.announce(QNAME);
-//    ServiceReference routerRef = ctx.getServiceReference(Client.class);
-//    Client router = (Client) ctx.getService(routerRef);
-//    _logger.debug("Found router[{}]", router);
-//    _logger.debug("Invoking RPC [{}]", QNAME);
-//    for (int i = 0; i < 3; i++) {
-//      RpcResult<CompositeNode> result = router.getInstance().invokeRpc(QNAME, consumer.getValidCompositeNodeWithOneSimpleChild());
-//      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
-//      Assert.assertNotNull(result);
-//    }
-//  }
-
-  private Message send(Message msg) throws IOException {
-    ZMQ.Socket reqSocket = zmqCtx.socket(ZMQ.REQ);
-    reqSocket.connect("tcp://localhost:5555");
-    reqSocket.send(Message.serialize(msg));
-    Message response = parseMessage(reqSocket);
-
-    return response;
-  }
-
-  /**
-   * @param socket
-   * @return
-   */
-  private Message parseMessage(ZMQ.Socket socket) {
-
-    Message msg = null;
-    try {
-      byte[] bytes = socket.recv();
-      _logger.debug("Received bytes:[{}]", bytes.length);
-      msg = (Message) Message.deserialize(bytes);
-    } catch (Throwable t) {
-      t.printStackTrace();
-    }
-    return msg;
-  }
-
-
-  private void printState(){
-    Bundle[] b = ctx.getBundles();
-    _logger.debug("\n\nNumber of bundles [{}]\n\n]", b.length);
-    for (int i=0;i<b.length;i++){
-      _logger.debug("Bundle States {}-{} ",b[i].getSymbolicName(), stateToString(b[i].getState()));
-
-      if ( Bundle.INSTALLED == b[i].getState() || (Bundle.RESOLVED == b[i].getState())){
-        try {
-          b[i].start();
-        } catch (BundleException e) {
-          e.printStackTrace();
-        }
-      }
-    }
-  }
-
-  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";
-    }
-  }
-
-  @Configuration
-  public Option[] config() {
-    return options(systemProperty("osgi.console").value("2401"),
-            systemProperty("rpc.port").value("5555"),
-            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(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(), //
-
-
-            baseModelBundles(),
-            bindingAwareSalBundles(),
-            TestHelper.bindingIndependentSalBundles(),
-            TestHelper.configMinumumBundles(),
-            TestHelper.mdSalCoreBundles(),
-
-            //Added the consumer
-            mavenBundle(SAMPLE, "sal-remoterpc-connector-test-consumer").versionAsInProject(), //
-            //**** These two bundles below are NOT successfully resolved -- some of their dependencies must be missing
-            //**** This causes the "Message" error to occur, the class cannot be found
-            mavenBundle(SAMPLE, "sal-remoterpc-connector-test-provider").versionAsInProject(), //
-            mavenBundle(ODL, "sal-remoterpc-connector").versionAsInProject(), //
-
-            mavenBundle(ODL, "zeromq-routingtable.implementation").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-parser-api").versionAsInProject(), //
-            mavenBundle(YANG, "yang-parser-impl").versionAsInProject(), //
-            mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
-            mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
-            mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
-            mavenBundle("com.google.guava", "guava").versionAsInProject(), //
-            mavenBundle("org.zeromq", "jeromq").versionAsInProject(),
-            mavenBundle("org.codehaus.jackson", "jackson-mapper-asl").versionAsInProject(),
-            mavenBundle("org.codehaus.jackson", "jackson-core-asl").versionAsInProject(),
-            //routingtable dependencies
-            systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
-            // 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.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(),
-            mavenBundle("org.opendaylight.controller", "sal.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()
-    );
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/controller.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/controller.xml
deleted file mode 100644 (file)
index c8e3b83..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<persisted-snapshots>
-    <snapshots>
-        <snapshot>
-            <required-capabilities>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config?module=config&amp;revision=2013-04-05
-                </capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28
-                </capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28
-                </capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28
-                </capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-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:impl">
-                                prefix:schema-service-singleton
-                            </type>
-                            <name>yang-schema-service</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                                prefix:hash-map-data-store
-                            </type>
-                            <name>hash-map-data-store</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                                prefix:dom-broker-impl
-                            </type>
-                            <name>dom-broker</name>
-                            <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                    dom:dom-data-store
-                                </type>
-                                <name>ref_hash-map-data-store</name>
-                            </data-store>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:binding-broker-impl
-                            </type>
-                            <name>binding-broker-impl</name>
-                            <notification-service
-                                    xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                    binding:binding-notification-service
-                                </type>
-                                <name>ref_binding-notification-broker</name>
-                            </notification-service>
-                            <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                    binding:binding-data-broker
-                                </type>
-                                <name>ref_binding-data-broker</name>
-                            </data-broker>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:runtime-generated-mapping
-                            </type>
-                            <name>runtime-mapping-singleton</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:binding-notification-broker
-                            </type>
-                            <name>binding-notification-broker</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:binding-data-broker
-                            </type>
-                            <name>binding-data-broker</name>
-                            <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                    dom:dom-broker-osgi-registry
-                                </type>
-                                <name>ref_dom-broker</name>
-                            </dom-broker>
-                            <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                    binding:binding-dom-mapping-service
-                                </type>
-                                <name>ref_runtime-mapping-singleton</name>
-                            </mapping-service>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
-                                prefix:remote-zeromq-rpc-server
-                            </type>
-                            <name>remoter</name>
-                            <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
-                            <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
-                                <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                    prefix:dom-broker-osgi-registry
-                                </type>
-                                <name>ref_dom-broker</name>
-                            </dom-broker>
-                        </module>
-                    </modules>
-
-                    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                        <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                dom:schema-service
-                            </type>
-                            <instance>
-                                <name>ref_yang-schema-service</name>
-                                <provider>
-                                    /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']
-                                </provider>
-                            </instance>
-                        </service>
-                        <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                binding:binding-notification-service
-                            </type>
-                            <instance>
-                                <name>ref_binding-notification-broker</name>
-                                <provider>
-                                    /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']
-                                </provider>
-                            </instance>
-                        </service>
-                        <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                dom:dom-data-store
-                            </type>
-                            <instance>
-                                <name>ref_hash-map-data-store</name>
-                                <provider>
-                                    /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']
-                                </provider>
-                            </instance>
-                        </service>
-                        <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                binding:binding-broker-osgi-registry
-                            </type>
-                            <instance>
-                                <name>ref_binding-broker-impl</name>
-                                <provider>
-                                    /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']
-                                </provider>
-                            </instance>
-                        </service>
-                        <service>
-                            <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                binding-impl:binding-dom-mapping-service
-                            </type>
-                            <instance>
-                                <name>ref_runtime-mapping-singleton</name>
-                                <provider>
-                                    /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']
-                                </provider>
-                            </instance>
-                        </service>
-                        <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                dom:dom-broker-osgi-registry
-                            </type>
-                            <instance>
-                                <name>ref_dom-broker</name>
-                                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']
-                                </provider>
-                            </instance>
-                        </service>
-                        <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                binding:binding-data-broker
-                            </type>
-                            <instance>
-                                <name>ref_binding-data-broker</name>
-                                <provider>
-                                    /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']
-                                </provider>
-                            </instance>
-                        </service>
-                    </services>
-                </data>
-
-            </configuration>
-        </snapshot>
-    </snapshots>
-</persisted-snapshots>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/logback.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 1d17796..0000000
+++ /dev/null
@@ -1,16 +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>
-
-
-  <logger name="org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort" level="ERROR"/>
-
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml
deleted file mode 100644 (file)
index b041cb4..0000000
+++ /dev/null
@@ -1,109 +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>
-    <artifactId>sal-remoterpc-connector-test-parent</artifactId>
-    <groupId>org.opendaylight.controller.tests</groupId>
-    <version>1.1-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>sal-remoterpc-connector-test-nb</artifactId>
-  <packaging>bundle</packaging>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${bundle.plugin.version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Export-Package>
-            </Export-Package>
-            <Import-Package>
-              com.sun.jersey.spi.container.servlet,
-              !org.codehaus.jackson.annotate,
-              javax.ws.rs,
-              javax.ws.rs.core,
-              javax.xml.bind,
-              javax.xml.bind.annotation,
-              org.slf4j,
-              org.apache.catalina.filters,
-              !org.codehaus.jackson.jaxrs,
-              org.opendaylight.controller.sample.zeromq.provider,
-              org.opendaylight.controller.sample.zeromq.consumer,
-              org.opendaylight.controller.sal.utils,
-              org.opendaylight.yangtools.yang.common,
-              org.opendaylight.controller.sal.connector.api,
-              org.opendaylight.controller.sal.connector.remoterpc.api;version="[0.4,1)",
-              org.opendaylight.controller.sal.connector.remoterpc.impl;version="[0.4,1)",
-              org.opendaylight.controller.sal.connector.remoterpc.dto,
-              org.opendaylight.controller.sal.connector.remoterpc.util,
-              org.osgi.framework,
-              com.google.common.base,
-              org.opendaylight.yangtools.yang.data.api,
-              !org.codehaus.enunciate.jaxrs
-
-            </Import-Package>
-            <Web-ContextPath>/controller/nb/v2/zmqnb</Web-ContextPath>
-            <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
-          </instructions>
-          <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <dependencies>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>containermanager</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>commons.northbound</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.tests</groupId>
-      <artifactId>sal-remoterpc-connector-test-provider</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.tests</groupId>
-      <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-remoterpc-connector</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-      <version>5.0.0</version>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-    </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>remoterpc-routingtable.implementation</artifactId>
-          <version>0.4.1-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>com.google.guava</groupId>
-          <artifactId>guava</artifactId>
-      </dependency>
-  </dependencies>
-
- </project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqrouter/rest/Router.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqrouter/rest/Router.java
deleted file mode 100644 (file)
index e97be52..0000000
+++ /dev/null
@@ -1,273 +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.tests.zmqrouter.rest;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-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.impl.RoutingTableImpl;
-import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
-import org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer;
-import org.opendaylight.controller.sample.zeromq.provider.ExampleProvider;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import java.io.Serializable;
-import java.net.URI;
-import java.util.Set;
-
-@Path("router")
-public class Router {
-  private Logger _logger = LoggerFactory.getLogger(Router.class);
-  private final URI namespace = URI.create("http://cisco.com/example");
-  private final QName QNAME = new QName(namespace, "heartbeat");
-
-
-  @GET
-  @Path("/hello")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String hello() {
-    return "Hello";
-  }
-
-  @GET
-  @Path("/announce")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String announce() {
-    _logger.info("Announce request received");
-
-    BundleContext ctx = getBundleContext();
-    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
-    if (providerRef == null) {
-      _logger.debug("Could not get provider reference");
-      return "Could not get provider reference";
-    }
-
-    ExampleProvider provider = (ExampleProvider) ctx.getService(providerRef);
-    if (provider == null) {
-      _logger.info("Could not get provider service");
-      return "Could not get provider service";
-    }
-
-    provider.announce(QNAME);
-    return "Announcement sent ";
-
-  }
-
-  @GET
-  @Path("/rpc")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String invokeRpc() throws Exception {
-    _logger.info("Invoking RPC");
-
-    ExampleConsumer consumer = getConsumer();
-    RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, consumer.getValidCompositeNodeWithOneSimpleChild());
-    _logger.info("Result [{}]", result.isSuccessful());
-
-    return stringify(result);
-  }
-
-  @GET
-  @Path("/rpc-success")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String invokeRpcSuccess() throws Exception {
-    ExampleConsumer consumer = getConsumer();
-    RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, consumer.getValidCompositeNodeWithFourSimpleChildren()); //TODO: Change this
-    _logger.info("Result [{}]", result.isSuccessful());
-
-    return stringify(result);
-  }
-
-  @GET
-  @Path("/rpc-failure")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String invokeRpcFailure() throws Exception {
-    ExampleConsumer consumer = getConsumer();
-    //RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, consumer.getInvalidCompositeNodeCompositeChild()); //TODO: Change this
-    RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, null); //TODO: Change this
-    _logger.info("Result [{}]", result.isSuccessful());
-
-    return stringify(result);
-  }
-
-  @GET
-  @Path("/routingtable")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String invokeRoutingTable() {
-    _logger.info("Invoking adding an entry in routing table");
-
-    BundleContext ctx = getBundleContext();
-    ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
-    if (routingTableServiceReference == null) {
-      _logger.debug("Could not get routing table impl reference");
-      return "Could not get routingtable referen ";
-    }
-    RoutingTableImpl routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
-    if (routingTable == null) {
-      _logger.info("Could not get routing table service");
-      return "Could not get routing table service";
-    }
-
-
-    RoutingIdentifierImpl rii = new RoutingIdentifierImpl();
-    try {
-      routingTable.addGlobalRoute(rii.toString(), "172.27.12.1:5000");
-    } catch (RoutingTableException e) {
-      _logger.error("error in adding routing identifier" + e.getMessage());
-
-    } catch (SystemException e) {
-      _logger.error("error in adding routing identifier" + e.getMessage());
-    }
-
-    String result = routingTable.dumpRoutingTableCache();
-
-
-
-
-    _logger.info("Result [{}] routes added for route" + rii + result);
-
-    return result;
-  }
-
-  @GET
-  @Path("/routingtabledelete")
-  @Produces(MediaType.TEXT_PLAIN)
-  public String invokeDeleteRoutingTable() {
-    _logger.info("Invoking adding an entry in routing table");
-
-    BundleContext ctx = getBundleContext();
-    ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
-    if (routingTableServiceReference == null) {
-      _logger.debug("Could not get routing table impl reference");
-      return "Could not get routingtable referen ";
-    }
-    RoutingTable routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
-    if (routingTable == null) {
-      _logger.info("Could not get routing table service");
-      return "Could not get routing table service";
-    }
-
-
-    RoutingIdentifierImpl rii = new RoutingIdentifierImpl();
-    try {
-      routingTable.removeGlobalRoute(rii.toString());
-    } catch (RoutingTableException e) {
-      _logger.error("error in adding routing identifier" + e.getMessage());
-
-    } catch (SystemException e) {
-      _logger.error("error in adding routing identifier" + e.getMessage());
-    }
-
-    Set<String> routes = routingTable.getRoutes(rii.toString());
-
-    StringBuilder stringBuilder = new StringBuilder();
-    if (routes != null) {
-      for (String route : routes) {
-        stringBuilder.append(route);
-      }
-    } else {
-      stringBuilder.append(" successfully");
-    }
-
-    _logger.info("Result [{}] routes removed for route" + rii + stringBuilder.toString());
-
-    return stringBuilder.toString();
-  }
-
-  private String stringify(RpcResult<CompositeNode> result) {
-    CompositeNode node = result.getResult();
-    StringBuilder builder = new StringBuilder("result:").append(XmlUtils.compositeNodeToXml(node)).append("\n")
-        .append("error:").append(result.getErrors()).append("\n");
-
-    return builder.toString();
-  }
-
-  private BundleContext getBundleContext() {
-    ClassLoader tlcl = Thread.currentThread().getContextClassLoader();
-    Bundle bundle = null;
-
-    if (tlcl instanceof BundleReference) {
-      bundle = ((BundleReference) tlcl).getBundle();
-    } else {
-      _logger.info("Unable to determine the bundle context based on " +
-          "thread context classloader.");
-      bundle = FrameworkUtil.getBundle(this.getClass());
-    }
-    return (bundle == null ? null : bundle.getBundleContext());
-  }
-
-  private ExampleConsumer getConsumer() {
-    BundleContext ctx = getBundleContext();
-    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
-    if (consumerRef == null) {
-      _logger.debug("Could not get consumer reference");
-      throw new NullPointerException("Could not get consumer reference");
-    }
-    ExampleConsumer consumer = (ExampleConsumer) ctx.getService(consumerRef);
-    if (consumer == null) {
-      _logger.info("Could not get consumer service");
-      throw new NullPointerException("Could not get consumer service");
-    }
-    return consumer;
-  }
-
-  class RoutingIdentifierImpl implements RpcRouter.RouteIdentifier, Serializable {
-
-    private final URI namespace = URI.create("http://cisco.com/example");
-    private final QName QNAME = new QName(namespace, "global");
-    private final QName instance = new QName(URI.create("127.0.0.1"), "local");
-
-    @Override
-    public QName getContext() {
-      return QNAME;
-    }
-
-    @Override
-    public QName getType() {
-      return QNAME;
-    }
-
-    @Override
-    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
-      return InstanceIdentifier.of(instance);
-    }
-
-      @Override
-      public boolean equals(Object o) {
-          if (this == o) return true;
-          if (o == null || getClass() != o.getClass()) return false;
-
-          RoutingIdentifierImpl that = (RoutingIdentifierImpl) o;
-
-          if (!QNAME.equals(that.QNAME)) return false;
-          if (!instance.equals(that.instance)) return false;
-          if (!namespace.equals(that.namespace)) return false;
-
-          return true;
-      }
-
-      @Override
-      public int hashCode() {
-          int result = namespace.hashCode();
-          result = 31 * result + QNAME.hashCode();
-          result = 31 * result + instance.hashCode();
-          return result;
-      }
-  }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml
deleted file mode 100644 (file)
index 5bd2139..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
-        version="3.0">
-  <servlet>
-    <servlet-name>JAXRSZmq</servlet-name>
-    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
-    <init-param>
-      <param-name>javax.ws.rs.Application</param-name>
-      <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
-
-  <servlet-mapping>
-    <servlet-name>JAXRSZmq</servlet-name>
-    <url-pattern>/*</url-pattern>
-  </servlet-mapping>
-
-
-
-        <security-constraint>
-          <web-resource-collection>
-            <web-resource-name>NB api</web-resource-name>
-            <url-pattern>/*</url-pattern>
-            <http-method>POST</http-method>
-            <http-method>GET</http-method>
-            <http-method>PUT</http-method>
-            <http-method>PATCH</http-method>
-            <http-method>DELETE</http-method>
-            <http-method>HEAD</http-method>
-          </web-resource-collection>
-          <auth-constraint>
-            <role-name>System-Admin</role-name>
-            <role-name>Network-Admin</role-name>
-            <role-name>Network-Operator</role-name>
-            <role-name>Container-User</role-name>
-          </auth-constraint>
-        </security-constraint>
-
-        <security-role>
-                <role-name>System-Admin</role-name>
-        </security-role>
-        <security-role>
-                <role-name>Network-Admin</role-name>
-        </security-role>
-        <security-role>
-                <role-name>Network-Operator</role-name>
-        </security-role>
-        <security-role>
-                <role-name>Container-User</role-name>
-        </security-role>
-
-        <login-config>
-                <auth-method>BASIC</auth-method>
-                <realm-name>opendaylight</realm-name>
-        </login-config>
-</web-app>
index c2d245badbca059dfbff3d7bdbf2b50ba30efa1d..b760263967864947268a3cc34df07e0a309e581b 100644 (file)
@@ -17,7 +17,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>sal-core-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>com.google.code.gson</groupId>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-util</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-remote</artifactId>
@@ -62,7 +65,6 @@
     <dependency>
       <groupId>org.jboss.resteasy</groupId>
       <artifactId>jaxrs-api</artifactId>
-      <version>3.0.4.Final</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
@@ -80,7 +82,6 @@
     <dependency>
       <groupId>org.glassfish.jersey.test-framework.providers</groupId>
       <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
-      <version>2.4</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <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>
index 1e5bfbd6b93e7fe540931a0f6f828625a4a963c1..85b4b2dee071aff3be08fb82b11690a8793d7014 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.controller.sal.rest.impl;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.common.base.Preconditions;
+import com.google.gson.stream.JsonWriter;
+
 import java.io.IOException;
 import java.net.URI;
 import java.util.Collections;
@@ -29,6 +32,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -48,22 +52,19 @@ import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinit
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-import com.google.gson.stream.JsonWriter;
-
 class JsonMapper {
+    private static final Logger LOG = LoggerFactory.getLogger(JsonMapper.class);
+    private final MountInstance mountPoint;
 
-    private final Set<LeafListSchemaNode> foundLeafLists = new HashSet<>();
-    private final Set<ListSchemaNode> foundLists = new HashSet<>();
-    private MountInstance mountPoint;
-    private final Logger logger = LoggerFactory.getLogger(JsonMapper.class);
+    public JsonMapper(final MountInstance mountPoint) {
+        this.mountPoint = mountPoint;
+    }
 
-    public void write(final JsonWriter writer, final CompositeNode data, final DataNodeContainer schema, final MountInstance mountPoint)
+    public void write(final JsonWriter writer, final CompositeNode data, final DataNodeContainer schema)
             throws IOException {
         Preconditions.checkNotNull(writer);
         Preconditions.checkNotNull(data);
         Preconditions.checkNotNull(schema);
-        this.mountPoint = mountPoint;
 
         writer.beginObject();
 
@@ -77,88 +78,112 @@ class JsonMapper {
         }
 
         writer.endObject();
-
-        foundLeafLists.clear();
-        foundLists.clear();
     }
 
     private void writeChildrenOfParent(final JsonWriter writer, final CompositeNode parent, final DataNodeContainer parentSchema)
             throws IOException {
         checkNotNull(parent);
 
+        final Set<QName> foundLists = new HashSet<>();
+
         Set<DataSchemaNode> parentSchemaChildNodes = parentSchema == null ?
-                                   Collections.<DataSchemaNode>emptySet() : parentSchema.getChildNodes();
+                Collections.<DataSchemaNode>emptySet() : parentSchema.getChildNodes();
 
 
-        for (Node<?> child : parent.getValue()) {
-            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
+                for (Node<?> child : parent.getValue()) {
+                    DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
 
-            if (childSchema == null) {
-                // Node may not conform to schema or allows "anyxml" - we'll process it.
+                    if (childSchema == null) {
+                        // Node may not conform to schema or allows "anyxml" - we'll process it.
 
-                logger.debug( "No schema found for data node \"" + child.getNodeType() );
+                        LOG.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);
-            } else if (childSchema instanceof ListSchemaNode) {
-                if (!foundLists.contains(childSchema)) {
-                    Preconditions.checkState(child instanceof CompositeNode,
-                            "Data representation of List should be CompositeNode - " + child.getNodeType());
-                    foundLists.add((ListSchemaNode) childSchema);
-                    writeList(writer, parent, (CompositeNode) child, (ListSchemaNode) childSchema);
-                }
-            } else if (childSchema instanceof LeafListSchemaNode) {
-                if (!foundLeafLists.contains(childSchema)) {
-                    Preconditions.checkState(child instanceof SimpleNode<?>,
-                            "Data representation of LeafList should be SimpleNode - " + child.getNodeType());
-                    foundLeafLists.add((LeafListSchemaNode) childSchema);
-                    writeLeafList(writer, parent, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
+                        if( !foundLists.contains( child.getNodeType() ) ) {
+                            handleNoSchemaFound( writer, child, parent );
+
+                            // Since we don't have a schema, we don't know which nodes are supposed to be
+                            // lists so treat every one as a potential list to avoid outputting duplicates.
+
+                            foundLists.add( child.getNodeType() );
+                        }
+                    }
+                    else if (childSchema instanceof ContainerSchemaNode) {
+                        Preconditions.checkState(child instanceof CompositeNode,
+                                "Data representation of Container should be CompositeNode - %s", child.getNodeType());
+                        writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
+                    } else if (childSchema instanceof ListSchemaNode) {
+                        if (!foundLists.contains( child.getNodeType() ) ) {
+                            Preconditions.checkState(child instanceof CompositeNode,
+                                    "Data representation of List should be CompositeNode - %s", child.getNodeType());
+                            foundLists.add( child.getNodeType() );
+                            writeList(writer, parent, (CompositeNode) child, (ListSchemaNode) childSchema);
+                        }
+                    } else if (childSchema instanceof LeafListSchemaNode) {
+                        if (!foundLists.contains( child.getNodeType() ) ) {
+                            Preconditions.checkState(child instanceof SimpleNode<?>,
+                                    "Data representation of LeafList should be SimpleNode - %s", child.getNodeType());
+                            foundLists.add( child.getNodeType() );
+                            writeLeafList(writer, parent, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
+                        }
+                    } else if (childSchema instanceof LeafSchemaNode) {
+                        Preconditions.checkState(child instanceof SimpleNode<?>,
+                                "Data representation of LeafList should be SimpleNode - %s", child.getNodeType());
+                        writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
+                    } else if (childSchema instanceof AnyXmlSchemaNode) {
+                        if( child instanceof CompositeNode ) {
+                            writeContainer(writer, (CompositeNode) child, null);
+                        }
+                        else {
+                            handleNoSchemaFound( writer, child, parent );
+                        }
+                    } else {
+                        throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, "
+                                + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet.");
+                    }
                 }
-            } else if (childSchema instanceof LeafSchemaNode) {
-                Preconditions.checkState(child instanceof SimpleNode<?>,
-                        "Data representation of LeafList should be SimpleNode - " + child.getNodeType());
-                writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
-            } else {
-                throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, "
-                        + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet.");
-            }
-        }
+    }
 
-        for (Node<?> child : parent.getValue()) {
-            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
-            if (childSchema instanceof LeafListSchemaNode) {
-                foundLeafLists.remove(childSchema);
-            } else if (childSchema instanceof ListSchemaNode) {
-                foundLists.remove(childSchema);
-            }
-        }
+    private static void writeValue(final JsonWriter writer, final Object value) throws IOException {
+        writer.value(value == null ? "" : String.valueOf(value));
     }
 
     private void handleNoSchemaFound( final JsonWriter writer, final Node<?> node,
-                                      final CompositeNode parent ) throws IOException {
+            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 ) );
+            List<SimpleNode<?>> nodeLeafList = parent.getSimpleNodesByName( node.getNodeType() );
+            if( nodeLeafList.size() == 1 ) {
+                writeName( node, null, writer );
+                writeValue( writer, node.getValue() );
+            }
+            else { // more than 1, write as a json array
+                writeName( node, null, writer );
+                writer.beginArray();
+                for( SimpleNode<?> leafNode: nodeLeafList ) {
+                    writeValue( writer, leafNode.getValue() );
+                }
+
+                writer.endArray();
             }
         } else { // CompositeNode
             Preconditions.checkState( node instanceof CompositeNode,
-                    "Data representation of Container should be CompositeNode - " + node.getNodeType() );
+                    "Data representation of Container should be CompositeNode - %s", node.getNodeType());
 
-            writeContainer( writer, (CompositeNode) node, null );
+            List<CompositeNode> nodeList = parent.getCompositesByName( node.getNodeType() );
+            if( nodeList.size() == 1 ) {
+                writeContainer( writer, (CompositeNode) node, null );
+            }
+            else { // more than 1, write as a json array
+                writeList( writer, parent, (CompositeNode) node, null );
+            }
         }
     }
 
-    private DataSchemaNode findFirstSchemaForNode(final Node<?> node, final Set<DataSchemaNode> dataSchemaNode) {
+    private static DataSchemaNode findFirstSchemaForNode(final Node<?> node, final Set<DataSchemaNode> dataSchemaNode) {
         for (DataSchemaNode dsn : dataSchemaNode) {
             if (node.getNodeType().equals(dsn.getQName())) {
                 return dsn;
-            } else if (dsn instanceof ChoiceNode) {
+            }
+            if (dsn instanceof ChoiceNode) {
                 for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
                     DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
                     if (foundDsn != null) {
@@ -221,8 +246,8 @@ class JsonMapper {
         TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
 
         if (node.getValue() == null && !(baseType instanceof EmptyTypeDefinition)) {
-            logger.debug("While generationg JSON output null value was found for type "
-                    + baseType.getClass().getSimpleName() + ".");
+            LOG.debug("While generationg JSON output null value was found for type {}.",
+                    baseType.getClass().getSimpleName());
         }
 
         if (baseType instanceof IdentityrefTypeDefinition) {
@@ -267,25 +292,24 @@ class JsonMapper {
         }
     }
 
-    private void writeIdentityValuesDTOToJson(final JsonWriter writer, final IdentityValuesDTO valueDTO) throws IOException {
+    private static void writeIdentityValuesDTOToJson(final JsonWriter writer, final IdentityValuesDTO valueDTO) throws IOException {
         StringBuilder result = new StringBuilder();
         for (IdentityValue identityValue : valueDTO.getValuesWithNamespaces()) {
-            result.append("/");
+            result.append('/');
 
             writeModuleNameAndIdentifier(result, identityValue);
             if (identityValue.getPredicates() != null && !identityValue.getPredicates().isEmpty()) {
                 for (Predicate predicate : identityValue.getPredicates()) {
                     IdentityValue identityValuePredicate = predicate.getName();
-                    result.append("[");
+                    result.append('[');
                     if (identityValuePredicate == null) {
-                        result.append(".");
+                        result.append('.');
                     } else {
                         writeModuleNameAndIdentifier(result, identityValuePredicate);
                     }
                     result.append("='");
                     result.append(predicate.getValue());
-                    result.append("'");
-                    result.append("]");
+                    result.append("']");
                 }
             }
         }
@@ -293,21 +317,22 @@ class JsonMapper {
         writer.value(result.toString());
     }
 
-    private void writeModuleNameAndIdentifier(final StringBuilder result, final IdentityValue identityValue) {
+    private static void writeModuleNameAndIdentifier(final StringBuilder result, final IdentityValue identityValue) {
         String moduleName = ControllerContext.getInstance().findModuleNameByNamespace(
                 URI.create(identityValue.getNamespace()));
         if (moduleName != null && !moduleName.isEmpty()) {
             result.append(moduleName);
-            result.append(":");
+            result.append(':');
         }
         result.append(identityValue.getValue());
     }
 
-    private void writeStringRepresentation(final JsonWriter writer, final SimpleNode<?> node, final TypeDefinition<?> baseType,
+    private static 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());
+        LOG.debug("Value of {}:{} is not instance of {} but is {}",
+                baseType.getQName().getNamespace(), baseType.getQName().getLocalName(),
+                requiredType.getClass(), node.getValue().getClass());
         if (value == null) {
             writer.value("");
         } else {
@@ -334,7 +359,7 @@ class JsonMapper {
             if (moduleName != null) {
                 nameForOutput = moduleName.toString();
             } else {
-                logger.info("Module '{}' was not found in schema from mount point", schema.getQName());
+                LOG.info("Module '{}' was not found in schema from mount point", schema.getQName());
             }
         }
         writer.name(nameForOutput);
index 1f7b061e921cd057d13ece0002e998973fb66db2..e94554061800cb8ae918dc59a598fea980cac972 100644 (file)
@@ -7,9 +7,17 @@
  */
 package org.opendaylight.controller.sal.rest.impl;
 
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterators;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URI;
+import java.util.Iterator;
 import java.util.Map.Entry;
 import java.util.Set;
 
@@ -18,21 +26,22 @@ import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.JsonPrimitive;
+final class JsonReader {
+    private static final Logger LOG = LoggerFactory.getLogger(JsonReader.class);
+    private static final Splitter COLON_SPLITTER = Splitter.on(':');
+
+    private JsonReader() {
 
-class JsonReader {
+    }
 
-    public CompositeNodeWrapper read(InputStream entityStream) throws UnsupportedFormatException {
+    public static CompositeNodeWrapper read(final InputStream entityStream) throws UnsupportedFormatException {
         JsonParser parser = new JsonParser();
 
         JsonElement rootElement = parser.parse(new InputStreamReader(entityStream));
-        if( rootElement.isJsonNull() )
-        {
+        if (rootElement.isJsonNull()) {
             //no content, so return null to indicate no input
             return null;
         }
@@ -44,29 +53,31 @@ class JsonReader {
         Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
         if (entrySetsOfRootJsonObject.size() != 1) {
             throw new UnsupportedFormatException("Json Object should contain one element");
-        } else {
-            Entry<String, JsonElement> childEntry = Lists.newArrayList(entrySetsOfRootJsonObject).get(0);
-            String firstElementName = childEntry.getKey();
-            JsonElement firstElementType = childEntry.getValue();
-            if (firstElementType.isJsonObject()) { // container in yang
-                return createStructureWithRoot(firstElementName, firstElementType.getAsJsonObject());
-            }
-            if (firstElementType.isJsonArray()) { // list in yang
-                if (firstElementType.getAsJsonArray().size() == 1) {
-                    JsonElement firstElementInArray = firstElementType.getAsJsonArray().get(0);
-                    if (firstElementInArray.isJsonObject()) {
-                        return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
-                    }
-                    throw new UnsupportedFormatException(
-                            "Array as the first element in Json Object can have only Object element");
+        }
+
+        Entry<String, JsonElement> childEntry = entrySetsOfRootJsonObject.iterator().next();
+        String firstElementName = childEntry.getKey();
+        JsonElement firstElementType = childEntry.getValue();
+        if (firstElementType.isJsonObject()) {
+            // container in yang
+            return createStructureWithRoot(firstElementName, firstElementType.getAsJsonObject());
+        }
+        if (firstElementType.isJsonArray()) {
+            // list in yang
+            if (firstElementType.getAsJsonArray().size() == 1) {
+                JsonElement firstElementInArray = firstElementType.getAsJsonArray().get(0);
+                if (firstElementInArray.isJsonObject()) {
+                    return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
                 }
+                throw new UnsupportedFormatException(
+                        "Array as the first element in Json Object can have only Object element");
             }
-            throw new UnsupportedFormatException(
-                    "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
         }
+        throw new UnsupportedFormatException(
+                "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
     }
 
-    private CompositeNodeWrapper createStructureWithRoot(String rootObjectName, JsonObject rootObject) {
+    private static CompositeNodeWrapper createStructureWithRoot(final String rootObjectName, final JsonObject rootObject) {
         CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFor(rootObjectName),
                 getLocalNameFor(rootObjectName));
         for (Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
@@ -75,7 +86,7 @@ class JsonReader {
         return firstNode;
     }
 
-    private void addChildToParent(String childName, JsonElement childType, CompositeNodeWrapper parent) {
+    private static void addChildToParent(final String childName, final JsonElement childType, final CompositeNodeWrapper parent) {
         if (childType.isJsonObject()) {
             CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName));
             parent.addValue(child);
@@ -85,7 +96,6 @@ class JsonReader {
         } else if (childType.isJsonArray()) {
             if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) {
                 parent.addValue(new EmptyNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName)));
-
             } else {
                 for (JsonElement childOfChildType : childType.getAsJsonArray()) {
                     addChildToParent(childName, childOfChildType, parent);
@@ -96,35 +106,42 @@ class JsonReader {
             String value = childPrimitive.getAsString().trim();
             parent.addValue(new SimpleNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName),
                     resolveValueOfElement(value)));
+        } else {
+            LOG.debug("Ignoring unhandled child type {}", childType);
         }
     }
 
-    private URI getNamespaceFor(String jsonElementName) {
-        String[] moduleNameAndLocalName = jsonElementName.split(":");
-        // it is not "moduleName:localName"
-        if (moduleNameAndLocalName.length != 2) {
-            return null;
+    private static URI getNamespaceFor(final String jsonElementName) {
+        final Iterator<String> it = COLON_SPLITTER.split(jsonElementName).iterator();
+
+        // The string needs to me in form "moduleName:localName"
+        if (it.hasNext()) {
+            final String maybeURI = it.next();
+            if (Iterators.size(it) == 1) {
+                return URI.create(maybeURI);
+            }
         }
-        return URI.create(moduleNameAndLocalName[0]);
+
+        return null;
     }
 
-    private String getLocalNameFor(String jsonElementName) {
-        String[] moduleNameAndLocalName = jsonElementName.split(":");
-        // it is not "moduleName:localName"
-        if (moduleNameAndLocalName.length != 2) {
-            return jsonElementName;
-        }
-        return moduleNameAndLocalName[1];
+    private static String getLocalNameFor(final String jsonElementName) {
+        final Iterator<String> it = COLON_SPLITTER.split(jsonElementName).iterator();
+
+        // The string needs to me in form "moduleName:localName"
+        final String ret = Iterators.get(it, 1, null);
+        return ret != null && !it.hasNext() ? ret : jsonElementName;
     }
 
-    private Object resolveValueOfElement(String value) {
+    private static Object resolveValueOfElement(final String value) {
         // it could be instance-identifier Built-In Type
-        if (value.startsWith("/")) {
+        if (!value.isEmpty() && value.charAt(0) == '/') {
             IdentityValuesDTO resolvedValue = RestUtil.asInstanceIdentifier(value, new PrefixMapingFromJson());
             if (resolvedValue != null) {
                 return resolvedValue;
             }
         }
+
         // it could be identityref Built-In Type
         URI namespace = getNamespaceFor(value);
         if (namespace != null) {
index 856e09fabd21a1083cbe716890ba22ae3b2d5bc6..9e6966540534c9c79d2a120f89c35ebf603d956d 100644 (file)
@@ -30,29 +30,28 @@ import org.slf4j.LoggerFactory;
 
 @Provider
 @Consumes({ Draft02.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.OPERATION + RestconfService.JSON,
-        MediaType.APPLICATION_JSON })
+    MediaType.APPLICATION_JSON })
 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) {
+    public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return true;
     }
 
     @Override
-    public CompositeNode readFrom(Class<CompositeNode> type, Type genericType, Annotation[] annotations,
-            MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
-            throws IOException, WebApplicationException {
-        JsonReader jsonReader = new JsonReader();
+    public CompositeNode readFrom(final Class<CompositeNode> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream)
+                    throws IOException, WebApplicationException {
         try {
-            return jsonReader.read(entityStream);
+            return JsonReader.read(entityStream);
         } catch (Exception e) {
-            LOG.debug( "Error parsing json input", e );
+            LOG.debug( "Error parsing json input", e);
             throw new RestconfDocumentedException(
-                            "Error parsing input: " + e.getMessage(),
-                            ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE );
+                    "Error parsing input: " + e.getMessage(),
+                    ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
         }
     }
 
index 290d976b2857c493e7c638592e2715e963a03277..cd263d3c55b0a56ce40feca32690749bd489ed6e 100644 (file)
@@ -21,11 +21,13 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
 public final class RestUtil {
 
+    // FIXME: BUG-1275: this is code duplicates data.impl.codec
+
     public static final String SQUOTE = "'";
     public static final String DQUOTE = "\"";
     private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
 
-    public final static TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
+    public final static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
         TypeDefinition<?> superType = type;
         while (superType.getBaseType() != null) {
             superType = superType.getBaseType();
@@ -33,7 +35,7 @@ public final class RestUtil {
         return superType;
     }
 
-    public static IdentityValuesDTO asInstanceIdentifier(String value, PrefixesMaping prefixMap) {
+    public static IdentityValuesDTO asInstanceIdentifier(final String value, final PrefixesMaping prefixMap) {
         String valueTrimmed = value.trim();
         if (!valueTrimmed.startsWith("/")) {
             return null;
@@ -63,12 +65,12 @@ public final class RestUtil {
         return identityValuesDTO.getValuesWithNamespaces().isEmpty() ? null : identityValuesDTO;
     }
 
-    private static String getIdAndPrefixAsStr(String pathPart) {
+    private static String getIdAndPrefixAsStr(final String pathPart) {
         int predicateStartIndex = pathPart.indexOf("[");
         return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
     }
 
-    private static IdentityValue toIdentity(String xPathPart, PrefixesMaping prefixMap) {
+    private static IdentityValue toIdentity(final String xPathPart, final PrefixesMaping prefixMap) {
         String xPathPartTrimmed = xPathPart.trim();
         if (xPathPartTrimmed.isEmpty()) {
             return null;
@@ -87,7 +89,7 @@ public final class RestUtil {
         return new IdentityValue(namespace, identifier, namespace.equals(prefix) ? null : prefix);
     }
 
-    private static List<Predicate> toPredicates(String predicatesStr, PrefixesMaping prefixMap) {
+    private static List<Predicate> toPredicates(final String predicatesStr, final PrefixesMaping prefixMap) {
         List<Predicate> result = new ArrayList<>();
         List<String> predicates = new ArrayList<>();
         Matcher matcher = PREDICATE_PATTERN.matcher(predicatesStr);
@@ -116,7 +118,7 @@ public final class RestUtil {
         return result;
     }
 
-    private static String toPredicateValue(String predicatedValue) {
+    private static String toPredicateValue(final String predicatedValue) {
         String predicatedValueTrimmed = predicatedValue.trim();
         if ((predicatedValueTrimmed.startsWith(DQUOTE) || predicatedValueTrimmed.startsWith(SQUOTE))
                 && (predicatedValueTrimmed.endsWith(DQUOTE) || predicatedValueTrimmed.endsWith(SQUOTE))) {
@@ -132,12 +134,12 @@ public final class RestUtil {
     public static class PrefixMapingFromXml implements PrefixesMaping {
         StartElement startElement = null;
 
-        public PrefixMapingFromXml(StartElement startElement) {
+        public PrefixMapingFromXml(final StartElement startElement) {
             this.startElement = startElement;
         }
 
         @Override
-        public String getNamespace(String prefix) {
+        public String getNamespace(final String prefix) {
             return startElement.getNamespaceContext().getNamespaceURI(prefix);
         }
     }
@@ -145,7 +147,7 @@ public final class RestUtil {
     public static class PrefixMapingFromJson implements PrefixesMaping {
 
         @Override
-        public String getNamespace(String prefix) {
+        public String getNamespace(final String prefix) {
             return prefix;
         }
     }
index 5f6909cea8e3e15d2b7887fe975d2d3e613163b5..0854ca71673465e76e7659bfa9479afc3fb1962f 100644 (file)
@@ -17,6 +17,11 @@ import static org.opendaylight.controller.sal.rest.api.Draft02.RestConfModule.ER
 import static org.opendaylight.controller.sal.rest.api.Draft02.RestConfModule.ERROR_TYPE_QNAME;
 import static org.opendaylight.controller.sal.rest.api.Draft02.RestConfModule.NAMESPACE;
 
+import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.gson.stream.JsonWriter;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
@@ -57,10 +62,6 @@ 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
@@ -139,20 +140,19 @@ public class RestconfDocumentedExceptionMapper implements ExceptionMapper<Restco
     private Object toJsonResponseBody( final ImmutableCompositeNode errorsNode,
             final DataNodeContainer errorsSchemaNode ) {
 
-        JsonMapper jsonMapper = new JsonMapper();
+        JsonMapper jsonMapper = new JsonMapper(null);
 
         Object responseBody = null;
         try {
             ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-            JsonWriter writer = new JsonWriter( new OutputStreamWriter( outStream, "UTF-8" ) );
+            JsonWriter writer = new JsonWriter(new OutputStreamWriter( outStream, Charsets.UTF_8));
             writer.setIndent( "    " );
 
-            jsonMapper.write( writer, errorsNode, errorsSchemaNode, null );
+            jsonMapper.write( writer, errorsNode, errorsSchemaNode);
             writer.flush();
 
             responseBody = outStream.toString( "UTF-8" );
-        }
-        catch( IOException e ) {
+        } catch( IOException e ) {
             LOG.error( "Error writing error response body", e );
         }
 
@@ -239,13 +239,11 @@ public class RestconfDocumentedExceptionMapper implements ExceptionMapper<Restco
         try {
             doc = factory.newDocumentBuilder().parse(
                     new InputSource( new StringReader( errorInfoWithRoot ) ) );
-        }
-        catch( Exception e ) {
+        } 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() );
+            LOG.warn( "Error parsing restconf error-info, \"{}\", as XML", errorInfo, e);
             return null;
         }
 
index 422cf04cca82f7d0bf5d2f535df40a6f7688215e..1c2e9c5009897f741efaa6a1320665d7ba2a4b0a 100644 (file)
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.controller.sal.rest.impl;
 
+import com.google.common.base.Charsets;
+import com.google.gson.stream.JsonWriter;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -28,37 +31,35 @@ import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 
-import com.google.gson.stream.JsonWriter;
-
 @Provider
 @Produces({ Draft02.MediaTypes.API + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
-        Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
+    Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
 public enum StructuredDataToJsonProvider implements MessageBodyWriter<StructuredData> {
     INSTANCE;
 
     @Override
-    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return type.equals( StructuredData.class );
     }
 
     @Override
-    public long getSize(StructuredData t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    public long getSize(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return -1;
     }
 
     @Override
-    public void writeTo(StructuredData t, Class<?> type, Type genericType, Annotation[] annotations,
-            MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
-            throws IOException, WebApplicationException {
+    public void writeTo(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+                    throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
         if (data == null) {
             throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
         }
 
-        JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
+        JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8));
         writer.setIndent("    ");
-        JsonMapper jsonMapper = new JsonMapper();
-        jsonMapper.write(writer, data, (DataNodeContainer) t.getSchema(), t.getMountPoint());
+        JsonMapper jsonMapper = new JsonMapper(t.getMountPoint());
+        jsonMapper.write(writer, data, (DataNodeContainer) t.getSchema());
         writer.flush();
     }
 
index bcb3c422ff8dc0c33c8a44d27d20b63ec1e3852d..e5a56cf47566c6ca4d3d8e1113b817706b404d71 100644 (file)
@@ -21,6 +21,7 @@ import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.Provider;
 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.dom.DOMSource;
@@ -40,46 +41,68 @@ import org.w3c.dom.Document;
 
 @Provider
 @Produces({ Draft02.MediaTypes.API + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
-        Draft02.MediaTypes.OPERATION + RestconfService.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
+    Draft02.MediaTypes.OPERATION + RestconfService.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
 public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredData> {
     INSTANCE;
 
-    private final static Logger logger = LoggerFactory.getLogger(StructuredDataToXmlProvider.class);
+    private static final Logger LOG = LoggerFactory.getLogger(StructuredDataToXmlProvider.class);
+    private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
+    private static final ThreadLocal<Transformer> TRANSFORMER = new ThreadLocal<Transformer>() {
+        @Override
+        protected Transformer initialValue() {
+            final Transformer ret;
+            try {
+                ret = FACTORY.newTransformer();
+            } catch (TransformerConfigurationException e) {
+                LOG.error("Failed to instantiate XML transformer", e);
+                throw new IllegalStateException("XML encoding currently unavailable", e);
+            }
+
+            ret.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            ret.setOutputProperty(OutputKeys.METHOD, "xml");
+            ret.setOutputProperty(OutputKeys.INDENT, "yes");
+            ret.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            ret.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+            return ret;
+        }
+    };
 
     @Override
-    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return type.equals( StructuredData.class );
     }
 
     @Override
-    public long getSize(StructuredData t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+    public long getSize(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return -1;
     }
 
     @Override
-    public void writeTo(StructuredData t, Class<?> type, Type genericType, Annotation[] annotations,
-            MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
-            throws IOException, WebApplicationException {
+    public void writeTo(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations,
+            final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
+                    throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
         if (data == null) {
             throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
         }
 
-        XmlMapper xmlMapper = new XmlMapper();
-        Document domTree = xmlMapper.write(data, (DataNodeContainer) t.getSchema());
+        final Transformer trans;
+        try {
+            trans = TRANSFORMER.get();
+        } catch (RuntimeException e) {
+            throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT,
+                    ErrorTag.OPERATION_FAILED);
+        }
+
+        // FIXME: BUG-1281: eliminate the intermediate Document
+        final Document domTree = new XmlMapper().write(data, (DataNodeContainer) t.getSchema());
         try {
-            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");
-            transformer.transform(new DOMSource(domTree), new StreamResult(entityStream));
+            trans.transform(new DOMSource(domTree), new StreamResult(entityStream));
         } catch (TransformerException e) {
-            logger.error("Error during translation of Document to OutputStream", e);
-            throw new RestconfDocumentedException( e.getMessage(), ErrorType.TRANSPORT,
-                                                   ErrorTag.OPERATION_FAILED );
+            LOG.error("Error during translation of Document to OutputStream", e);
+            throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT,
+                    ErrorTag.OPERATION_FAILED);
         }
     }
 
index 171805a1798a872ff7f42b821f3201dced670b9f..1d6ca15f3c86986d97044b12de645343166226d6 100644 (file)
@@ -14,14 +14,13 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 import java.util.Stack;
-
 import javax.xml.stream.XMLEventReader;
 import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.Characters;
 import javax.xml.stream.events.StartElement;
 import javax.xml.stream.events.XMLEvent;
-
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
@@ -131,17 +130,9 @@ public class XmlReader {
     private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
         checkArgument(event != null, "XML Event cannot be NULL!");
         if (event.isStartElement()) {
-            if (eventReader.hasNext()) {
-                final XMLEvent innerEvent;
-                innerEvent = eventReader.peek();
-                if (innerEvent.isCharacters()) {
-                    final Characters chars = innerEvent.asCharacters();
-                    if (!chars.isWhiteSpace()) {
-                        return true;
-                    }
-                } else if (innerEvent.isEndElement()) {
-                    return true;
-                }
+            XMLEvent innerEvent = skipCommentsAndWhitespace();
+            if ( innerEvent != null && (innerEvent.isCharacters() || innerEvent.isEndElement())) {
+                return true;
             }
         }
         return false;
@@ -150,16 +141,8 @@ public class XmlReader {
     private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
         checkArgument(event != null, "XML Event cannot be NULL!");
         if (event.isStartElement()) {
-            if (eventReader.hasNext()) {
-                XMLEvent innerEvent;
-                innerEvent = eventReader.peek();
-                if (innerEvent.isCharacters()) {
-                    Characters chars = innerEvent.asCharacters();
-                    if (chars.isWhiteSpace()) {
-                        eventReader.nextEvent();
-                        innerEvent = eventReader.peek();
-                    }
-                }
+            XMLEvent innerEvent = skipCommentsAndWhitespace();
+            if( innerEvent != null ) {
                 if (innerEvent.isStartElement()) {
                     return true;
                 }
@@ -168,6 +151,26 @@ public class XmlReader {
         return false;
     }
 
+    private XMLEvent skipCommentsAndWhitespace() throws XMLStreamException {
+        while( eventReader.hasNext() ) {
+            XMLEvent event = eventReader.peek();
+            if( event.getEventType() == XMLStreamConstants.COMMENT ) {
+                eventReader.nextEvent();
+                continue;
+            }
+
+            if( event.isCharacters() ) {
+                Characters chars = event.asCharacters();
+                if( chars.isWhiteSpace() ) {
+                    eventReader.nextEvent();
+                    continue;
+                }
+            }
+            return event;
+        }
+        return null;
+    }
+
     private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
         checkArgument(startElement != null, "Start Element cannot be NULL!");
         return new CompositeNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
index 062d03a49f56e12ca6bb178fa39303b78fc059da..3d047dd07f53e47a4000a5de137fcc52e3affa75 100644 (file)
@@ -7,12 +7,13 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
 import java.util.concurrent.Future;
-
 import javax.ws.rs.core.Response.Status;
-
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
@@ -23,6 +24,7 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -160,20 +162,24 @@ public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNod
 
     public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete( final InstanceIdentifier path ) {
         this.checkPreconditions();
-
-        final DataModificationTransaction transaction = dataService.beginTransaction();
-        LOG.info( "Delete Configuration via Restconf: {}", path );
-        transaction.removeConfigurationData( path );
-        return transaction.commit();
+        return deleteDataAtTarget(path,dataService.beginTransaction());
     }
 
     public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
                                           final MountInstance mountPoint, final InstanceIdentifier path ) {
         this.checkPreconditions();
+        return deleteDataAtTarget(path,mountPoint.beginTransaction());
+    }
 
-        final DataModificationTransaction transaction = mountPoint.beginTransaction();
-        LOG.info( "Delete Configuration via Restconf: {}", path );
-        transaction.removeConfigurationData( path );
+    private Future<RpcResult<TransactionStatus>> deleteDataAtTarget(final InstanceIdentifier path,
+            final DataModificationTransaction transaction) {
+        LOG.info("Delete Configuration via Restconf: {}", path);
+        CompositeNode redDataAtPath = transaction.readConfigurationData(path);
+        if (redDataAtPath == null) {
+            return Futures.immediateFuture(Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
+                    Collections.<RpcError> emptyList()));
+        }
+        transaction.removeConfigurationData(path);
         return transaction.commit();
     }
 
index 96ad528a0dd3f9e0591b78b2be702e9b1d004c4c..69b975dab7e5ef15bb7e5ad4cf389ed55f0ef9c8 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.base.Preconditions;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -23,8 +25,6 @@ import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
-import com.google.common.base.Preconditions;
-
 public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, CompositeNode {
 
     private MutableCompositeNode compositeNode;
@@ -104,7 +104,7 @@ public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, C
                 name = new QName(namespace, localName);
             }
 
-            List<Node<?>> nodeValues = new ArrayList<>();
+            List<Node<?>> nodeValues = new ArrayList<>(values.size());
             for (NodeWrapper<?> nodeWrapper : values) {
                 nodeValues.add(nodeWrapper.unwrap());
             }
index b0916f4500d65d9dfb3291f4435e7c2aad31cc1b..85c8e595396e9463b8fb7bf93437510041306b09 100644 (file)
@@ -7,6 +7,18 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Iterables;
+
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLDecoder;
@@ -36,6 +48,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdent
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -54,19 +67,6 @@ import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
 public class ControllerContext implements SchemaContextListener {
     private final static Logger LOG = LoggerFactory.getLogger( ControllerContext.class );
 
@@ -82,6 +82,10 @@ public class ControllerContext implements SchemaContextListener {
 
     private final static String URI_ENCODING_CHAR_SET = "ISO-8859-1";
 
+    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
+
+    private static final Splitter COLON_SPLITTER = Splitter.on(':');
+
     private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
 
     private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
@@ -128,10 +132,8 @@ public class ControllerContext implements SchemaContextListener {
             final boolean toMountPointIdentifier ) {
         this.checkPreconditions();
 
-        Iterable<String> split = Splitter.on( "/" ).split( restconfInstance );
-        final ArrayList<String> encodedPathArgs = Lists.<String> newArrayList( split );
-        final List<String> pathArgs = this.urlPathArgsDecode( encodedPathArgs );
-        this.omitFirstAndLastEmptyString( pathArgs );
+        final List<String> pathArgs = urlPathArgsDecode( SLASH_SPLITTER.split( restconfInstance ) );
+        omitFirstAndLastEmptyString( pathArgs );
         if( pathArgs.isEmpty() ) {
             return null;
         }
@@ -157,7 +159,7 @@ public class ControllerContext implements SchemaContextListener {
         return iiWithSchemaNode;
     }
 
-    private List<String> omitFirstAndLastEmptyString( final List<String> list ) {
+    private static List<String> omitFirstAndLastEmptyString( final List<String> list ) {
         if( list.isEmpty() ) {
             return list;
         }
@@ -255,7 +257,7 @@ public class ControllerContext implements SchemaContextListener {
     public DataNodeContainer getDataNodeContainerFor( final InstanceIdentifier path ) {
         this.checkPreconditions();
 
-        final List<PathArgument> elements = path.getPath();
+        final Iterable<PathArgument> elements = path.getPathArguments();
         PathArgument head = elements.iterator().next();
         final QName startQName = head.getNodeType();
         final Module initialModule = globalSchema.findModuleByNamespaceAndRevision(
@@ -276,7 +278,7 @@ public class ControllerContext implements SchemaContextListener {
     public String toFullRestconfIdentifier( final InstanceIdentifier path ) {
         this.checkPreconditions();
 
-        final List<PathArgument> elements = path.getPath();
+        final Iterable<PathArgument> elements = path.getPathArguments();
         final StringBuilder builder = new StringBuilder();
         PathArgument head = elements.iterator().next();
         final QName startQName = head.getNodeType();
@@ -561,7 +563,7 @@ public class ControllerContext implements SchemaContextListener {
         }
 
         String head = strings.iterator().next();
-        final String nodeName = this.toNodeName( head );
+        final String nodeName = toNodeName( head );
         final String moduleName = ControllerContext.toModuleName( head );
 
         DataSchemaNode targetNode = null;
@@ -804,7 +806,8 @@ public class ControllerContext implements SchemaContextListener {
 
     public boolean isInstantiatedDataSchema( final DataSchemaNode node ) {
         return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode ||
-                node instanceof ContainerSchemaNode || node instanceof ListSchemaNode;
+                node instanceof ContainerSchemaNode || node instanceof ListSchemaNode ||
+                node instanceof AnyXmlSchemaNode;
     }
 
     private void addKeyValue( final HashMap<QName, Object> map, final DataSchemaNode node,
@@ -837,20 +840,20 @@ public class ControllerContext implements SchemaContextListener {
 
     private static String toModuleName( final String str ) {
         Preconditions.<String> checkNotNull( str );
-        if( str.contains( ":" ) ) {
-            final String[] args = str.split( ":" );
-            if( args.length == 2 ) {
-                return args[0];
+        if( str.indexOf( ':' ) != -1 ) {
+            final Iterable<String> args = COLON_SPLITTER.split( str );
+            if( Iterables.size( args ) == 2 ) {
+                return args.iterator().next();
             }
         }
         return null;
     }
 
-    private String toNodeName( final String str ) {
-        if( str.contains( ":" ) ) {
-            final String[] args = str.split( ":" );
-            if( args.length == 2 ) {
-                return args[1];
+    private static String toNodeName( final String str ) {
+        if( str.indexOf( ':' ) != -1 ) {
+            final Iterable<String> args = COLON_SPLITTER.split( str );
+            if( Iterables.size( args ) == 2 ) {
+                return Iterables.get( args, 1 );
             }
         }
         return str;
@@ -858,7 +861,7 @@ public class ControllerContext implements SchemaContextListener {
 
     private QName toQName( final String name ) {
         final String module = toModuleName( name );
-        final String node = this.toNodeName( name );
+        final String node = toNodeName( name );
         Set<Module> modules = globalSchema.getModules();
 
         final Comparator<Module> comparator = new Comparator<Module>() {
@@ -914,7 +917,7 @@ public class ControllerContext implements SchemaContextListener {
         }
     }
 
-    public List<String> urlPathArgsDecode( final List<String> strings ) {
+    public static List<String> urlPathArgsDecode( final Iterable<String> strings ) {
         try {
             List<String> decodedPathArgs = new ArrayList<String>();
             for( final String pathArg : strings ) {
@@ -996,7 +999,7 @@ public class ControllerContext implements SchemaContextListener {
             try {
                 builder.append( this.toUriString( keyValues.get( key ) ) );
             } catch( UnsupportedEncodingException e ) {
-                LOG.error( "Error parsing URI: " + keyValues.get( key ), e );
+                LOG.error( "Error parsing URI: {}", keyValues.get( key ), e );
                 return null;
             }
         }
index 934d4434c38a3e724279405da05198099eba2f70..f93a0aea70fa311a7dd0b6f8ba520d8153f03b89 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.base.Preconditions;
+
 import java.net.URI;
 import java.util.Collections;
 
@@ -15,8 +17,6 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
-import com.google.common.base.Preconditions;
-
 public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void> {
 
     private Node<?> unwrapped;
@@ -31,17 +31,17 @@ public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void>
         return composite;
     }
 
-    public void setComposite(boolean composite) {
+    public void setComposite(final boolean composite) {
         this.composite = composite;
     }
 
-    public EmptyNodeWrapper(URI namespace, String localName) {
+    public EmptyNodeWrapper(final URI namespace, final String localName) {
         this.localName = Preconditions.checkNotNull(localName);
         this.namespace = namespace;
     }
 
     @Override
-    public void setQname(QName name) {
+    public void setQname(final QName name) {
         Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
         this.name = name;
     }
@@ -68,7 +68,7 @@ public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void>
     }
 
     @Override
-    public void setNamespace(URI namespace) {
+    public void setNamespace(final URI namespace) {
         Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
         this.namespace = namespace;
     }
@@ -103,6 +103,7 @@ public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void>
     }
 
     @Override
+    @Deprecated
     public CompositeNode getParent() {
         return unwrap().getParent();
     }
@@ -118,7 +119,7 @@ public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void>
     }
 
     @Override
-    public Void setValue(Void value) {
+    public Void setValue(final Void value) {
         return null;
     }
 
index 265cc5db4536c96ecbf51bf4005ff4ced54e8c14..14b8282312d7accd1ba0c912a55178c72d3f317c 100644 (file)
@@ -47,7 +47,7 @@ public class RestCodec {
     private RestCodec() {
     }
 
-    public static final Codec<Object, Object> from(TypeDefinition<?> typeDefinition, MountInstance mountPoint) {
+    public static final Codec<Object, Object> from(final TypeDefinition<?> typeDefinition, final MountInstance mountPoint) {
         return new ObjectCodec(typeDefinition, mountPoint);
     }
 
@@ -62,7 +62,7 @@ public class RestCodec {
 
         private final TypeDefinition<?> type;
 
-        private ObjectCodec(TypeDefinition<?> typeDefinition, MountInstance mountPoint) {
+        private ObjectCodec(final TypeDefinition<?> typeDefinition, final MountInstance mountPoint) {
             type = RestUtil.resolveBaseTypeFrom(typeDefinition);
             if (type instanceof IdentityrefTypeDefinition) {
                 identityrefCodec = new IdentityrefCodecImpl(mountPoint);
@@ -78,7 +78,7 @@ public class RestCodec {
 
         @SuppressWarnings("unchecked")
         @Override
-        public Object deserialize(Object input) {
+        public Object deserialize(final Object input) {
             try {
                 if (type instanceof IdentityrefTypeDefinition) {
                     if (input instanceof IdentityValuesDTO) {
@@ -116,7 +116,7 @@ public class RestCodec {
                     }
                 }
             } catch (ClassCastException e) { // TODO remove this catch when
-                                             // everyone use codecs
+                // everyone use codecs
                 logger.error(
                         "ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input),
                         e);
@@ -126,7 +126,7 @@ public class RestCodec {
 
         @SuppressWarnings("unchecked")
         @Override
-        public Object serialize(Object input) {
+        public Object serialize(final Object input) {
             try {
                 if (type instanceof IdentityrefTypeDefinition) {
                     return identityrefCodec.serialize(input);
@@ -146,7 +146,7 @@ public class RestCodec {
                     }
                 }
             } catch (ClassCastException e) { // TODO remove this catch when
-                                             // everyone use codecs
+                // everyone use codecs
                 logger.error(
                         "ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input),
                         e);
@@ -162,17 +162,17 @@ public class RestCodec {
 
         private final MountInstance mountPoint;
 
-        public IdentityrefCodecImpl(MountInstance mountPoint) {
+        public IdentityrefCodecImpl(final MountInstance mountPoint) {
             this.mountPoint = mountPoint;
         }
 
         @Override
-        public IdentityValuesDTO serialize(QName data) {
+        public IdentityValuesDTO serialize(final QName data) {
             return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix(),null);
         }
 
         @Override
-        public QName deserialize(IdentityValuesDTO data) {
+        public QName deserialize(final IdentityValuesDTO data) {
             IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
             Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint);
             if (module == null) {
@@ -189,12 +189,12 @@ public class RestCodec {
     public static class LeafrefCodecImpl implements LeafrefCodec<String> {
 
         @Override
-        public String serialize(Object data) {
+        public String serialize(final Object data) {
             return String.valueOf(data);
         }
 
         @Override
-        public Object deserialize(String data) {
+        public Object deserialize(final String data) {
             return data;
         }
 
@@ -204,15 +204,14 @@ public class RestCodec {
         private final Logger logger = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class);
         private final MountInstance mountPoint;
 
-        public InstanceIdentifierCodecImpl(MountInstance mountPoint) {
+        public InstanceIdentifierCodecImpl(final MountInstance mountPoint) {
             this.mountPoint = mountPoint;
         }
 
         @Override
-        public IdentityValuesDTO serialize(InstanceIdentifier data) {
-            List<PathArgument> pathArguments = data.getPath();
+        public IdentityValuesDTO serialize(final InstanceIdentifier data) {
             IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
-            for (PathArgument pathArgument : pathArguments) {
+            for (PathArgument pathArgument : data.getPathArguments()) {
                 IdentityValue identityValue = qNameToIdentityValue(pathArgument.getNodeType());
                 if (pathArgument instanceof NodeIdentifierWithPredicates && identityValue != null) {
                     List<Predicate> predicates = keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument)
@@ -230,7 +229,7 @@ public class RestCodec {
         }
 
         @Override
-        public InstanceIdentifier deserialize(IdentityValuesDTO data) {
+        public InstanceIdentifier deserialize(final IdentityValuesDTO data) {
             List<PathArgument> result = new ArrayList<PathArgument>();
             IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
             Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint);
@@ -293,10 +292,10 @@ public class RestCodec {
                 }
             }
 
-            return result.isEmpty() ? null : new InstanceIdentifier(result);
+            return result.isEmpty() ? null : InstanceIdentifier.create(result);
         }
 
-        private List<Predicate> keyValuesToPredicateList(Map<QName, Object> keyValues) {
+        private List<Predicate> keyValuesToPredicateList(final Map<QName, Object> keyValues) {
             List<Predicate> result = new ArrayList<>();
             for (QName qName : keyValues.keySet()) {
                 Object value = keyValues.get(qName);
@@ -305,7 +304,7 @@ public class RestCodec {
             return result;
         }
 
-        private IdentityValue qNameToIdentityValue(QName qName) {
+        private IdentityValue qNameToIdentityValue(final QName qName) {
             if (qName != null) {
                 return new IdentityValue(qName.getNamespace().toString(), qName.getLocalName(), qName.getPrefix());
             }
@@ -313,7 +312,7 @@ public class RestCodec {
         }
     }
 
-    private static Module getModuleByNamespace(String namespace, MountInstance mountPoint) {
+    private static Module getModuleByNamespace(final String namespace, final MountInstance mountPoint) {
         URI validNamespace = resolveValidNamespace(namespace, mountPoint);
 
         Module module = null;
@@ -329,7 +328,7 @@ public class RestCodec {
         return module;
     }
 
-    private static URI resolveValidNamespace(String namespace, MountInstance mountPoint) {
+    private static URI resolveValidNamespace(final String namespace, final MountInstance mountPoint) {
         URI validNamespace;
         if (mountPoint != null) {
             validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(mountPoint, namespace);
index 7b6dcd57dbd7afb223168e6b7c1ad2b8ab87fec5..5a16c04aedb1fb7ed3d44b77bd1595897215d73f 100644 (file)
@@ -8,6 +8,14 @@
  */
 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.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
 import java.net.URI;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -51,6 +59,7 @@ import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -68,14 +77,6 @@ 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.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
 public class RestconfImpl implements RestconfService {
     private final static RestconfImpl INSTANCE = new RestconfImpl();
 
@@ -114,7 +115,7 @@ public class RestconfImpl implements RestconfService {
 
         final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
         final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                                        restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
+                restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
 
         Set<Module> allModules = this.controllerContext.getAllModules();
         for (final Module module : allModules) {
@@ -123,7 +124,7 @@ public class RestconfImpl implements RestconfService {
         }
 
         final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                                   restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
+                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);
@@ -136,13 +137,13 @@ public class RestconfImpl implements RestconfService {
         final List<Node<?>> streamsAsData = new ArrayList<Node<?>>();
         Module restconfModule = this.getRestconfModule();
         final DataSchemaNode streamSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                                             restconfModule, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
+                restconfModule, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
         for (final String streamName : availableStreams) {
             streamsAsData.add(this.toStreamCompositeNode(streamName, streamSchemaNode));
         }
 
         final DataSchemaNode streamsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                                     restconfModule, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
+                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);
@@ -154,27 +155,27 @@ public class RestconfImpl implements RestconfService {
         MountInstance mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             InstanceIdWithSchemaNode mountPointIdentifier =
-                                           this.controllerContext.toMountPointIdentifier(identifier);
+                    this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
             modules = this.controllerContext.getAllModules(mountPoint);
         }
         else {
             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 );
+                            ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
         Module restconfModule = this.getRestconfModule();
         final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                                         restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
+                restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
 
         for (final Module module : modules) {
             modulesAsData.add(this.toModuleCompositeNode(module, moduleSchemaNode));
         }
 
         final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                                  restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
+                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);
@@ -187,7 +188,7 @@ public class RestconfImpl implements RestconfService {
         MountInstance mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             InstanceIdWithSchemaNode mountPointIdentifier =
-                                            this.controllerContext.toMountPointIdentifier(identifier);
+                    this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
             module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision);
         }
@@ -198,13 +199,13 @@ public class RestconfImpl implements RestconfService {
         if (module == null) {
             throw new RestconfDocumentedException(
                     "Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '" +
-                    moduleNameAndRevision.getRevision() + "' was not found.",
-                    ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
+                            moduleNameAndRevision.getRevision() + "' was not found.",
+                            ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
         }
 
         Module restconfModule = this.getRestconfModule();
         final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                                          restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
+                restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
         final CompositeNode moduleNode = this.toModuleCompositeNode(module, moduleSchemaNode);
         return new StructuredData(moduleNode, moduleSchemaNode, mountPoint);
     }
@@ -221,40 +222,41 @@ public class RestconfImpl implements RestconfService {
         MountInstance mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             InstanceIdWithSchemaNode mountPointIdentifier =
-                                         this.controllerContext.toMountPointIdentifier(identifier);
+                    this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
             modules = this.controllerContext.getAllModules(mountPoint);
         }
         else {
             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 );
+                            ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
 
         return this.operationsFromModulesToStructuredData(modules, mountPoint);
     }
 
     private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
-                                                                 final MountInstance mountPoint) {
+            final MountInstance mountPoint) {
         final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
         Module restconfModule = this.getRestconfModule();
         final DataSchemaNode operationsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
-                              restconfModule, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
+                restconfModule, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
         QName qName = operationsSchemaNode.getQName();
         SchemaPath path = operationsSchemaNode.getPath();
         ContainerSchemaNodeBuilder containerSchemaNodeBuilder =
-                             new ContainerSchemaNodeBuilder(Draft02.RestConfModule.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();
             for (final RpcDefinition rpc : rpcs) {
                 QName rpcQName = rpc.getQName();
                 SimpleNode<Object> immutableSimpleNode =
-                                     NodeFactory.<Object>createImmutableSimpleNode(rpcQName, null, null);
+                        NodeFactory.<Object>createImmutableSimpleNode(rpcQName, null, null);
                 operationsAsData.add(immutableSimpleNode);
 
                 String name = module.getName();
-                LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName, null);
+                LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName,
+                        SchemaPath.create(true, QName.create("dummy")));
                 final LeafSchemaNodeBuilder fakeRpcSchemaNode = leafSchemaNodeBuilder;
                 fakeRpcSchemaNode.setAugmenting(true);
 
@@ -265,7 +267,7 @@ public class RestconfImpl implements RestconfService {
         }
 
         final CompositeNode operationsNode =
-                                  NodeFactory.createImmutableCompositeNode(qName, null, operationsAsData);
+                NodeFactory.createImmutableCompositeNode(qName, null, operationsAsData);
         ContainerSchemaNode schemaNode = fakeOperationsSchemaNode.build();
         return new StructuredData(operationsNode, schemaNode, mountPoint);
     }
@@ -317,34 +319,34 @@ public class RestconfImpl implements RestconfService {
         final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
         List<DataSchemaNode> instanceDataChildrenByName =
                 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) streamSchemaNode),
-                                                                       "name");
+                        "name");
         final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(), null,
-                                                                           streamName));
+                streamName));
 
         instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
-                                                 ((DataNodeContainer) streamSchemaNode), "description");
+                ((DataNodeContainer) streamSchemaNode), "description");
         final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
-                                                                           "DESCRIPTION_PLACEHOLDER"));
+                "DESCRIPTION_PLACEHOLDER"));
 
         instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
-                                               ((DataNodeContainer) streamSchemaNode), "replay-support");
+                ((DataNodeContainer) streamSchemaNode), "replay-support");
         final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<Boolean>createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
-                                                                            Boolean.valueOf(true)));
+                Boolean.valueOf(true)));
 
         instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
-                                           ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
+                ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
         final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
-                                                                           null, ""));
+                null, ""));
 
         instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
-                                                        ((DataNodeContainer) streamSchemaNode), "events");
+                ((DataNodeContainer) streamSchemaNode), "events");
         final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(eventsSchemaNode.getQName(),
-                                                                           null, ""));
+                null, ""));
 
         return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
     }
@@ -352,30 +354,30 @@ public class RestconfImpl implements RestconfService {
     private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
         final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
         List<DataSchemaNode> instanceDataChildrenByName =
-            this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) moduleSchemaNode), "name");
+                this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) moduleSchemaNode), "name");
         final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(),
-                                                                           null, module.getName()));
+                null, module.getName()));
 
         instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
-                                                          ((DataNodeContainer) moduleSchemaNode), "revision");
+                ((DataNodeContainer) moduleSchemaNode), "revision");
         final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         Date _revision = module.getRevision();
         moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
-                                                                           REVISION_FORMAT.format(_revision)));
+                REVISION_FORMAT.format(_revision)));
 
         instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
-                                                        ((DataNodeContainer) moduleSchemaNode), "namespace");
+                ((DataNodeContainer) moduleSchemaNode), "namespace");
         final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
-                                                                           module.getNamespace().toString()));
+                module.getNamespace().toString()));
 
         instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
-                                                           ((DataNodeContainer) moduleSchemaNode), "feature");
+                ((DataNodeContainer) moduleSchemaNode), "feature");
         final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         for (final FeatureDefinition feature : module.getFeatures()) {
             moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(featureSchemaNode.getQName(), null,
-                                                                               feature.getQName().getLocalName()));
+                    feature.getQName().getLocalName()));
         }
 
         return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.getQName(), null, moduleNodeValues);
@@ -392,7 +394,7 @@ public class RestconfImpl implements RestconfService {
         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)) {
+                Objects.equal(rpcName.getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
             return invokeSalRemoteRpcSubscribeRPC(payload, rpc.getRpcDefinition());
         }
 
@@ -401,33 +403,33 @@ public class RestconfImpl implements RestconfService {
         return callRpc(rpc, payload);
     }
 
-    private void validateInput(DataSchemaNode inputSchema, CompositeNode payload) {
+    private void validateInput(final DataSchemaNode inputSchema, final CompositeNode payload) {
         if( inputSchema != null && payload == null )
         {
             //expected a non null payload
             throw new RestconfDocumentedException( "Input is required.",
-                                                   ErrorType.PROTOCOL,
-                                                   ErrorTag.MALFORMED_MESSAGE );
+                    ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE );
         }
         else if( inputSchema == null && payload != null )
         {
             //did not expect any input
             throw new RestconfDocumentedException( "No input expected.",
-                                                   ErrorType.PROTOCOL,
-                                                   ErrorTag.MALFORMED_MESSAGE );
+                    ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE );
         }
         //else
         //{
-            //TODO: Validate "mandatory" and "config" values here??? Or should those be
+        //TODO: Validate "mandatory" and "config" values here??? Or should those be
         // validate in a more central location inside MD-SAL core.
         //}
     }
 
     private StructuredData invokeSalRemoteRpcSubscribeRPC(final CompositeNode payload,
-                                                          final RpcDefinition rpc) {
+            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") );
+            value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
         final Object pathValue = pathNode == null ? null : pathNode.getValue();
 
         if (!(pathValue instanceof InstanceIdentifier)) {
@@ -438,7 +440,7 @@ public class RestconfImpl implements RestconfService {
 
         final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
         String streamName = null;
-        if (!Iterables.isEmpty(pathIdentifier.getPath())) {
+        if (!Iterables.isEmpty(pathIdentifier.getPathArguments())) {
             String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
             streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
         }
@@ -450,12 +452,12 @@ public class RestconfImpl implements RestconfService {
         }
 
         final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
-                             QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
+                QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
         final List<Node<?>> output = new ArrayList<Node<?>>();
         output.add(streamNameNode);
 
         final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
-                                              rpc.getOutput().getQName(), null, output, null, null);
+                rpc.getOutput().getQName(), null, output, null, null);
 
         if (!Notificator.existListenerFor(pathIdentifier)) {
             Notificator.createListener(pathIdentifier, streamName);
@@ -548,14 +550,14 @@ public class RestconfImpl implements RestconfService {
         return new StructuredData(rpcResult.getResult(), rpc.getOutput(), null);
     }
 
-    private void checkRpcSuccessAndThrowException(RpcResult<CompositeNode> rpcResult) {
+    private void checkRpcSuccessAndThrowException(final 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 );
+                        "The operation was not successful and there were no RPC errors returned",
+                        ErrorType.RPC, ErrorTag.OPERATION_FAILED );
             }
 
             List<RestconfError> errorList = Lists.newArrayList();
@@ -568,7 +570,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     @Override
-    public StructuredData readConfigurationData(final String identifier, UriInfo info) {
+    public StructuredData readConfigurationData(final String identifier, final UriInfo info) {
         final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
         CompositeNode data = null;
         MountInstance mountPoint = iiWithData.getMountPoint();
@@ -584,7 +586,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     @SuppressWarnings("unchecked")
-    private <T extends Node<?>> T pruneDataAtDepth( T node, Integer depth ) {
+    private <T extends Node<?>> T pruneDataAtDepth( final T node, final Integer depth ) {
         if( depth == null ) {
             return node;
         }
@@ -604,7 +606,7 @@ public class RestconfImpl implements RestconfService {
         }
     }
 
-    private Integer parseDepthParameter( UriInfo info ) {
+    private Integer parseDepthParameter( final UriInfo info ) {
         String param = info.getQueryParameters( false ).getFirst( "depth" );
         if( Strings.isNullOrEmpty( param ) || "unbounded".equals( param ) ) {
             return null;
@@ -629,7 +631,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     @Override
-    public StructuredData readOperationalData(final String identifier, UriInfo info) {
+    public StructuredData readOperationalData(final String identifier, final UriInfo info) {
         final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
         CompositeNode data = null;
         MountInstance mountPoint = iiWithData.getMountPoint();
@@ -657,7 +659,7 @@ public class RestconfImpl implements RestconfService {
         try {
             if (mountPoint != null) {
                 status = broker.commitConfigurationDataPutBehindMountPoint(
-                                                mountPoint, iiWithData.getInstanceIdentifier(), value).get();
+                        mountPoint, iiWithData.getInstanceIdentifier(), value).get();
             } else {
                 status = broker.commitConfigurationDataPut(iiWithData.getInstanceIdentifier(), value).get();
             }
@@ -666,8 +668,9 @@ public class RestconfImpl implements RestconfService {
             throw new RestconfDocumentedException( "Error updating data", e );
         }
 
-        if( status.getResult() == TransactionStatus.COMMITED )
+        if( status.getResult() == TransactionStatus.COMMITED ) {
             return Response.status(Status.OK).build();
+        }
 
         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
     }
@@ -683,14 +686,14 @@ public class RestconfImpl implements RestconfService {
         URI payloadNS = this.namespace(payload);
         if (payloadNS == null) {
             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 );
+                    "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;
         CompositeNode value = null;
         if (this.representsMountPointRootData(payload)) {
-             // payload represents mount point data and URI represents path to the mount point
+            // payload represents mount point data and URI represents path to the mount point
 
             if (this.endsWithMountPoint(identifier)) {
                 throw new RestconfDocumentedException(
@@ -706,7 +709,7 @@ public class RestconfImpl implements RestconfService {
         }
         else {
             final InstanceIdWithSchemaNode incompleteInstIdWithData =
-                                               this.controllerContext.toInstanceIdentifier(identifier);
+                    this.controllerContext.toInstanceIdentifier(identifier);
             final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
             MountInstance mountPoint = incompleteInstIdWithData.getMountPoint();
             final Module module = this.findModule(mountPoint, payload);
@@ -718,7 +721,7 @@ public class RestconfImpl implements RestconfService {
 
             String payloadName = this.getName(payload);
             final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
-                                                              parentSchema, payloadName, module.getNamespace());
+                    parentSchema, payloadName, module.getNamespace());
             value = this.normalizeNode(payload, schemaNode, mountPoint);
 
             iiWithData = this.addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
@@ -729,13 +732,13 @@ public class RestconfImpl implements RestconfService {
         try {
             if (mountPoint != null) {
                 Future<RpcResult<TransactionStatus>> future =
-                                          broker.commitConfigurationDataPostBehindMountPoint(
-                                                       mountPoint, iiWithData.getInstanceIdentifier(), value);
+                        broker.commitConfigurationDataPostBehindMountPoint(
+                                mountPoint, iiWithData.getInstanceIdentifier(), value);
                 status = future == null ? null : future.get();
             }
             else {
                 Future<RpcResult<TransactionStatus>> future =
-                               broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
+                        broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
                 status = future == null ? null : future.get();
             }
         }
@@ -747,8 +750,9 @@ public class RestconfImpl implements RestconfService {
             return Response.status(Status.ACCEPTED).build();
         }
 
-        if( status.getResult() == TransactionStatus.COMMITED )
+        if( status.getResult() == TransactionStatus.COMMITED ) {
             return Response.status(Status.NO_CONTENT).build();
+        }
 
         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
     }
@@ -764,8 +768,8 @@ public class RestconfImpl implements RestconfService {
         URI payloadNS = this.namespace(payload);
         if (payloadNS == null) {
             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 );
+                    "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);
@@ -777,7 +781,7 @@ public class RestconfImpl implements RestconfService {
 
         String payloadName = this.getName(payload);
         final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
-                                                                   module, payloadName, module.getNamespace());
+                module, payloadName, module.getNamespace());
         final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
         final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
         RpcResult<TransactionStatus> status = null;
@@ -786,13 +790,13 @@ public class RestconfImpl implements RestconfService {
         try {
             if (mountPoint != null) {
                 Future<RpcResult<TransactionStatus>> future =
-                                             broker.commitConfigurationDataPostBehindMountPoint(
-                                                          mountPoint, iiWithData.getInstanceIdentifier(), value);
+                        broker.commitConfigurationDataPostBehindMountPoint(
+                                mountPoint, iiWithData.getInstanceIdentifier(), value);
                 status = future == null ? null : future.get();
             }
             else {
                 Future<RpcResult<TransactionStatus>> future =
-                                 broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
+                        broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
                 status = future == null ? null : future.get();
             }
         }
@@ -804,8 +808,9 @@ public class RestconfImpl implements RestconfService {
             return Response.status(Status.ACCEPTED).build();
         }
 
-        if( status.getResult() == TransactionStatus.COMMITED )
+        if( status.getResult() == TransactionStatus.COMMITED ) {
             return Response.status(Status.NO_CONTENT).build();
+        }
 
         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
     }
@@ -819,7 +824,7 @@ public class RestconfImpl implements RestconfService {
         try {
             if (mountPoint != null) {
                 status = broker.commitConfigurationDataDeleteBehindMountPoint(
-                                        mountPoint, iiWithData.getInstanceIdentifier()).get();
+                        mountPoint, iiWithData.getInstanceIdentifier()).get();
             }
             else {
                 status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier()).get();
@@ -829,8 +834,9 @@ public class RestconfImpl implements RestconfService {
             throw new RestconfDocumentedException( "Error creating data", e );
         }
 
-        if( status.getResult() == TransactionStatus.COMMITED )
+        if( status.getResult() == TransactionStatus.COMMITED ) {
             return Response.status(Status.OK).build();
+        }
 
         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
     }
@@ -899,8 +905,8 @@ public class RestconfImpl implements RestconfService {
     }
 
     private InstanceIdWithSchemaNode addLastIdentifierFromData(
-                                              final InstanceIdWithSchemaNode identifierWithSchemaNode,
-                                              final CompositeNode data, final DataSchemaNode schemaOfData) {
+            final InstanceIdWithSchemaNode identifierWithSchemaNode,
+            final CompositeNode data, final DataSchemaNode schemaOfData) {
         InstanceIdentifier instanceIdentifier = null;
         if (identifierWithSchemaNode != null) {
             instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier();
@@ -933,7 +939,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     private HashMap<QName,Object> resolveKeysFromData(final ListSchemaNode listNode,
-                                                      final CompositeNode dataNode) {
+            final CompositeNode dataNode) {
         final HashMap<QName,Object> keyValues = new HashMap<QName, Object>();
         List<QName> _keyDefinition = listNode.getKeyDefinition();
         for (final QName key : _keyDefinition) {
@@ -964,7 +970,7 @@ public class RestconfImpl implements RestconfService {
 
     private boolean endsWithMountPoint(final String identifier) {
         return identifier.endsWith(ControllerContext.MOUNT) ||
-               identifier.endsWith(ControllerContext.MOUNT + "/");
+                identifier.endsWith(ControllerContext.MOUNT + "/");
     }
 
     private boolean representsMountPointRootData(final CompositeNode data) {
@@ -984,7 +990,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     private CompositeNode normalizeNode(final CompositeNode node, final DataSchemaNode schema,
-                                        final MountInstance mountPoint) {
+            final MountInstance mountPoint) {
         if (schema == null) {
             QName nodeType = node == null ? null : node.getNodeType();
             String localName = nodeType == null ? null : nodeType.getLocalName();
@@ -1008,7 +1014,7 @@ public class RestconfImpl implements RestconfService {
                 }
                 catch (IllegalArgumentException e) {
                     throw new RestconfDocumentedException(
-                                    e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+                            e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
                 }
             }
 
@@ -1019,8 +1025,8 @@ public class RestconfImpl implements RestconfService {
     }
 
     private void normalizeNode(final NodeWrapper<? extends Object> nodeBuilder,
-                               final DataSchemaNode schema, final QName previousAugment,
-                               final MountInstance mountPoint) {
+            final DataSchemaNode schema, final QName previousAugment,
+            final MountInstance mountPoint) {
         if (schema == null) {
             throw new RestconfDocumentedException(
                     "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
@@ -1037,120 +1043,150 @@ public class RestconfImpl implements RestconfService {
             if (nodeBuilder.getQname() == null) {
                 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() + "\".",
-                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+                                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() + "\".",
+                                ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
         }
 
-        if ((nodeBuilder instanceof CompositeNodeWrapper)) {
-            final List<NodeWrapper<?>> children = ((CompositeNodeWrapper) nodeBuilder).getValues();
-            for (final NodeWrapper<? extends Object> child : children) {
-                final List<DataSchemaNode> potentialSchemaNodes =
-                        this.controllerContext.findInstanceDataChildrenByName(
-                                             ((DataNodeContainer) schema), child.getLocalName());
+        if ( nodeBuilder instanceof CompositeNodeWrapper ) {
+            if( schema instanceof DataNodeContainer ) {
+                normalizeCompositeNode( (CompositeNodeWrapper)nodeBuilder, (DataNodeContainer)schema,
+                        mountPoint, currentAugment );
+            }
+            else if( schema instanceof AnyXmlSchemaNode ) {
+                normalizeAnyXmlNode( (CompositeNodeWrapper)nodeBuilder, (AnyXmlSchemaNode)schema );
+            }
+        }
+        else if ( nodeBuilder instanceof SimpleNodeWrapper ) {
+            normalizeSimpleNode( (SimpleNodeWrapper) nodeBuilder, schema, mountPoint );
+        }
+        else if ((nodeBuilder instanceof EmptyNodeWrapper)) {
+            normalizeEmptyNode( (EmptyNodeWrapper) nodeBuilder, schema );
+        }
+    }
 
-                if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
-                    StringBuilder builder = new StringBuilder();
-                    for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
-                        builder.append("   ").append(potentialSchemaNode.getQName().getNamespace().toString())
-                               .append("\n");
-                    }
+    private void normalizeAnyXmlNode( final CompositeNodeWrapper compositeNode, final AnyXmlSchemaNode schema ) {
+        List<NodeWrapper<?>> children = compositeNode.getValues();
+        for( NodeWrapper<? extends Object> child : children ) {
+            child.setNamespace( schema.getQName().getNamespace() );
+            if( child instanceof CompositeNodeWrapper ) {
+                normalizeAnyXmlNode( (CompositeNodeWrapper)child, schema );
+            }
+        }
+    }
 
-                    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,
-                                 ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
-                }
+    private void normalizeEmptyNode( final EmptyNodeWrapper emptyNodeBuilder, final DataSchemaNode schema ) {
+        if ((schema instanceof LeafSchemaNode)) {
+            emptyNodeBuilder.setComposite(false);
+        }
+        else {
+            if ((schema instanceof ContainerSchemaNode)) {
+                // FIXME: Add presence check
+                emptyNodeBuilder.setComposite(true);
+            }
+        }
+    }
+
+    private void normalizeSimpleNode( final SimpleNodeWrapper simpleNode, final DataSchemaNode schema,
+            final MountInstance mountPoint ) {
+        final Object value = simpleNode.getValue();
+        Object inputValue = value;
+        TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
+        if ((typeDefinition instanceof IdentityrefTypeDefinition)) {
+            if ((value instanceof String)) {
+                inputValue = new IdentityValuesDTO( simpleNode.getNamespace().toString(),
+                        (String) value, null, (String) value );
+            } // else value is already instance of IdentityValuesDTO
+        }
+
+        Object outputValue = inputValue;
 
-                boolean rightNodeSchemaFound = false;
+        if( typeDefinition != null ) {
+            Codec<Object,Object> codec = RestCodec.from(typeDefinition, mountPoint);
+            outputValue = codec == null ? null : codec.deserialize(inputValue);
+        }
+
+        simpleNode.setValue(outputValue);
+    }
+
+    private void normalizeCompositeNode( final CompositeNodeWrapper compositeNodeBuilder,
+            final DataNodeContainer schema, final MountInstance mountPoint,
+            final QName currentAugment ) {
+        final List<NodeWrapper<?>> children = compositeNodeBuilder.getValues();
+        for (final NodeWrapper<? extends Object> child : children) {
+            final List<DataSchemaNode> potentialSchemaNodes =
+                    this.controllerContext.findInstanceDataChildrenByName(
+                            schema, child.getLocalName());
+
+            if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
+                StringBuilder builder = new StringBuilder();
                 for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
-                    if (!rightNodeSchemaFound) {
-                        final QName potentialCurrentAugment =
-                                this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint);
-                        if (child.getQname() != null ) {
-                            this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint);
-                            rightNodeSchemaFound = true;
-                        }
-                    }
+                    builder.append("   ").append(potentialSchemaNode.getQName().getNamespace().toString())
+                    .append("\n");
                 }
 
-                if (!rightNodeSchemaFound) {
-                    throw new RestconfDocumentedException(
-                               "Schema node \"" + child.getLocalName() + "\" was not found in module.",
-                               ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT );
-                }
+                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,
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
             }
 
-            if ((schema instanceof ListSchemaNode)) {
-                final List<QName> listKeys = ((ListSchemaNode) schema).getKeyDefinition();
-                for (final QName listKey : listKeys) {
-                    boolean foundKey = false;
-                    for (final NodeWrapper<? extends Object> child : children) {
-                        if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) {
-                            foundKey = true;
-                        }
-                    }
-
-                    if (!foundKey) {
-                        throw new RestconfDocumentedException(
-                                       "Missing key in URI \"" + listKey.getLocalName() +
-                                       "\" of list \"" + schema.getQName().getLocalName() + "\"",
-                                       ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+            boolean rightNodeSchemaFound = false;
+            for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
+                if (!rightNodeSchemaFound) {
+                    final QName potentialCurrentAugment =
+                            this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint);
+                    if (child.getQname() != null ) {
+                        this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint);
+                        rightNodeSchemaFound = true;
                     }
                 }
             }
-        }
-        else {
-            if ((nodeBuilder instanceof SimpleNodeWrapper)) {
-                final SimpleNodeWrapper simpleNode = ((SimpleNodeWrapper) nodeBuilder);
-                final Object value = simpleNode.getValue();
-                Object inputValue = value;
-                TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
-                if ((typeDefinition instanceof IdentityrefTypeDefinition)) {
-                    if ((value instanceof String)) {
-                        inputValue = new IdentityValuesDTO( nodeBuilder.getNamespace().toString(),
-                                                            (String) value, null, (String) value );
-                    } // else value is already instance of IdentityValuesDTO
-                }
 
-                Codec<Object,Object> codec = RestCodec.from(typeDefinition, mountPoint);
-                Object outputValue = codec == null ? null : codec.deserialize(inputValue);
-
-                simpleNode.setValue(outputValue);
+            if (!rightNodeSchemaFound) {
+                throw new RestconfDocumentedException(
+                        "Schema node \"" + child.getLocalName() + "\" was not found in module.",
+                        ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT );
             }
-            else {
-                if ((nodeBuilder instanceof EmptyNodeWrapper)) {
-                    final EmptyNodeWrapper emptyNodeBuilder = ((EmptyNodeWrapper) nodeBuilder);
-                    if ((schema instanceof LeafSchemaNode)) {
-                        emptyNodeBuilder.setComposite(false);
-                    }
-                    else {
-                        if ((schema instanceof ContainerSchemaNode)) {
-                            // FIXME: Add presence check
-                            emptyNodeBuilder.setComposite(true);
-                        }
+        }
+
+        if ((schema instanceof ListSchemaNode)) {
+            ListSchemaNode listSchemaNode = (ListSchemaNode)schema;
+            final List<QName> listKeys = listSchemaNode.getKeyDefinition();
+            for (final QName listKey : listKeys) {
+                boolean foundKey = false;
+                for (final NodeWrapper<? extends Object> child : children) {
+                    if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) {
+                        foundKey = true;
                     }
                 }
+
+                if (!foundKey) {
+                    throw new RestconfDocumentedException(
+                            "Missing key in URI \"" + listKey.getLocalName() +
+                            "\" of list \"" + listSchemaNode.getQName().getLocalName() + "\"",
+                            ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+                }
             }
         }
     }
 
     private QName normalizeNodeName(final NodeWrapper<? extends Object> nodeBuilder,
-                                    final DataSchemaNode schema, final QName previousAugment,
-                                    final MountInstance mountPoint) {
+            final DataSchemaNode schema, final QName previousAugment,
+            final MountInstance mountPoint) {
         QName validQName = schema.getQName();
         QName currentAugment = previousAugment;
         if (schema.isAugmenting()) {
             currentAugment = schema.getQName();
         }
         else if (previousAugment != null &&
-                 !Objects.equal( schema.getQName().getNamespace(), previousAugment.getNamespace())) {
+                !Objects.equal( schema.getQName().getNamespace(), previousAugment.getNamespace())) {
             validQName = QName.create(currentAugment, schema.getQName().getLocalName());
         }
 
@@ -1163,8 +1199,8 @@ public class RestconfImpl implements RestconfService {
         }
 
         if (nodeBuilder.getNamespace() == null ||
-            Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace()) ||
-            Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*||
+                Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace()) ||
+                Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*||
             Note: this check is wrong - can never be true as it compares a URI with a String
                   not sure what the intention is so commented out...
             Objects.equal(nodeBuilder.getNamespace(), MOUNT_POINT_MODULE_NAME)*/ ) {
@@ -1239,6 +1275,9 @@ public class RestconfImpl implements RestconfService {
         else if (node instanceof LeafSchemaNode) {
             return _typeDefinition((LeafSchemaNode)node);
         }
+        else if (node instanceof AnyXmlSchemaNode) {
+            return null;
+        }
         else {
             throw new IllegalArgumentException("Unhandled parameter types: " +
                     Arrays.<Object>asList(node).toString());
index 3131668ed9ed23ae8fb8f0edb75076c8635a235d..b0959c8398263dbd55a4ccb9fafac6d339f9fdaf 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.base.Preconditions;
+
 import java.net.URI;
 
 import org.opendaylight.yangtools.yang.common.QName;
@@ -16,8 +18,6 @@ import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
-import com.google.common.base.Preconditions;
-
 public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<Object> {
 
     private SimpleNode<Object> simpleNode;
@@ -27,18 +27,18 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     private URI namespace;
     private QName name;
 
-    public SimpleNodeWrapper(String localName, Object value) {
+    public SimpleNodeWrapper(final String localName, final Object value) {
         this.localName = Preconditions.checkNotNull(localName);
         this.value = value;
     }
 
-    public SimpleNodeWrapper(URI namespace, String localName, Object value) {
+    public SimpleNodeWrapper(final URI namespace, final String localName, final Object value) {
         this(localName, value);
         this.namespace = namespace;
     }
 
     @Override
-    public void setQname(QName name) {
+    public void setQname(final QName name) {
         Preconditions.checkState(simpleNode == null, "Cannot change the object, due to data inconsistencies.");
         this.name = name;
     }
@@ -65,7 +65,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
-    public void setNamespace(URI namespace) {
+    public void setNamespace(final URI namespace) {
         Preconditions.checkState(simpleNode == null, "Cannot change the object, due to data inconsistencies.");
         this.namespace = namespace;
     }
@@ -89,7 +89,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
             localName = null;
             name = null;
         }
-        return (SimpleNode<Object>) simpleNode;
+        return simpleNode;
     }
 
     @Override
@@ -98,6 +98,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
+    @Deprecated
     public CompositeNode getParent() {
         return unwrap().getParent();
     }
@@ -108,6 +109,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
+    @Deprecated
     public ModifyAction getModificationAction() {
         return unwrap().getModificationAction();
     }
@@ -123,7 +125,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
     }
 
     @Override
-    public Object setValue(Object value) {
+    public Object setValue(final Object value) {
         return unwrap().setValue(value);
     }
 
index 6282f37602be8236a737fe3e8ef42852816756bc..925a09337ca3ee1e8fba707020e3c7a19b8e03f6 100644 (file)
@@ -7,6 +7,12 @@
  */
 package org.opendaylight.controller.sal.streams.listeners;
 
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.eventbus.AsyncEventBus;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
 import io.netty.channel.Channel;
 import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
 import io.netty.util.internal.ConcurrentSet;
@@ -23,6 +29,7 @@ import java.util.Map.Entry;
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.Executors;
+import java.util.regex.Pattern;
 
 import javax.activation.UnsupportedDataTypeException;
 import javax.xml.parsers.DocumentBuilder;
@@ -53,19 +60,17 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
-import com.google.common.base.Preconditions;
-import com.google.common.eventbus.AsyncEventBus;
-import com.google.common.eventbus.EventBus;
-import com.google.common.eventbus.Subscribe;
-
 /**
  * {@link ListenerAdapter} is responsible to track events, which occurred by
  * changing data in data source.
  */
 public class ListenerAdapter implements DataChangeListener {
 
-    private static final Logger logger = LoggerFactory
-            .getLogger(ListenerAdapter.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ListenerAdapter.class);
+    private static final DocumentBuilderFactory DBF = DocumentBuilderFactory.newInstance();
+    private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
+    private static final Pattern RFC3339_PATTERN = Pattern.compile("(\\d\\d)(\\d\\d)$");
+
     private final XmlMapper xmlMapper = new XmlMapper();
     private final SimpleDateFormat rfc3339 = new SimpleDateFormat(
             "yyyy-MM-dd'T'hh:mm:ssZ");
@@ -77,6 +82,7 @@ public class ListenerAdapter implements DataChangeListener {
     private final EventBus eventBus;
     private final EventBusChangeRecorder eventBusChangeRecorder;
 
+
     /**
      * Creates new {@link ListenerAdapter} listener specified by path and stream
      * name.
@@ -86,10 +92,10 @@ public class ListenerAdapter implements DataChangeListener {
      * @param streamName
      *            The name of the stream.
      */
-    ListenerAdapter(InstanceIdentifier path, String streamName) {
+    ListenerAdapter(final InstanceIdentifier path, final String streamName) {
         Preconditions.checkNotNull(path);
         Preconditions
-                .checkArgument(streamName != null && !streamName.isEmpty());
+        .checkArgument(streamName != null && !streamName.isEmpty());
         this.path = path;
         this.streamName = streamName;
         eventBus = new AsyncEventBus(Executors.newSingleThreadExecutor());
@@ -99,7 +105,7 @@ public class ListenerAdapter implements DataChangeListener {
 
     @Override
     public void onDataChanged(
-            DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
+            final DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
         if (!change.getCreatedConfigurationData().isEmpty()
                 || !change.getCreatedOperationalData().isEmpty()
                 || !change.getUpdatedConfigurationData().isEmpty()
@@ -118,7 +124,7 @@ public class ListenerAdapter implements DataChangeListener {
      */
     private final class EventBusChangeRecorder {
         @Subscribe
-        public void recordCustomerChange(Event event) {
+        public void recordCustomerChange(final Event event) {
             if (event.getType() == EventType.REGISTER) {
                 Channel subscriber = event.getSubscriber();
                 if (!subscribers.contains(subscriber)) {
@@ -127,16 +133,16 @@ public class ListenerAdapter implements DataChangeListener {
             } else if (event.getType() == EventType.DEREGISTER) {
                 subscribers.remove(event.getSubscriber());
                 Notificator
-                        .removeListenerIfNoSubscriberExists(ListenerAdapter.this);
+                .removeListenerIfNoSubscriberExists(ListenerAdapter.this);
             } else if (event.getType() == EventType.NOTIFY) {
                 for (Channel subscriber : subscribers) {
                     if (subscriber.isActive()) {
-                        logger.debug("Data are sent to subscriber {}:",
+                        LOG.debug("Data are sent to subscriber {}:",
                                 subscriber.remoteAddress());
                         subscriber.writeAndFlush(new TextWebSocketFrame(event
                                 .getData()));
                     } else {
-                        logger.debug(
+                        LOG.debug(
                                 "Subscriber {} is removed - channel is not active yet.",
                                 subscriber.remoteAddress());
                         subscribers.remove(subscriber);
@@ -161,7 +167,7 @@ public class ListenerAdapter implements DataChangeListener {
          * @param type
          *            EventType
          */
-        public Event(EventType type) {
+        public Event(final EventType type) {
             this.type = type;
         }
 
@@ -180,7 +186,7 @@ public class ListenerAdapter implements DataChangeListener {
          * @param subscriber
          *            Channel
          */
-        public void setSubscriber(Channel subscriber) {
+        public void setSubscriber(final Channel subscriber) {
             this.subscriber = subscriber;
         }
 
@@ -199,7 +205,7 @@ public class ListenerAdapter implements DataChangeListener {
          * @param String
          *            data.
          */
-        public void setData(String data) {
+        public void setData(final String data) {
             this.data = data;
         }
 
@@ -228,7 +234,7 @@ public class ListenerAdapter implements DataChangeListener {
      * @return Data in printable form.
      */
     private String prepareXmlFrom(
-            DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
+            final DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
         Document doc = createDocument();
         Element notificationElement = doc.createElementNS(
                 "urn:ietf:params:xml:ns:netconf:notification:1.0",
@@ -248,22 +254,19 @@ public class ListenerAdapter implements DataChangeListener {
 
         try {
             ByteArrayOutputStream out = new ByteArrayOutputStream();
-            TransformerFactory tf = TransformerFactory.newInstance();
-            Transformer transformer = tf.newTransformer();
-            transformer
-                    .setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            Transformer transformer = FACTORY.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");
+            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
             transformer.transform(new DOMSource(doc), new StreamResult(
-                    new OutputStreamWriter(out, "UTF-8")));
+                    new OutputStreamWriter(out, Charsets.UTF_8)));
             byte[] charData = out.toByteArray();
             return new String(charData, "UTF-8");
         } catch (TransformerException | UnsupportedEncodingException e) {
             String msg = "Error during transformation of Document into String";
-            logger.error(msg, e);
+            LOG.error(msg, e);
             return msg;
         }
     }
@@ -275,8 +278,8 @@ public class ListenerAdapter implements DataChangeListener {
      *            Date
      * @return Data specified by RFC3339.
      */
-    private String toRFC3339(Date d) {
-        return rfc3339.format(d).replaceAll("(\\d\\d)(\\d\\d)$", "$1:$2");
+    private String toRFC3339(final Date d) {
+        return RFC3339_PATTERN.matcher(rfc3339.format(d)).replaceAll("$1:$2");
     }
 
     /**
@@ -285,15 +288,13 @@ public class ListenerAdapter implements DataChangeListener {
      * @return {@link Document} document.
      */
     private Document createDocument() {
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        Document doc = null;
+        final DocumentBuilder bob;
         try {
-            DocumentBuilder bob = dbf.newDocumentBuilder();
-            doc = bob.newDocument();
+            bob = DBF.newDocumentBuilder();
         } catch (ParserConfigurationException e) {
             return null;
         }
-        return doc;
+        return bob.newDocument();
     }
 
     /**
@@ -306,9 +307,9 @@ public class ListenerAdapter implements DataChangeListener {
      * @param change
      *            {@link DataChangeEvent}
      */
-    private void addValuesToDataChangedNotificationEventElement(Document doc,
-            Element dataChangedNotificationEventElement,
-            DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
+    private void addValuesToDataChangedNotificationEventElement(final Document doc,
+            final Element dataChangedNotificationEventElement,
+            final DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
         addValuesFromDataToElement(doc, change.getCreatedConfigurationData(),
                 dataChangedNotificationEventElement, Store.CONFIG,
                 Operation.CREATED);
@@ -348,9 +349,9 @@ public class ListenerAdapter implements DataChangeListener {
      * @param operation
      *            {@link Operation}
      */
-    private void addValuesFromDataToElement(Document doc,
-            Set<InstanceIdentifier> data, Element element, Store store,
-            Operation operation) {
+    private void addValuesFromDataToElement(final Document doc,
+            final Set<InstanceIdentifier> data, final Element element, final Store store,
+            final Operation operation) {
         if (data == null || data.isEmpty()) {
             return;
         }
@@ -375,9 +376,9 @@ public class ListenerAdapter implements DataChangeListener {
      * @param operation
      *            {@link Operation}
      */
-    private void addValuesFromDataToElement(Document doc,
-            Map<InstanceIdentifier, CompositeNode> data, Element element,
-            Store store, Operation operation) {
+    private void addValuesFromDataToElement(final Document doc,
+            final Map<InstanceIdentifier, CompositeNode> data, final Element element,
+            final Store store, final Operation operation) {
         if (data == null || data.isEmpty()) {
             return;
         }
@@ -403,9 +404,9 @@ public class ListenerAdapter implements DataChangeListener {
      *            {@link Operation}
      * @return {@link Node} node represented by changed event element.
      */
-    private Node createDataChangeEventElement(Document doc,
-            InstanceIdentifier path, CompositeNode data, Store store,
-            Operation operation) {
+    private Node createDataChangeEventElement(final Document doc,
+            final InstanceIdentifier path, final CompositeNode data, final Store store,
+            final Operation operation) {
         Element dataChangeEventElement = doc.createElement("data-change-event");
 
         Element pathElement = doc.createElement("path");
@@ -440,11 +441,11 @@ public class ListenerAdapter implements DataChangeListener {
      *            {@link CompositeNode}
      * @return Data in XML format.
      */
-    private Node translateToXml(InstanceIdentifier path, CompositeNode data) {
+    private Node translateToXml(final InstanceIdentifier path, final CompositeNode data) {
         DataNodeContainer schemaNode = ControllerContext.getInstance()
                 .getDataNodeContainerFor(path);
         if (schemaNode == null) {
-            logger.info(
+            LOG.info(
                     "Path '{}' contains node with unsupported type (supported type is Container or List) or some node was not found.",
                     path);
             return null;
@@ -453,7 +454,7 @@ public class ListenerAdapter implements DataChangeListener {
             Document xml = xmlMapper.write(data, schemaNode);
             return xml.getFirstChild();
         } catch (UnsupportedDataTypeException e) {
-            logger.error(
+            LOG.error(
                     "Error occured during translation of notification to XML.",
                     e);
             return null;
@@ -468,13 +469,15 @@ public class ListenerAdapter implements DataChangeListener {
      * @param element
      *            {@link Element}
      */
-    private void addPathAsValueToElement(InstanceIdentifier path,
-            Element element) {
+    private void addPathAsValueToElement(final InstanceIdentifier path,
+            final Element element) {
         // Map< key = namespace, value = prefix>
         Map<String, String> prefixes = new HashMap<>();
         InstanceIdentifier instanceIdentifier = path;
         StringBuilder textContent = new StringBuilder();
-        for (PathArgument pathArgument : instanceIdentifier.getPath()) {
+
+        // FIXME: BUG-1281: this is duplicated code from yangtools (BUG-1275)
+        for (PathArgument pathArgument : instanceIdentifier.getPathArguments()) {
             textContent.append("/");
             writeIdentifierWithNamespacePrefix(element, textContent,
                     pathArgument.getNodeType(), prefixes);
@@ -514,8 +517,8 @@ public class ListenerAdapter implements DataChangeListener {
      * @param prefixes
      *            Map of namespaces and prefixes.
      */
-    private static void writeIdentifierWithNamespacePrefix(Element element,
-            StringBuilder textContent, QName qName, Map<String, String> prefixes) {
+    private static void writeIdentifierWithNamespacePrefix(final Element element,
+            final StringBuilder textContent, final QName qName, final Map<String, String> prefixes) {
         String namespace = qName.getNamespace().toString();
         String prefix = prefixes.get(namespace);
         if (prefix == null) {
@@ -541,7 +544,7 @@ public class ListenerAdapter implements DataChangeListener {
      *            Collection of prefixes.
      * @return New prefix which consists of four random characters <a-z>.
      */
-    private static String generateNewPrefix(Collection<String> prefixes) {
+    private static String generateNewPrefix(final Collection<String> prefixes) {
         StringBuilder result = null;
         Random random = new Random();
         do {
@@ -571,7 +574,7 @@ public class ListenerAdapter implements DataChangeListener {
      *            ListenerRegistration<DataChangeListener>
      */
     public void setRegistration(
-            ListenerRegistration<DataChangeListener> registration) {
+            final ListenerRegistration<DataChangeListener> registration) {
         this.registration = registration;
     }
 
@@ -611,9 +614,9 @@ public class ListenerAdapter implements DataChangeListener {
      * @param subscriber
      *            Channel
      */
-    public void addSubscriber(Channel subscriber) {
+    public void addSubscriber(final Channel subscriber) {
         if (!subscriber.isActive()) {
-            logger.debug("Channel is not active between websocket server and subscriber {}"
+            LOG.debug("Channel is not active between websocket server and subscriber {}"
                     + subscriber.remoteAddress());
         }
         Event event = new Event(EventType.REGISTER);
@@ -627,8 +630,8 @@ public class ListenerAdapter implements DataChangeListener {
      *
      * @param subscriber
      */
-    public void removeSubscriber(Channel subscriber) {
-        logger.debug("Subscriber {} is removed.", subscriber.remoteAddress());
+    public void removeSubscriber(final Channel subscriber) {
+        LOG.debug("Subscriber {} is removed.", subscriber.remoteAddress());
         Event event = new Event(EventType.DEREGISTER);
         event.setSubscriber(subscriber);
         eventBus.post(event);
@@ -652,7 +655,7 @@ public class ListenerAdapter implements DataChangeListener {
 
         private final String value;
 
-        private Store(String value) {
+        private Store(final String value) {
             this.value = value;
         }
     }
@@ -666,7 +669,7 @@ public class ListenerAdapter implements DataChangeListener {
 
         private final String value;
 
-        private Operation(String value) {
+        private Operation(final String value) {
             this.value = value;
         }
     }
index b5d6a6ea9be647d22c1dc8a75609506433e850f6..26e4936d3f27d0d20e3875fe051335d79beae3be 100644 (file)
@@ -46,7 +46,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
     private WebSocketServerHandshaker handshaker;
 
     @Override
-    protected void channelRead0(ChannelHandlerContext ctx, Object msg)
+    protected void channelRead0(final ChannelHandlerContext ctx, final Object msg)
             throws Exception {
         if (msg instanceof FullHttpRequest) {
             handleHttpRequest(ctx, (FullHttpRequest) msg);
@@ -64,8 +64,8 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
      * @param req
      *            FullHttpRequest
      */
-    private void handleHttpRequest(ChannelHandlerContext ctx,
-            FullHttpRequest req) throws Exception {
+    private void handleHttpRequest(final ChannelHandlerContext ctx,
+            final FullHttpRequest req) throws Exception {
         // Handle a bad request.
         if (!req.getDecoderResult().isSuccess()) {
             sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1,
@@ -97,8 +97,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
                 getWebSocketLocation(req), null, false);
         handshaker = wsFactory.newHandshaker(req);
         if (handshaker == null) {
-            WebSocketServerHandshakerFactory
-                    .sendUnsupportedWebSocketVersionResponse(ctx.channel());
+            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
         } else {
             handshaker.handshake(ctx.channel(), req);
         }
@@ -115,8 +114,8 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
      * @param res
      *            FullHttpResponse
      */
-    private static void sendHttpResponse(ChannelHandlerContext ctx,
-            HttpRequest req, FullHttpResponse res) {
+    private static void sendHttpResponse(final ChannelHandlerContext ctx,
+            final HttpRequest req, final FullHttpResponse res) {
         // Generate an error page if response getStatus code is not OK (200).
         if (res.getStatus().code() != 200) {
             ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(),
@@ -141,8 +140,8 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
      * @param frame
      *            {@link WebSocketFrame}
      */
-    private void handleWebSocketFrame(ChannelHandlerContext ctx,
-            WebSocketFrame frame) throws IOException {
+    private void handleWebSocketFrame(final ChannelHandlerContext ctx,
+            final WebSocketFrame frame) throws IOException {
         if (frame instanceof CloseWebSocketFrame) {
             handshaker.close(ctx.channel(),
                     (CloseWebSocketFrame) frame.retain());
@@ -164,7 +163,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
     }
 
     @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
+    public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause)
             throws Exception {
         if (cause instanceof java.nio.channels.ClosedChannelException == false) {
             // cause.printStackTrace();
@@ -179,7 +178,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
      *            HTTP request from which the location will be returned
      * @return String representation of web socket location.
      */
-    private static String getWebSocketLocation(HttpRequest req) {
+    private static String getWebSocketLocation(final HttpRequest req) {
         return "http://" + req.headers().get(HOST) + req.getUri();
     }
 
index 1ec7253b8d595dea9ef3e62a05decbd224178975..93d32a14992e9df0209be9409cbea91074db514a 100644 (file)
@@ -116,6 +116,75 @@ public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader
 
     }
 
+    static class ComplexAnyXmlVerifier extends LeafVerifier {
+
+        ComplexAnyXmlVerifier() {
+            super( null, JsonToken.BEGIN_OBJECT );
+        }
+
+        @Override
+        void verify( JsonReader reader, String keyName ) throws IOException {
+
+            reader.beginObject();
+            String innerKey = reader.nextName();
+            assertEquals( "Json reader child key for " + keyName, "data", innerKey );
+            assertEquals( "Json token type for key " + innerKey, JsonToken.BEGIN_OBJECT, reader.peek() );
+
+            reader.beginObject();
+            verifyLeaf( reader, innerKey, "leaf1", "leaf1-value" );
+            verifyLeaf( reader, innerKey, "leaf2", "leaf2-value" );
+
+            String nextName = reader.nextName();
+            assertEquals( "Json reader child key for " + innerKey, "leaf-list", nextName );
+            reader.beginArray();
+            assertEquals( "Json value for key " + nextName, "leaf-list-value1", reader.nextString() );
+            assertEquals( "Json value for key " + nextName, "leaf-list-value2", reader.nextString() );
+            reader.endArray();
+
+            nextName = reader.nextName();
+            assertEquals( "Json reader child key for " + innerKey, "list", nextName );
+            reader.beginArray();
+            verifyNestedLists( reader, 1 );
+            verifyNestedLists( reader, 3 );
+            reader.endArray();
+
+            reader.endObject();
+            reader.endObject();
+        }
+
+        void verifyNestedLists( JsonReader reader, int leafNum ) throws IOException {
+            reader.beginObject();
+
+            String nextName = reader.nextName();
+            assertEquals( "Json reader next name", "nested-list", nextName );
+
+            reader.beginArray();
+
+            reader.beginObject();
+            verifyLeaf( reader, "nested-list", "nested-leaf", "nested-value" + leafNum++ );
+            reader.endObject();
+
+            reader.beginObject();
+            verifyLeaf( reader, "nested-list", "nested-leaf", "nested-value" + leafNum );
+            reader.endObject();
+
+            reader.endArray();
+            reader.endObject();
+        }
+
+        void verifyLeaf( JsonReader reader, String parent, String name, String value ) throws IOException {
+            String nextName = reader.nextName();
+            assertEquals( "Json reader child key for " + parent, name, nextName );
+            assertEquals( "Json token type for key " + parent, JsonToken.STRING, reader.peek() );
+            assertEquals( "Json value for key " + nextName, value, reader.nextString() );
+        }
+
+        @Override
+        Object getActualValue( JsonReader reader ) throws IOException {
+            return null;
+        }
+    }
+
     @BeforeClass
     public static void initialize() {
         dataLoad("/cnsn-to-json/simple-data-types");
@@ -208,6 +277,9 @@ public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader
         expectedMap.put( "lfunion14", new StringVerifier( "zero" ) );
         expectedMap.put( "lfempty", new EmptyVerifier() );
         expectedMap.put( "identityref1", new StringVerifier( "simple-data-types:iden" ) );
+        expectedMap.put( "complex-any", new ComplexAnyXmlVerifier() );
+        expectedMap.put( "simple-any", new StringVerifier( "simple" ) );
+        expectedMap.put( "empty-any", new StringVerifier( "" ) );
 
         while (jReader.hasNext()) {
             String keyName = jReader.nextName();
index 42e1e3f739a002259e4b833dd1e9dbafdb373b78..24dba17c90cdff4e9a87d0a059160357dcbaad88 100644 (file)
@@ -12,15 +12,14 @@ import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.util.Collections;
-
 import javax.ws.rs.WebApplicationException;
-
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.DummyType;
 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.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
@@ -28,6 +27,7 @@ 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.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
 import org.slf4j.Logger;
@@ -65,9 +65,9 @@ public class CnSnToJsonNotExistingLeafTypeTest extends YangAndXmlAndDataSchemaLo
 
     private DataSchemaNode prepareDataSchemaNode() {
         ContainerSchemaNodeBuilder contBuild = new ContainerSchemaNodeBuilder("module", 1, TestUtils.buildQName("cont",
-                "simple:uri", "2012-12-17"), null);
+                "simple:uri", "2012-12-17"), SchemaPath.create(true, QName.create("dummy")));
         LeafSchemaNodeBuilder leafBuild = new LeafSchemaNodeBuilder("module", 2, TestUtils.buildQName("lf1",
-                "simple:uri", "2012-12-17"), null);
+                "simple:uri", "2012-12-17"), SchemaPath.create(true, QName.create("dummy")));
         leafBuild.setType(new DummyType());
         leafBuild.setConfiguration(true);
 
index 9318af529b74c6ec4097331f6e374b7aa7038e9b..30dc1161bf43841888f4d823e4c50450bf93a199 100644 (file)
@@ -226,7 +226,7 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
         BitsTypeDefinition.Bit mockBit1 = mock( BitsTypeDefinition.Bit.class );
         when( mockBit1.getName() ).thenReturn( "first" );
         BitsTypeDefinition.Bit mockBit2 = mock( BitsTypeDefinition.Bit.class );
-        when( mockBit1.getName() ).thenReturn( "second" );
+        when( mockBit2.getName() ).thenReturn( "second" );
         List<BitsTypeDefinition.Bit> bitList = Lists.newArrayList( mockBit1, mockBit2 );
 
         List<TypeDefinition<?>> types = Lists.<TypeDefinition<?>>newArrayList(
index ddab7004408f4d60aa3e89f8660f8aa9749bce7b..19ca812f8e9a90c1aad698be0df347b2b651b26f 100644 (file)
@@ -7,19 +7,20 @@
  */
 
 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.Matchers.any;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
 import java.util.Map;
 import java.util.concurrent.Future;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.InOrder;
@@ -42,9 +43,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.Futures;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 
 /**
  * Unit tests for BrokerFacade.
@@ -275,6 +274,8 @@ public class BrokerFacadeTest {
         Future<RpcResult<TransactionStatus>> expFuture =  Futures.immediateFuture( null );
 
         when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+        when(mockTransaction.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(
+                ImmutableCompositeNode.builder().toInstance());
         mockTransaction.removeConfigurationData( instanceID );
         when( mockTransaction.commit() ).thenReturn( expFuture );
 
@@ -294,6 +295,8 @@ public class BrokerFacadeTest {
         Future<RpcResult<TransactionStatus>> expFuture =  Futures.immediateFuture( null );
 
         when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+        when(mockTransaction.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(
+                ImmutableCompositeNode.builder().toInstance());
         mockTransaction.removeConfigurationData( instanceID );
         when( mockTransaction.commit() ).thenReturn( expFuture );
 
index 07d781028b99feaa03cd8dc610f499f63a0ca1dc..3f2c212bd87785ccbf021749d9bddb1db069bf6f 100644 (file)
@@ -226,7 +226,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
 
         pathArguments.add(new NodeIdentifier(new QName(new URI("augment:augment:module"), "lf112")));
 
-        return new InstanceIdentifier(pathArguments);
+        return InstanceIdentifier.create(pathArguments);
     }
 
     private InstanceIdentifier createInstanceIdentifierWithLeafList() throws URISyntaxException {
@@ -235,7 +235,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch
         pathArguments.add(new NodeIdentifier(new QName(new URI("instance:identifier:module"), "cont1")));
         pathArguments.add(new NodeWithValue(new QName(new URI("augment:module:leaf:list"), "lflst11"), "lflst11_1"));
 
-        return new InstanceIdentifier(pathArguments);
+        return InstanceIdentifier.create(pathArguments);
     }
 
 }
index 22b34a44203e0ba67384f6635e7b55bb0dc4e2e5..19a7eff480dece01d1e9ff5743b3ef9c5fa94c5e 100644 (file)
@@ -11,16 +11,14 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
-public class DummyFuture implements Future<RpcResult<TransactionStatus>> {
+public class DummyFuture<T> implements Future<RpcResult<T>> {
 
     private final boolean cancel;
     private final boolean isCancelled;
     private final boolean isDone;
-    private final RpcResult<TransactionStatus> result;
+    private final RpcResult<T> result;
 
     public DummyFuture() {
         cancel = false;
@@ -29,16 +27,13 @@ public class DummyFuture implements Future<RpcResult<TransactionStatus>> {
         result = null;
     }
 
-    private DummyFuture(final Builder builder) {
+    private DummyFuture(final Builder<T> builder) {
         cancel = builder.cancel;
         isCancelled = builder.isCancelled;
         isDone = builder.isDone;
         result = builder.result;
     }
 
-    public static Builder builder() {
-        return new DummyFuture.Builder();
-    }
 
     @Override
     public boolean cancel(final boolean mayInterruptIfRunning) {
@@ -56,45 +51,45 @@ public class DummyFuture implements Future<RpcResult<TransactionStatus>> {
     }
 
     @Override
-    public RpcResult<TransactionStatus> get() throws InterruptedException, ExecutionException {
+    public RpcResult<T> get() throws InterruptedException, ExecutionException {
         return result;
     }
 
     @Override
-    public RpcResult<TransactionStatus> get(final long timeout, final TimeUnit unit) throws InterruptedException,
+    public RpcResult<T> get(final long timeout, final TimeUnit unit) throws InterruptedException,
     ExecutionException, TimeoutException {
         return result;
     }
 
-    public static class Builder {
+    public static class Builder<T> {
 
         private boolean cancel;
         private boolean isCancelled;
         private boolean isDone;
-        private RpcResult<TransactionStatus> result;
+        private RpcResult<T> result;
 
-        public Builder cancel(final boolean cancel) {
+        public Builder<T> cancel(final boolean cancel) {
             this.cancel = cancel;
             return this;
         }
 
-        public Builder isCancelled(final boolean isCancelled) {
+        public Builder<T> isCancelled(final boolean isCancelled) {
             this.isCancelled = isCancelled;
             return this;
         }
 
-        public Builder isDone(final boolean isDone) {
+        public Builder<T> isDone(final boolean isDone) {
             this.isDone = isDone;
             return this;
         }
 
-        public Builder rpcResult(final RpcResult<TransactionStatus> result) {
+        public Builder<T> rpcResult(final RpcResult<T> result) {
             this.result = result;
             return this;
         }
 
-        public Future<RpcResult<TransactionStatus>> build() {
-            return new DummyFuture(this);
+        public Future<RpcResult<T>> build() {
+            return new DummyFuture<T>(this);
         }
     }
 }
index 56a58eeadd1f5d80f4dc4f2926c48a9968fbe3c8..e8cbf3140f35f9f750612ddc5c932a8763034a4b 100644 (file)
@@ -17,11 +17,9 @@ import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
 import java.util.Set;
 import java.util.concurrent.Future;
-
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
@@ -85,7 +83,7 @@ public class RestDeleteOperationTest extends JerseyTest {
 
     private Future<RpcResult<TransactionStatus>> createFuture(TransactionStatus statusName) {
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(statusName).build();
-        return DummyFuture.builder().rpcResult(rpcResult).build();
+        return new DummyFuture.Builder<TransactionStatus>().rpcResult(rpcResult).build();
     }
 
 }
index f0a232fba670539c5a872e5894a89bd7c214c778..41a1c3827d21973180e01b7fd3cb11e2e73f993c 100644 (file)
@@ -7,8 +7,8 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
@@ -77,7 +77,7 @@ public class RestGetOperationTest extends JerseyTest {
         Object key;
         Object data; // List for a CompositeNode, value Object for a SimpleNode
 
-        NodeData( Object key, Object data ) {
+        NodeData( final Object key, final Object data ) {
             this.key = key;
             this.data = data;
         }
@@ -186,7 +186,7 @@ public class RestGetOperationTest extends JerseyTest {
      */
     @Test
     public void getDataWithSlashesBehindMountPoint() throws UnsupportedEncodingException, URISyntaxException,
-            ParseException {
+    ParseException {
         InstanceIdentifier awaitedInstanceIdentifier = prepareInstanceIdentifierForList();
         when(
                 brokerFacade.readConfigurationDataBehindMountPoint(any(MountInstance.class),
@@ -214,7 +214,7 @@ public class RestGetOperationTest extends JerseyTest {
         parameters.add(new InstanceIdentifier.NodeIdentifier(qNameCont));
         parameters.add(new InstanceIdentifier.NodeIdentifierWithPredicates(qNameList, qNameKeyList,
                 "GigabitEthernet0/0/0/0"));
-        return new InstanceIdentifier(parameters);
+        return InstanceIdentifier.create(parameters);
     }
 
     @Test
@@ -356,7 +356,7 @@ public class RestGetOperationTest extends JerseyTest {
 
     }
 
-    private Matcher validateOperationsResponseJson(String searchIn, String rpcName, String moduleName) {
+    private Matcher validateOperationsResponseJson(final String searchIn, final String rpcName, final String moduleName) {
         StringBuilder regex = new StringBuilder();
         regex.append("^");
 
@@ -390,7 +390,7 @@ public class RestGetOperationTest extends JerseyTest {
 
     }
 
-    private Matcher validateOperationsResponseXml(String searchIn, String rpcName, String namespace) {
+    private Matcher validateOperationsResponseXml(final String searchIn, final String rpcName, final String namespace) {
         StringBuilder regex = new StringBuilder();
 
         regex.append("^");
@@ -448,11 +448,11 @@ public class RestGetOperationTest extends JerseyTest {
         assertTrue(
                 "module1-behind-mount-point in json wasn't found",
                 prepareXmlRegex("module1-behind-mount-point", "2014-02-03", "module:1:behind:mount:point", responseBody)
-                        .find());
+                .find());
         assertTrue(
                 "module2-behind-mount-point in json wasn't found",
                 prepareXmlRegex("module2-behind-mount-point", "2014-02-04", "module:2:behind:mount:point", responseBody)
-                        .find());
+                .find());
 
     }
 
@@ -488,13 +488,13 @@ public class RestGetOperationTest extends JerseyTest {
         assertTrue(
                 "module1-behind-mount-point in json wasn't found",
                 prepareXmlRegex("module1-behind-mount-point", "2014-02-03", "module:1:behind:mount:point", responseBody)
-                        .find());
+                .find());
         split = responseBody.split("<module");
         assertEquals("<module element is returned more then once", 2, split.length);
 
     }
 
-    private void validateModulesResponseXml(Response response) {
+    private void validateModulesResponseXml(final Response response) {
         assertEquals(200, response.getStatus());
         String responseBody = response.readEntity(String.class);
 
@@ -506,7 +506,7 @@ public class RestGetOperationTest extends JerseyTest {
                 .find());
     }
 
-    private void validateModulesResponseJson(Response response) {
+    private void validateModulesResponseJson(final Response response) {
         assertEquals(200, response.getStatus());
         String responseBody = response.readEntity(String.class);
 
@@ -518,7 +518,7 @@ public class RestGetOperationTest extends JerseyTest {
                 .find());
     }
 
-    private Matcher prepareJsonRegex(String module, String revision, String namespace, String searchIn) {
+    private Matcher prepareJsonRegex(final String module, final String revision, final String namespace, final String searchIn) {
         StringBuilder regex = new StringBuilder();
         regex.append("^");
 
@@ -544,7 +544,7 @@ public class RestGetOperationTest extends JerseyTest {
 
     }
 
-    private Matcher prepareXmlRegex(String module, String revision, String namespace, String searchIn) {
+    private Matcher prepareXmlRegex(final String module, final String revision, final String namespace, final String searchIn) {
         StringBuilder regex = new StringBuilder();
         regex.append("^");
 
@@ -572,13 +572,13 @@ public class RestGetOperationTest extends JerseyTest {
         return ptrn.matcher(searchIn);
     }
 
-    private void prepareMockForModulesTest(ControllerContext mockedControllerContext) throws FileNotFoundException {
+    private void prepareMockForModulesTest(final ControllerContext mockedControllerContext) throws FileNotFoundException {
         SchemaContext schemaContext = TestUtils.loadSchemaContext("/modules");
         mockedControllerContext.setGlobalSchema(schemaContext);
         // when(mockedControllerContext.getGlobalSchema()).thenReturn(schemaContext);
     }
 
-    private int get(String uri, String mediaType) {
+    private int get(final String uri, final String mediaType) {
         return target(uri).request(mediaType).get().getStatus();
     }
 
@@ -621,179 +621,179 @@ public class RestGetOperationTest extends JerseyTest {
         ControllerContext.getInstance().setGlobalSchema( schemaContextModules );
 
         CompositeNode depth1Cont = toCompositeNode(
-            toCompositeNodeData( toNestedQName( "depth1-cont" ),
-                toCompositeNodeData( toNestedQName( "depth2-cont1" ),
-                    toCompositeNodeData( toNestedQName( "depth3-cont1" ),
-                        toCompositeNodeData( toNestedQName( "depth4-cont1" ),
-                            toSimpleNodeData( toNestedQName( "depth5-leaf1" ), "depth5-leaf1-value" )
-                        ),
-                        toSimpleNodeData( toNestedQName( "depth4-leaf1" ), "depth4-leaf1-value" )
-                    ),
-                    toSimpleNodeData( toNestedQName( "depth3-leaf1" ), "depth3-leaf1-value" )
-                ),
-                toCompositeNodeData( toNestedQName( "depth2-cont2" ),
-                    toCompositeNodeData( toNestedQName( "depth3-cont2" ),
-                        toCompositeNodeData( toNestedQName( "depth4-cont2" ),
-                            toSimpleNodeData( toNestedQName( "depth5-leaf2" ), "depth5-leaf2-value" )
-                        ),
-                        toSimpleNodeData( toNestedQName( "depth4-leaf2" ), "depth4-leaf2-value" )
-                    ),
-                    toSimpleNodeData( toNestedQName( "depth3-leaf2" ), "depth3-leaf2-value" )
-                ),
-                toSimpleNodeData( toNestedQName( "depth2-leaf1" ), "depth2-leaf1-value" )
-            ) );
+                toCompositeNodeData( toNestedQName( "depth1-cont" ),
+                        toCompositeNodeData( toNestedQName( "depth2-cont1" ),
+                                toCompositeNodeData( toNestedQName( "depth3-cont1" ),
+                                        toCompositeNodeData( toNestedQName( "depth4-cont1" ),
+                                                toSimpleNodeData( toNestedQName( "depth5-leaf1" ), "depth5-leaf1-value" )
+                                                ),
+                                                toSimpleNodeData( toNestedQName( "depth4-leaf1" ), "depth4-leaf1-value" )
+                                        ),
+                                        toSimpleNodeData( toNestedQName( "depth3-leaf1" ), "depth3-leaf1-value" )
+                                ),
+                                toCompositeNodeData( toNestedQName( "depth2-cont2" ),
+                                        toCompositeNodeData( toNestedQName( "depth3-cont2" ),
+                                                toCompositeNodeData( toNestedQName( "depth4-cont2" ),
+                                                        toSimpleNodeData( toNestedQName( "depth5-leaf2" ), "depth5-leaf2-value" )
+                                                        ),
+                                                        toSimpleNodeData( toNestedQName( "depth4-leaf2" ), "depth4-leaf2-value" )
+                                                ),
+                                                toSimpleNodeData( toNestedQName( "depth3-leaf2" ), "depth3-leaf2-value" )
+                                        ),
+                                        toSimpleNodeData( toNestedQName( "depth2-leaf1" ), "depth2-leaf1-value" )
+                        ) );
 
         when( brokerFacade.readConfigurationData( any( InstanceIdentifier.class ) ) )
-            .thenReturn( depth1Cont );
+        .thenReturn( depth1Cont );
 
         // Test config with depth 1
 
         Response response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "1" )
-                                .request( "application/xml" ).get();
+                .request( "application/xml" ).get();
 
         verifyXMLResponse( response, expectEmptyContainer( "depth1-cont" ) );
 
         // Test config with depth 2
 
         response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "2" )
-                       .request( "application/xml" ).get();
+                .request( "application/xml" ).get();
 
-//        String xml="<depth1-cont><depth2-cont1/><depth2-cont2/><depth2-leaf1>depth2-leaf1-value</depth2-leaf1></depth1-cont>";
-//        Response mr=mock(Response.class);
-//        when(mr.getEntity()).thenReturn( new java.io.StringBufferInputStream(xml) );
+        //        String xml="<depth1-cont><depth2-cont1/><depth2-cont2/><depth2-leaf1>depth2-leaf1-value</depth2-leaf1></depth1-cont>";
+        //        Response mr=mock(Response.class);
+        //        when(mr.getEntity()).thenReturn( new java.io.StringBufferInputStream(xml) );
 
         verifyXMLResponse( response,
-            expectContainer( "depth1-cont",
-                expectEmptyContainer( "depth2-cont1" ),
-                expectEmptyContainer( "depth2-cont2" ),
-                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
-            ) );
+                expectContainer( "depth1-cont",
+                        expectEmptyContainer( "depth2-cont1" ),
+                        expectEmptyContainer( "depth2-cont2" ),
+                        expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+                        ) );
 
         // Test config with depth 3
 
         response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "3" )
-                       .request( "application/xml" ).get();
+                .request( "application/xml" ).get();
 
         verifyXMLResponse( response,
-            expectContainer( "depth1-cont",
-                expectContainer( "depth2-cont1",
-                    expectEmptyContainer( "depth3-cont1" ),
-                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
-                ),
-                expectContainer( "depth2-cont2",
-                    expectEmptyContainer( "depth3-cont2" ),
-                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
-                ),
-                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
-           ) );
+                expectContainer( "depth1-cont",
+                        expectContainer( "depth2-cont1",
+                                expectEmptyContainer( "depth3-cont1" ),
+                                expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                                ),
+                                expectContainer( "depth2-cont2",
+                                        expectEmptyContainer( "depth3-cont2" ),
+                                        expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                                        ),
+                                        expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+                        ) );
 
         // Test config with depth 4
 
         response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "4" )
-                      .request( "application/xml" ).get();
+                .request( "application/xml" ).get();
 
         verifyXMLResponse( response,
-            expectContainer( "depth1-cont",
-                expectContainer( "depth2-cont1",
-                    expectContainer( "depth3-cont1",
-                        expectEmptyContainer( "depth4-cont1" ),
-                        expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
-                    ),
-                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
-                ),
-                expectContainer( "depth2-cont2",
-                    expectContainer( "depth3-cont2",
-                        expectEmptyContainer( "depth4-cont2" ),
-                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
-                    ),
-                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
-                ),
-                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
-            ) );
+                expectContainer( "depth1-cont",
+                        expectContainer( "depth2-cont1",
+                                expectContainer( "depth3-cont1",
+                                        expectEmptyContainer( "depth4-cont1" ),
+                                        expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                                        ),
+                                        expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                                ),
+                                expectContainer( "depth2-cont2",
+                                        expectContainer( "depth3-cont2",
+                                                expectEmptyContainer( "depth4-cont2" ),
+                                                expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
+                                                ),
+                                                expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                                        ),
+                                        expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+                        ) );
 
         // Test config with depth 5
 
         response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "5" )
-                       .request( "application/xml" ).get();
+                .request( "application/xml" ).get();
 
         verifyXMLResponse( response,
-            expectContainer( "depth1-cont",
-                expectContainer( "depth2-cont1",
-                    expectContainer( "depth3-cont1",
-                        expectContainer( "depth4-cont1",
-                            expectLeaf( "depth5-leaf1", "depth5-leaf1-value" )
-                        ),
-                        expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
-                    ),
-                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
-                ),
-                expectContainer( "depth2-cont2",
-                    expectContainer( "depth3-cont2",
-                        expectContainer( "depth4-cont2",
-                            expectLeaf( "depth5-leaf2", "depth5-leaf2-value" )
-                        ),
-                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
-                    ),
-                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
-                ),
-                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
-            ) );
+                expectContainer( "depth1-cont",
+                        expectContainer( "depth2-cont1",
+                                expectContainer( "depth3-cont1",
+                                        expectContainer( "depth4-cont1",
+                                                expectLeaf( "depth5-leaf1", "depth5-leaf1-value" )
+                                                ),
+                                                expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                                        ),
+                                        expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                                ),
+                                expectContainer( "depth2-cont2",
+                                        expectContainer( "depth3-cont2",
+                                                expectContainer( "depth4-cont2",
+                                                        expectLeaf( "depth5-leaf2", "depth5-leaf2-value" )
+                                                        ),
+                                                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
+                                                ),
+                                                expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                                        ),
+                                        expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+                        ) );
 
         // Test config with depth unbounded
 
         response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "unbounded" )
-                       .request( "application/xml" ).get();
+                .request( "application/xml" ).get();
 
         verifyXMLResponse( response,
-            expectContainer( "depth1-cont",
-                expectContainer( "depth2-cont1",
-                    expectContainer( "depth3-cont1",
-                        expectContainer( "depth4-cont1",
-                            expectLeaf( "depth5-leaf1", "depth5-leaf1-value" )
-                        ),
-                        expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
-                    ),
-                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
-                ),
-                expectContainer( "depth2-cont2",
-                    expectContainer( "depth3-cont2",
-                        expectContainer( "depth4-cont2",
-                            expectLeaf( "depth5-leaf2", "depth5-leaf2-value" )
-                        ),
-                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
-                    ),
-                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
-                ),
-                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
-            ) );
+                expectContainer( "depth1-cont",
+                        expectContainer( "depth2-cont1",
+                                expectContainer( "depth3-cont1",
+                                        expectContainer( "depth4-cont1",
+                                                expectLeaf( "depth5-leaf1", "depth5-leaf1-value" )
+                                                ),
+                                                expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                                        ),
+                                        expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                                ),
+                                expectContainer( "depth2-cont2",
+                                        expectContainer( "depth3-cont2",
+                                                expectContainer( "depth4-cont2",
+                                                        expectLeaf( "depth5-leaf2", "depth5-leaf2-value" )
+                                                        ),
+                                                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
+                                                ),
+                                                expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                                        ),
+                                        expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+                        ) );
 
         // Test operational
 
         CompositeNode depth2Cont1 = toCompositeNode(
-            toCompositeNodeData( toNestedQName( "depth2-cont1" ),
-                toCompositeNodeData( toNestedQName( "depth3-cont1" ),
-                    toCompositeNodeData( toNestedQName( "depth4-cont1" ),
-                        toSimpleNodeData( toNestedQName( "depth5-leaf1" ), "depth5-leaf1-value" )
-                    ),
-                    toSimpleNodeData( toNestedQName( "depth4-leaf1" ), "depth4-leaf1-value" )
-                ),
-                toSimpleNodeData( toNestedQName( "depth3-leaf1" ), "depth3-leaf1-value" )
-            ) );
+                toCompositeNodeData( toNestedQName( "depth2-cont1" ),
+                        toCompositeNodeData( toNestedQName( "depth3-cont1" ),
+                                toCompositeNodeData( toNestedQName( "depth4-cont1" ),
+                                        toSimpleNodeData( toNestedQName( "depth5-leaf1" ), "depth5-leaf1-value" )
+                                        ),
+                                        toSimpleNodeData( toNestedQName( "depth4-leaf1" ), "depth4-leaf1-value" )
+                                ),
+                                toSimpleNodeData( toNestedQName( "depth3-leaf1" ), "depth3-leaf1-value" )
+                        ) );
 
         when( brokerFacade.readOperationalData( any( InstanceIdentifier.class ) ) )
-             .thenReturn( depth2Cont1 );
+        .thenReturn( depth2Cont1 );
 
         response = target( "/operational/nested-module:depth1-cont/depth2-cont1" )
-                       .queryParam( "depth", "3" ).request( "application/xml" ).get();
+                .queryParam( "depth", "3" ).request( "application/xml" ).get();
 
         verifyXMLResponse( response,
-            expectContainer( "depth2-cont1",
-                expectContainer( "depth3-cont1",
-                    expectEmptyContainer( "depth4-cont1" ),
-                    expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
-                ),
-                expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
-            ) );
+                expectContainer( "depth2-cont1",
+                        expectContainer( "depth3-cont1",
+                                expectEmptyContainer( "depth4-cont1" ),
+                                expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                                ),
+                                expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                        ) );
     }
 
     @Test
@@ -805,12 +805,12 @@ public class RestGetOperationTest extends JerseyTest {
         paramMap.putSingle( "depth", "1o" );
         UriInfo mockInfo = mock( UriInfo.class );
         when( mockInfo.getQueryParameters( false ) ).thenAnswer(
-            new Answer<MultivaluedMap<String,String>>() {
-                @Override
-                public MultivaluedMap<String, String> answer( InvocationOnMock invocation ) {
-                    return paramMap;
-                }
-            } );
+                new Answer<MultivaluedMap<String,String>>() {
+                    @Override
+                    public MultivaluedMap<String, String> answer( final InvocationOnMock invocation ) {
+                        return paramMap;
+                    }
+                } );
 
         getDataWithInvalidDepthParameterTest( mockInfo );
 
@@ -821,18 +821,18 @@ public class RestGetOperationTest extends JerseyTest {
         getDataWithInvalidDepthParameterTest( mockInfo );
     }
 
-    private void getDataWithInvalidDepthParameterTest( UriInfo uriInfo ) {
+    private void getDataWithInvalidDepthParameterTest( final UriInfo uriInfo ) {
         try {
             restconfImpl.readConfigurationData( "nested-module:depth1-cont", uriInfo );
             fail( "Expected RestconfDocumentedException" );
         }
         catch( RestconfDocumentedException e ) {
             assertTrue( "Unexpected error message: " + e.getErrors().get( 0 ).getErrorMessage(),
-                        e.getErrors().get( 0 ).getErrorMessage().contains( "depth" ) );
+                    e.getErrors().get( 0 ).getErrorMessage().contains( "depth" ) );
         }
     }
 
-    private void verifyXMLResponse( Response response, NodeData nodeData ) {
+    private void verifyXMLResponse( final Response response, final NodeData nodeData ) {
 
         Document doc = TestUtils.loadDocumentFrom( (InputStream) response.getEntity() );
         assertNotNull( "Could not parse XML document", doc );
@@ -843,14 +843,14 @@ public class RestGetOperationTest extends JerseyTest {
     }
 
     @SuppressWarnings("unchecked")
-    private void verifyContainerElement( Element element, NodeData nodeData ) {
+    private void verifyContainerElement( final Element element, final NodeData nodeData ) {
 
         assertEquals( "Element local name", nodeData.key, element.getNodeName() );
 
         NodeList childNodes = element.getChildNodes();
         if( nodeData.data == null ) { // empty container
             assertTrue( "Expected no child elements for \"" + element.getNodeName() + "\"",
-                        childNodes.getLength() == 0 );
+                    childNodes.getLength() == 0 );
             return;
         }
 
@@ -868,41 +868,41 @@ public class RestGetOperationTest extends JerseyTest {
             Element actualElement = (Element)actualChild;
             NodeData expChild = expChildMap.remove( actualElement.getNodeName() );
             assertNotNull( "Unexpected child element for parent \"" + element.getNodeName() +
-                           "\": " + actualElement.getNodeName(), expChild );
+                    "\": " + actualElement.getNodeName(), expChild );
 
             if( expChild.data == null || expChild.data instanceof List ) {
                 verifyContainerElement( actualElement, expChild );
             }
             else {
                 assertEquals( "Text content for element: " + actualElement.getNodeName(),
-                              expChild.data, actualElement.getTextContent() );
+                        expChild.data, actualElement.getTextContent() );
             }
         }
 
         if( !expChildMap.isEmpty() ) {
             fail( "Missing elements for parent \"" + element.getNodeName() +
-                  "\": " + expChildMap.keySet() );
+                    "\": " + expChildMap.keySet() );
         }
     }
 
-    private NodeData expectContainer( String name, NodeData... childData ) {
+    private NodeData expectContainer( final String name, final NodeData... childData ) {
         return new NodeData( name, Lists.newArrayList( childData ) );
     }
 
-    private NodeData expectEmptyContainer( String name ) {
+    private NodeData expectEmptyContainer( final String name ) {
         return new NodeData( name, null );
     }
 
-    private NodeData expectLeaf( String name, Object value ) {
+    private NodeData expectLeaf( final String name, final Object value ) {
         return new NodeData( name, value );
     }
 
-    private QName toNestedQName( String localName ) {
+    private QName toNestedQName( final String localName ) {
         return QName.create( "urn:nested:module", "2014-06-3", localName );
     }
 
     @SuppressWarnings("unchecked")
-    private CompositeNode toCompositeNode( NodeData nodeData ) {
+    private CompositeNode toCompositeNode( final NodeData nodeData ) {
         CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
         builder.setQName( (QName) nodeData.key );
 
@@ -918,11 +918,11 @@ public class RestGetOperationTest extends JerseyTest {
         return builder.toInstance();
     }
 
-    private NodeData toCompositeNodeData( QName key, NodeData... childData ) {
+    private NodeData toCompositeNodeData( final QName key, final NodeData... childData ) {
         return new NodeData( key, Lists.newArrayList( childData ) );
     }
 
-    private NodeData toSimpleNodeData( QName key, Object value ) {
+    private NodeData toSimpleNodeData( final QName key, final Object value ) {
         return new NodeData( key, value );
     }
 }
index cfbc9fdb767c2c9c8fb8bc7e8d4954f5e5e210e8..5b36fd52f78c329649fb3d593034d6bf028031f0 100644 (file)
@@ -15,25 +15,29 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.XML;
 
+import com.google.common.util.concurrent.Futures;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Future;
-
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
-
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountService;
 import org.opendaylight.controller.sal.rest.api.Draft02;
@@ -47,14 +51,15 @@ import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.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;
@@ -102,12 +107,12 @@ public class RestPostOperationTest extends JerseyTest {
         resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
                 JsonToCompositeNodeProvider.INSTANCE);
-        resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
+        resourceConfig.registerClasses(RestconfDocumentedExceptionMapper.class);
         return resourceConfig;
     }
 
     @Test
-    public void postOperationsStatusCodes() throws UnsupportedEncodingException {
+    public void postOperationsStatusCodes() throws IOException {
         controllerContext.setSchemas(schemaContextTestModule);
         mockInvokeRpc(cnSnDataOutput, true);
         String uri = "/operations/test-module:rpc-test";
@@ -119,6 +124,12 @@ public class RestPostOperationTest extends JerseyTest {
         mockInvokeRpc(null, false);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
+        List<RpcError> rpcErrors = new ArrayList<>();
+        rpcErrors.add( RpcErrors.getRpcError("applicationTag1", "tag1", "info1", ErrorSeverity.ERROR, "message1", ErrorType.RPC, null));
+        rpcErrors.add( RpcErrors.getRpcError("applicationTag2", "tag2", "info2", ErrorSeverity.WARNING, "message2", ErrorType.PROTOCOL, null));
+        mockInvokeRpc(null, false, rpcErrors);
+        assertEquals(500,post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
+
         uri = "/operations/test-module:rpc-wrongtest";
         assertEquals(400, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
     }
@@ -150,7 +161,7 @@ public class RestPostOperationTest extends JerseyTest {
         mockCommitConfigurationDataPostMethod(TransactionStatus.FAILED);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
 
-        assertEquals( 400, post(uri, MediaType.APPLICATION_JSON, "" ));
+        assertEquals(400, post(uri, MediaType.APPLICATION_JSON, ""));
     }
 
     @Test
@@ -158,7 +169,8 @@ public class RestPostOperationTest extends JerseyTest {
         controllerContext.setSchemas(schemaContextYangsIetf);
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
                 TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
+                rpcResult).build();
         when(
                 brokerFacade.commitConfigurationDataPostBehindMountPoint(any(MountInstance.class),
                         any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
@@ -175,14 +187,23 @@ public class RestPostOperationTest extends JerseyTest {
         uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont";
         assertEquals(204, post(uri, Draft02.MediaTypes.DATA + XML, xmlData3));
 
-        assertEquals( 400, post(uri, MediaType.APPLICATION_JSON, "" ));
+        assertEquals(400, post(uri, MediaType.APPLICATION_JSON, ""));
     }
 
-    private void mockInvokeRpc(CompositeNode result, boolean sucessful) {
-        RpcResult<CompositeNode> rpcResult = new DummyRpcResult.Builder<CompositeNode>().result(result)
-                .isSuccessful(sucessful).build();
+    private void mockInvokeRpc(CompositeNode result, boolean sucessful, Collection<RpcError> errors) {
+
+        DummyRpcResult.Builder<CompositeNode> builder = new DummyRpcResult.Builder<CompositeNode>().result(result)
+                .isSuccessful(sucessful);
+        if (!errors.isEmpty()) {
+            builder.errors(errors);
+        }
+        RpcResult<CompositeNode> rpcResult = builder.build();
         when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class)))
-            .thenReturn(Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ));
+                .thenReturn(Futures.<RpcResult<CompositeNode>> immediateFuture(rpcResult));
+    }
+
+    private void mockInvokeRpc(CompositeNode result, boolean sucessful) {
+        mockInvokeRpc(result, sucessful, Collections.<RpcError> emptyList());
     }
 
     private void mockCommitConfigurationDataPostMethod(TransactionStatus statusName) {
@@ -190,9 +211,9 @@ public class RestPostOperationTest extends JerseyTest {
                 .build();
         Future<RpcResult<TransactionStatus>> dummyFuture = null;
         if (statusName != null) {
-            dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+            dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(rpcResult).build();
         } else {
-            dummyFuture = DummyFuture.builder().build();
+            dummyFuture = new DummyFuture.Builder<TransactionStatus>().build();
         }
 
         when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
@@ -204,7 +225,8 @@ public class RestPostOperationTest extends JerseyTest {
         initMocking();
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
                 TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
+                rpcResult).build();
 
         when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
                 .thenReturn(dummyFuture);
index 77b39b73529dca04ee8b6279b824c01a4361bf25..44b5f491d66ff71f1ca2ea53196f5c4db7536f8c 100644 (file)
@@ -18,12 +18,10 @@ import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URISyntaxException;
 import java.util.concurrent.Future;
-
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
@@ -88,7 +86,7 @@ public class RestPutOperationTest extends JerseyTest {
         resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
                 JsonToCompositeNodeProvider.INSTANCE);
-        resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
+        resourceConfig.registerClasses(RestconfDocumentedExceptionMapper.class);
         return resourceConfig;
     }
 
@@ -104,14 +102,15 @@ public class RestPutOperationTest extends JerseyTest {
         mockCommitConfigurationDataPutMethod(TransactionStatus.FAILED);
         assertEquals(500, put(uri, MediaType.APPLICATION_XML, xmlData));
 
-        assertEquals( 400, put(uri, MediaType.APPLICATION_JSON, "" ));
+        assertEquals(400, put(uri, MediaType.APPLICATION_JSON, ""));
     }
 
     @Test
     public void putConfigStatusCodesEmptyBody() throws UnsupportedEncodingException {
         String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
-        Response resp = target(uri).request( MediaType.APPLICATION_JSON).put(Entity.entity( "", MediaType.APPLICATION_JSON));
-        assertEquals( 400, put(uri, MediaType.APPLICATION_JSON, "" ));
+        Response resp = target(uri).request(MediaType.APPLICATION_JSON).put(
+                Entity.entity("", MediaType.APPLICATION_JSON));
+        assertEquals(400, put(uri, MediaType.APPLICATION_JSON, ""));
     }
 
     @Test
@@ -120,7 +119,8 @@ public class RestPutOperationTest extends JerseyTest {
 
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
                 TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
+                rpcResult).build();
         when(
                 brokerFacade.commitConfigurationDataPutBehindMountPoint(any(MountInstance.class),
                         any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
@@ -143,7 +143,8 @@ public class RestPutOperationTest extends JerseyTest {
     public void putDataMountPointIntoHighestElement() throws UnsupportedEncodingException, URISyntaxException {
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
                 TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
+                rpcResult).build();
         when(
                 brokerFacade.commitConfigurationDataPutBehindMountPoint(any(MountInstance.class),
                         any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
@@ -166,7 +167,8 @@ public class RestPutOperationTest extends JerseyTest {
     private void mockCommitConfigurationDataPutMethod(TransactionStatus statusName) {
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(statusName)
                 .build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
+        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
+                rpcResult).build();
         when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class)))
                 .thenReturn(dummyFuture);
     }
index e146cf8f4fa165a4d3234b616e3bbad1516004e1..c5c459618933af91bb272654d0b40b070fb7ffd3 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.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -18,6 +19,12 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.when;
 
+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;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -29,7 +36,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -41,7 +49,6 @@ 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;
@@ -63,13 +70,6 @@ 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.
  *
@@ -842,6 +842,14 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
                 errorListEntrySet.iterator().next().getKey() );
         assertTrue( "\"error\" Json element is not an Array", errorListElement.isJsonArray() );
 
+        // As a final check, make sure there aren't multiple "error" array elements. Unfortunately,
+        // the call above to getAsJsonObject().entrySet() will out duplicate "error" elements. So
+        // we'll use regex on the json string to verify this.
+
+        Matcher matcher = Pattern.compile( "\"error\"[ ]*:[ ]*\\[", Pattern.DOTALL ).matcher( bos.toString() );
+        assertTrue( "Expected 1 \"error\" element", matcher.find() );
+        assertFalse( "Found multiple \"error\" elements", matcher.find() );
+
         return errorListElement.getAsJsonArray();
     }
 
@@ -850,7 +858,6 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
             final 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();
index 33d4b325bef2c6abc6424c044e8a572acb619ac2..efdb7b240c94a9fb9b47aec81d71ff99e61ebff5 100644 (file)
@@ -14,6 +14,8 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.google.common.collect.Iterables;
+
 import java.io.FileNotFoundException;
 import java.util.Set;
 
@@ -131,7 +133,7 @@ public class URITest {
         initMountService(true);
         InstanceIdWithSchemaNode instanceIdentifier = controllerContext
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/");
-        assertEquals(true, instanceIdentifier.getInstanceIdentifier().getPath().isEmpty());
+        assertTrue(Iterables.isEmpty(instanceIdentifier.getInstanceIdentifier().getPathArguments()));
     }
 
     @Test
@@ -152,7 +154,7 @@ public class URITest {
                 .toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class");
     }
 
-    public void initMountService(boolean withSchema) {
+    public void initMountService(final boolean withSchema) {
         MountService mountService = mock(MountService.class);
         controllerContext.setMountService(mountService);
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
@@ -163,10 +165,11 @@ public class URITest {
         Set<Module> modules2 = TestUtils.loadModulesFrom("/test-config-data/yang2");
         SchemaContext schemaContext2 = TestUtils.loadSchemaContext(modules2);
         MountInstance mountInstance = mock(MountInstance.class);
-        if (withSchema)
+        if (withSchema) {
             when(mountInstance.getSchemaContext()).thenReturn(schemaContext2);
-        else
+        } else {
             when(mountInstance.getSchemaContext()).thenReturn(null);
+        }
         when(mountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
     }
 }
index 9b382d210ebd5de7c88c01a814a16aecc4194a3f..3617ed9fb0d897adaf654ed96f0f98967811d7d2 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.test.structures;
 
+import static org.junit.Assert.assertFalse;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -56,10 +57,14 @@ public class LstItem {
     }
 
     public void addLfLst(LfLst lfLst) {
+        assertFalse( "Found multiple leaf list elements for " + lfLst.getName(),
+                    lfLsts.containsKey( lfLst.getName() ) );
         lfLsts.put(lfLst.getName(), lfLst);
     }
 
     public void addLst(Lst lst) {
+        assertFalse( "Found multiple list elements for " + lst.getName(),
+                     lsts.containsKey( lst.getName() ) );
         lsts.put(lst.getName(), lst);
     }
 
index 9bdea8157910f1db92ce1458876014ece1dc6487..cf6e513b30a1bdc6f10f7725bba73d54aaefac2c 100644 (file)
@@ -269,6 +269,10 @@ module simple-data-types {
         }
     }
          
-         
+       anyxml complex-any;
+       
+       anyxml simple-any;
+       
+       anyxml empty-any;
   }
 }
\ No newline at end of file
index 28d355dbab0a44375559dad7e57670f87cc7b047..ed02ca35f6f13ba2d82bd358e05fb159df537587 100644 (file)
@@ -23,7 +23,6 @@
     <lfenum>enum3</lfenum>
     <lfbits>bit3 bit2</lfbits>
     <lfbinary>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</lfbinary>
-    <lfempty />
     <lfunion1>324</lfunion1>
     <lfunion2>33.3</lfunion2>
     <lfunion3>55</lfunion3>
     <lfunion12>false</lfunion12>
     <lfunion13>b1</lfunion13>
     <lfunion14>zero</lfunion14>
+    <lfempty />
     <identityref1 xmlns:x="simple:data:types">x:iden</identityref1>
-</cont>
\ No newline at end of file
+    <complex-any>
+      <data>
+        <leaf1>leaf1-value</leaf1>
+        <leaf2>leaf2-value</leaf2>
+
+        <leaf-list>leaf-list-value1</leaf-list>
+        <leaf-list>leaf-list-value2</leaf-list>
+
+        <list>
+            <nested-list>
+                <nested-leaf>nested-value1</nested-leaf>
+            </nested-list>
+            <nested-list>
+                <nested-leaf>nested-value2</nested-leaf>
+            </nested-list>
+        </list>
+
+         <list>
+            <nested-list>
+                <nested-leaf>nested-value3</nested-leaf>
+            </nested-list>
+            <nested-list>
+                <nested-leaf>nested-value4</nested-leaf>
+            </nested-list>
+        </list>
+      </data>
+    </complex-any>
+    <simple-any>simple</simple-any>
+    <empty-any></empty-any>
+</cont>
index 79a3434c497e2e3773a75cdaf7238f4cbf0a3b97..0c8b4d5a2ada924025aa40ff805d9c4613606e66 100644 (file)
@@ -36,8 +36,6 @@
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
-      <version>3.3.2</version>
-      <!--$NO-MVN-MAN-VER$ -->
     </dependency>
 
     <!-- Jax rs -->
index 0e929afc8461c5da04bafa6dc44e7c782f83417d..8bac0d211e71cb2d88969c72d9b3f21a9fb00919 100644 (file)
@@ -14,7 +14,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
+import org.apache.commons.lang3.BooleanUtils;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -25,6 +25,7 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -85,6 +86,8 @@ public class ModelGenerator {
     private static final String NUMBER = "number";
     private static final String BOOLEAN = "boolean";
     private static final String STRING = "string";
+  private static final String ID_KEY = "id";
+  private static final String SUB_TYPES_KEY = "subTypes";
 
     private static final Map<Class<? extends TypeDefinition<?>>, String> YANG_TYPE_TO_JSON_TYPE_MAPPING;
 
@@ -115,6 +118,7 @@ public class ModelGenerator {
         JSONObject models = new JSONObject();
         processContainers(module, models);
         processRPCs(module, models);
+    processIdentities(module, models);
         return models;
     }
 
@@ -187,6 +191,58 @@ public class ModelGenerator {
         }
     }
 
+  /**
+   * Processes the 'identity' statement in a yang model
+   * and maps it to a 'model' in the Swagger JSON spec.
+   *
+   * @param module The module from which the identity stmt will be processed
+   * @param models The JSONObject in which the parsed identity will be put as a 'model' obj
+   * @throws JSONException
+   */
+  private void processIdentities(Module module, JSONObject models) throws JSONException {
+
+    String moduleName = module.getName();
+    Set<IdentitySchemaNode> idNodes =  module.getIdentities();
+    _logger.debug("Processing Identities for module {} . Found {} identity statements", moduleName, idNodes.size());
+
+    for(IdentitySchemaNode idNode : idNodes){
+      JSONObject identityObj=new JSONObject();
+      String identityName = idNode.getQName().getLocalName();
+      _logger.debug("Processing Identity: {}", identityName);
+
+      identityObj.put(ID_KEY, identityName);
+      identityObj.put(DESCRIPTION_KEY, idNode.getDescription());
+
+      JSONObject props = new JSONObject();
+      IdentitySchemaNode baseId = idNode.getBaseIdentity();
+
+
+      if(baseId==null) {
+        /**
+         * This is a base identity. So lets see if
+         * it has sub types. If it does, then add them to the model definition.
+         */
+        Set<IdentitySchemaNode> derivedIds = idNode.getDerivedIdentities();
+
+        if(derivedIds != null) {
+          JSONArray subTypes = new JSONArray();
+          for(IdentitySchemaNode derivedId : derivedIds){
+            subTypes.put(derivedId.getQName().getLocalName());
+          }
+          identityObj.put(SUB_TYPES_KEY, subTypes);
+        }
+      } else {
+        /**
+         * This is a derived entity. Add it's base type & move on.
+         */
+        props.put(TYPE_KEY, baseId.getQName().getLocalName());
+      }
+
+      //Add the properties. For a base type, this will be an empty object as required by the Swagger spec.
+      identityObj.put(PROPERTIES_KEY, props);
+      models.put(identityName, identityObj);
+    }
+  }
     /**
      * Processes the container node and populates the moduleJSON
      *
@@ -249,7 +305,7 @@ public class ModelGenerator {
                 if (node instanceof LeafSchemaNode) {
                     property = processLeafNode((LeafSchemaNode) node);
                 } else if (node instanceof ListSchemaNode) {
-                    property = processListSchemaNode((ListSchemaNode) node, moduleName, models);
+                    property = processListSchemaNode((ListSchemaNode) node, moduleName, models, isConfig);
 
                 } else if (node instanceof LeafListSchemaNode) {
                     property = processLeafListNode((LeafListSchemaNode) node);
@@ -354,15 +410,17 @@ public class ModelGenerator {
      *
      * @param listNode
      * @param moduleName
+     * @param isConfig
      * @return
      * @throws JSONException
      * @throws IOException
      */
     private JSONObject processListSchemaNode(ListSchemaNode listNode, String moduleName,
-            JSONObject models) throws JSONException, IOException {
+            JSONObject models, Boolean isConfig) throws JSONException, IOException {
 
         Set<DataSchemaNode> listChildren = listNode.getChildNodes();
-        String fileName = listNode.getQName().getLocalName();
+        String fileName = (BooleanUtils.isNotFalse(isConfig)?OperationBuilder.CONFIG:OperationBuilder.OPERATIONAL) +
+                                                                listNode.getQName().getLocalName();
 
         JSONObject childSchemaProperties = processChildren(listChildren, moduleName, models);
         JSONObject childSchema = getSchemaTemplate();
@@ -443,7 +501,7 @@ public class ModelGenerator {
             processUnionType((UnionTypeDefinition) leafTypeDef, property);
 
         } else if (leafTypeDef instanceof IdentityrefTypeDefinition) {
-            property.putOpt(TYPE_KEY, "object");
+      property.putOpt(TYPE_KEY, ((IdentityrefTypeDefinition) leafTypeDef).getIdentity().getQName().getLocalName());
         } else if (leafTypeDef instanceof BinaryTypeDefinition) {
             processBinaryType((BinaryTypeDefinition) leafTypeDef, property);
         } else {
@@ -541,12 +599,15 @@ public class ModelGenerator {
     private void processUnionType(UnionTypeDefinition unionType, JSONObject property)
             throws JSONException {
 
-        List<TypeDefinition<?>> unionTypes = unionType.getTypes();
-        JSONArray unionArray = new JSONArray();
-        for (TypeDefinition<?> typeDef : unionTypes) {
-            unionArray.put(YANG_TYPE_TO_JSON_TYPE_MAPPING.get(typeDef.getClass()));
+        StringBuilder type = new StringBuilder();
+        for (TypeDefinition<?> typeDef : unionType.getTypes() ) {
+            if( type.length() > 0 ){
+                type.append( " or " );
+            }
+            type.append(YANG_TYPE_TO_JSON_TYPE_MAPPING.get(typeDef.getClass()));
         }
-        property.put(TYPE_KEY, unionArray);
+
+        property.put(TYPE_KEY, type );
     }
 
     /**
index b996bf12348ccc89088b1426c269049a9cf98928..fcabb088f4decbac32df1ba08648cb3d2d18fdf9 100644 (file)
@@ -46,7 +46,7 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
     private final Map<InstanceIdentifier, Long> instanceIdToLongId = new TreeMap<>(
             new Comparator<InstanceIdentifier>() {
                 @Override
-                public int compare(InstanceIdentifier o1, InstanceIdentifier o2) {
+                public int compare(final InstanceIdentifier o1, final InstanceIdentifier o2) {
                     return o1.toString().compareToIgnoreCase(o2.toString());
                 }
             });
@@ -71,12 +71,12 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
         return urlToId;
     }
 
-    public void setGlobalSchema(SchemaService globalSchema) {
+    public void setGlobalSchema(final SchemaService globalSchema) {
         this.globalSchema = globalSchema;
     }
 
-    private String findModuleName(InstanceIdentifier id, SchemaContext context) {
-        PathArgument rootQName = id.getPath().get(0);
+    private String findModuleName(final InstanceIdentifier id, final SchemaContext context) {
+        PathArgument rootQName = id.getPathArguments().iterator().next();
         for (Module mod : context.getModules()) {
             if (mod.getDataChildByName(rootQName.getNodeType()) != null) {
                 return mod.getName();
@@ -85,40 +85,39 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
         return null;
     }
 
-    private String generateUrlPrefixFromInstanceID(InstanceIdentifier key, String moduleName) {
-        List<PathArgument> path = key.getPath();
+    private String generateUrlPrefixFromInstanceID(final InstanceIdentifier key, final String moduleName) {
         StringBuilder builder = new StringBuilder();
         if (moduleName != null) {
             builder.append(moduleName);
-            builder.append(":");
+            builder.append(':');
         }
         boolean first = true;
-        for (PathArgument arg : path) {
+        for (PathArgument arg : key.getPathArguments()) {
 
             String name = arg.getNodeType().getLocalName();
             if (first) {
                 first = false;
             } else {
-                builder.append("/");
+                builder.append('/');
             }
             builder.append(name);
             if (arg instanceof InstanceIdentifier.NodeIdentifierWithPredicates) {
                 NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
                 for (Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
-                    builder.append("/").append(entry.getValue());
+                    builder.append('/').append(entry.getValue());
                 }
             }
         }
 
-        return builder.append("/").toString();
+        return builder.append('/').toString();
     }
 
-    private String getYangMountUrl(InstanceIdentifier key) {
+    private String getYangMountUrl(final InstanceIdentifier key) {
         String modName = findModuleName(key, globalSchema.getGlobalContext());
         return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount/";
     }
 
-    public ResourceList getResourceList(UriInfo uriInfo, Long id) {
+    public ResourceList getResourceList(final UriInfo uriInfo, final Long id) {
         InstanceIdentifier iid = getInstanceId(id);
         if (iid == null) {
             return null; // indicating not found.
@@ -139,7 +138,7 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
         return list;
     }
 
-    private InstanceIdentifier getInstanceId(Long id) {
+    private InstanceIdentifier getInstanceId(final Long id) {
         InstanceIdentifier instanceId;
         synchronized (lock) {
             instanceId = longIdToInstanceId.get(id);
@@ -147,7 +146,7 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
         return instanceId;
     }
 
-    private SchemaContext getSchemaContext(InstanceIdentifier id) {
+    private SchemaContext getSchemaContext(final InstanceIdentifier id) {
 
         if (id == null) {
             return null;
@@ -165,7 +164,7 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
         return context;
     }
 
-    public ApiDeclaration getMountPointApi(UriInfo uriInfo, Long id, String module, String revision) {
+    public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module, final String revision) {
         InstanceIdentifier iid = getInstanceId(id);
         SchemaContext context = getSchemaContext(iid);
         String urlPrefix = getYangMountUrl(iid);
@@ -179,7 +178,7 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
         return super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
     }
 
-    private ApiDeclaration generateDataStoreApiDoc(UriInfo uriInfo, String context) {
+    private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
 
         ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
         List<Api> apis = new LinkedList<>();
@@ -194,7 +193,7 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
 
     }
 
-    private Api createGetApi(String datastore, String note, String context) {
+    private Api createGetApi(final String datastore, final String note, final String context) {
         Operation getConfig = new Operation();
         getConfig.setMethod("GET");
         getConfig.setNickname("GET " + datastore);
@@ -207,12 +206,12 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
         return api;
     }
 
-    public void setMountService(MountProvisionService mountService) {
+    public void setMountService(final MountProvisionService mountService) {
         this.mountService = mountService;
     }
 
     @Override
-    public void onMountPointCreated(InstanceIdentifier path) {
+    public void onMountPointCreated(final InstanceIdentifier path) {
         synchronized (lock) {
             Long idLong = idKey.incrementAndGet();
             instanceIdToLongId.put(path, idLong);
@@ -221,7 +220,7 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
     }
 
     @Override
-    public void onMountPointRemoved(InstanceIdentifier path) {
+    public void onMountPointRemoved(final InstanceIdentifier path) {
         synchronized (lock) {
             Long id = instanceIdToLongId.remove(path);
             longIdToInstanceId.remove(id);
index 2816f79e2413a90afc4125346a1a64804658a548..05a76a4cb7ca0551d0bb55322b4603f78eb7fd4b 100644 (file)
@@ -24,7 +24,6 @@
 <script src='swagger-ui.js' type='text/javascript'></script>\r
 <script src='lib/odl/list_mounts.js' type='text/javascript'></script>\r
 <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>\r
-<script src='lib/odl/rest-tree.js' type='text/javascript'></script>\r
 <script src='lib/odl/swagger.js' type='text/javascript'></script>\r
 \r
 <script type="text/javascript">\r
index 8390a385e6a136a29d79e64376a0fadf8fa03757..07c9378439d2f66551672d8a08ec20785a0a074b 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.sal.rest.doc.impl;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.File;
@@ -65,6 +66,24 @@ public class ApiDocGeneratorTest {
         }
     }
 
+    @Test
+    public void testEdgeCases() throws Exception {
+        Preconditions.checkArgument(helper.getModules() != null, "No modules found");
+
+        for (Entry<File, Module> m : helper.getModules().entrySet()) {
+            if (m.getKey().getAbsolutePath().endsWith("toaster.yang")) {
+                ApiDeclaration doc = generator.getSwaggerDocSpec(m.getValue(),
+                        "http://localhost:8080/restconf", "");
+                Assert.assertNotNull(doc);
+
+                //testing bugs.opendaylight.org bug 1290. UnionType model type.
+                String jsonString = doc.getModels().toString();
+                assertTrue(
+                        jsonString.contains( "testUnion\":{\"type\":\"integer or string\",\"required\":false}" ) );
+            }
+        }
+    }
+
     private void validateToaster(ApiDeclaration doc) throws Exception {
         Set<String> expectedUrls = new TreeSet<>(Arrays.asList(new String[] {
                 "/config/toaster2:toaster/", "/operational/toaster2:toaster/",
@@ -99,6 +118,7 @@ public class ApiDocGeneratorTest {
             expectedConfigMethods.removeAll(actualConfigMethods);
             fail("Missing expected method on config API: " + expectedConfigMethods);
         }
+
         // TODO: we should really do some more validation of the
         // documentation...
         /**
index 10a9d6ddadfe2995a310a71440cc6b526a33c85f..8824284785bccea43ca82615b45ba09b66bcc4b7 100644 (file)
@@ -32,7 +32,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.samples.l2switch.md</groupId>
index 2fcb2f6d63ad6805603d0725ce7801b754bbcede..56ed9a07a6481e046e9a39ea9b7bb799cd09faa7 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller.samples</groupId>
       <artifactId>sample-toaster</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.samples</groupId>
       <artifactId>sample-toaster-consumer</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.opendaylight.controller.samples</groupId>
       <artifactId>sample-toaster-provider</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.openexi</groupId>
@@ -50,7 +47,6 @@
     <dependency>
       <groupId>equinoxSDK381</groupId>
       <artifactId>org.eclipse.osgi</artifactId>
-      <version>3.8.1.v20120830-144521</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -72,7 +68,6 @@
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
-        <version>1.2.4</version>
         <executions>
           <execution>
             <id>generate-config</id>
index 61c24c6b6413cae9012916bf93001af11fc77f92..4cce64dcd329a9404d9273a24d45dd253db08dad 100644 (file)
@@ -1,45 +1,92 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+
 <persisted-snapshots>
     <snapshots>
         <snapshot>
-            <required-capabilities>
-                <!-- <capability>urn:opendaylight:l2:types?module=opendaylight-l2-types&amp;revision=2013-08-27</capability>-->
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28
-                </capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:config?module=config&amp;revision=2013-04-05
-                </capability>
-                <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
-                <capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&amp;revision=2010-10-04</capability>
-                <capability>urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&amp;revision=2013-06-17
-                </capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28
-                </capability>
-                <capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&amp;revision=2010-09-24
-                </capability>
-                <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability>
-                <capability>urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&amp;revision=2010-09-24
-                </capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28
-                </capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&amp;revision=2013-07-16</capability>
-                <!-- <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&amp;revision=2013-07-09</capability>-->
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28
-                </capability>
-                <capability>http://netconfcentral.org/ns/toaster?module=toaster&amp;revision=2009-11-20</capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&amp;revision=2014-01-31</capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&amp;revision=2014-01-31</capability>
-
-            </required-capabilities>
             <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:impl">prefix:schema-service-singleton</type>
+                            <name>yang-schema-service</name>
+                        </module>
+                        <module>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+                            <name>runtime-mapping-singleton</name>
+                        </module>
+                        <module>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+                            <name>binding-notification-broker</name>
+                        </module>
+                        <module>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+                            <name>binding-broker-impl</name>
+                            <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+                                <name>binding-notification-broker</name>
+                            </notification-service>
+                            <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                                <name>binding-data-broker</name>
+                            </data-broker>
+                        </module>
+
+                        <!--
+                             Tree-based in-memory data store. This is the data store which is currently
+                             recommended for single-node deployments.
+                        -->
+                        <module>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+                            <name>inmemory-data-broker</name>
+                            <schema-service>
+                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                                <name>yang-schema-service</name>
+                            </schema-service>
+                        </module>
+                        <module>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+                            <name>inmemory-dom-broker</name>
+                            <async-data-broker>
+                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+                                <name>inmemory-data-broker</name>
+                            </async-data-broker>
+                        </module>
+                        <module>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
+                            <name>inmemory-binding-data-broker</name>
+                            <dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+                                <name>dom-broker</name>
+                            </dom-async-broker>
+                            <binding-mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+                                <name>runtime-mapping-singleton</name>
+                            </binding-mapping-service>
+                        </module>
+                        <module>
+                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-forwarded-data-broker</type>
+                            <name>binding-async-data-broker</name>
+                            <binding-forwarded-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                                <dom-async-broker>
+                                    <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+                                    <name>dom-broker</name>
+                                </dom-async-broker>
+                                <binding-mapping-service>
+                                    <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+                                    <name>runtime-mapping-singleton</name>
+                                </binding-mapping-service>
+                            </binding-forwarded-data-broker>
+                        </module>
+
+                        <!-- Toaster Congiguration -->
                         <module>
                             <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
                                 prefix:toaster-provider-impl
                             </rpc-registry>
 
                             <data-broker>
-                              <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
-                              <name>ref_binding-data-broker</name>
+                              <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                              <name>binding-data-broker</name>
                             </data-broker>
 
                             <notification-service>
                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
                                     binding:binding-notification-service
                                 </type>
-                                <name>ref_binding-notification-broker</name>
+                                <name>binding-notification-broker</name>
                             </notification-service>
                         </module>
 
+                        <!-- Kitchen Service -->
                         <module>
                             <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
                                 prefix:kitchen-service-impl
                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
                                     binding:binding-notification-service
                                 </type>
-                                <name>ref_binding-notification-broker</name>
-                            </notification-service>
-                        </module>
-
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                                prefix:schema-service-singleton
-                            </type>
-                            <name>yang-schema-service</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                                prefix:hash-map-data-store
-                            </type>
-                            <name>hash-map-data-store</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                                prefix:dom-broker-impl
-                            </type>
-                            <name>dom-broker</name>
-                            <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
-                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                    dom:dom-data-store
-                                </type>
-                                <name>ref_hash-map-data-store</name>
-                            </data-store>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:binding-broker-impl
-                            </type>
-                            <name>binding-broker-impl</name>
-                            <notification-service
-                                    xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                    binding:binding-notification-service
-                                </type>
-                                <name>ref_binding-notification-broker</name>
+                                <name>binding-notification-broker</name>
                             </notification-service>
-                            <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                    binding:binding-data-broker
-                                </type>
-                                <name>ref_binding-data-broker</name>
-                            </data-broker>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:runtime-generated-mapping
-                            </type>
-                            <name>runtime-mapping-singleton</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:binding-notification-broker
-                            </type>
-                            <name>binding-notification-broker</name>
-                        </module>
-                        <module>
-                            <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                prefix:binding-data-broker
-                            </type>
-                            <name>binding-data-broker</name>
-                            <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                    dom:dom-broker-osgi-registry
-                                </type>
-                                <name>ref_dom-broker</name>
-                            </dom-broker>
-                            <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                    binding:binding-dom-mapping-service
-                                </type>
-                                <name>ref_runtime-mapping-singleton</name>
-                            </mapping-service>
                         </module>
                     </modules>
-
                     <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                         <service>
-                          <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
-                            kitchen:kitchen-service
-                          </type>
-                          <instance>
-                            <name>kitchen-service</name>
-                            <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
-                          </instance>
+                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+                            <instance>
+                                <name>yang-schema-service</name>
+                                <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+                            </instance>
                         </service>
                         <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                dom:schema-service
-                            </type>
+                            <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
                             <instance>
-                                <name>ref_yang-schema-service</name>
-                                <provider>
-                                    /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']
-                                </provider>
+                                <name>runtime-mapping-singleton</name>
+                                <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
                             </instance>
                         </service>
                         <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                binding:binding-notification-service
-                            </type>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
                             <instance>
-                                <name>ref_binding-notification-broker</name>
-                                <provider>
-                                    /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']
-                                </provider>
+                                <name>binding-notification-broker</name>
+                                <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
                             </instance>
                         </service>
                         <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                dom:dom-data-store
-                            </type>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
                             <instance>
-                                <name>ref_hash-map-data-store</name>
-                                <provider>
-                                    /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']
-                                </provider>
+                                <name>binding-osgi-broker</name>
+                                <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
                             </instance>
                         </service>
                         <service>
                                 <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
                             </instance>
                         </service>
+
                         <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                binding:binding-broker-osgi-registry
-                            </type>
+                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
                             <instance>
-                                <name>ref_binding-broker-impl</name>
-                                <provider>
-                                    /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']
-                                </provider>
+                                <name>dom-broker</name>
+                                <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
                             </instance>
                         </service>
+
                         <service>
-                            <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
-                                binding-impl:binding-dom-mapping-service
-                            </type>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
                             <instance>
-                                <name>ref_runtime-mapping-singleton</name>
-                                <provider>
-                                    /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']
-                                </provider>
+                                <name>binding-data-broker</name>
+                                <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
                             </instance>
                         </service>
+
                         <service>
-                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
-                                dom:dom-broker-osgi-registry
-                            </type>
+                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
                             <instance>
-                                <name>ref_dom-broker</name>
-                                <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']
-                                </provider>
+                                <name>binding-data-broker</name>
+                                <provider>/modules/module[type='binding-forwarded-data-broker'][name='binding-async-data-broker']</provider>
                             </instance>
                         </service>
+
                         <service>
-                            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                                binding:binding-data-broker
-                            </type>
+                            <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
                             <instance>
-                                <name>ref_binding-data-broker</name>
-                                <provider>
-                                    /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']
-                                </provider>
+                                <name>inmemory-data-broker</name>
+                                <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
                             </instance>
                         </service>
+
+                        <!-- Toaster samples -->
+                        <service>
+                          <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+                            kitchen:kitchen-service
+                          </type>
+                          <instance>
+                            <name>kitchen-service</name>
+                            <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
+                          </instance>
+                        </service>
                     </services>
                 </data>
-
             </configuration>
-        </snapshot>
+            <required-capabilities>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
 
+                <!-- Toaster capabilities -->
+                <capability>http://netconfcentral.org/ns/toaster?module=toaster&amp;revision=2009-11-20</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&amp;revision=2014-01-31</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&amp;revision=2014-01-31</capability>
+
+            </required-capabilities>
+        </snapshot>
     </snapshots>
 </persisted-snapshots>
index bd8e89fd7a5ab99ddb1246a167d0b142f446a07f..388c78eaaf6365c77241c17cae04848680882624 100644 (file)
@@ -9,9 +9,11 @@
 */
 package org.opendaylight.controller.config.yang.config.toaster_provider.impl;
 
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sample.toaster.provider.OpendaylightToaster;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -21,23 +23,26 @@ import org.slf4j.LoggerFactory;
 /**
 *
 */
-public final class ToasterProviderModule extends org.opendaylight.controller.config.yang.config.toaster_provider.impl.AbstractToasterProviderModule
- {
+public final class ToasterProviderModule extends
       org.opendaylight.controller.config.yang.config.toaster_provider.impl.AbstractToasterProviderModule {
     private static final Logger log = LoggerFactory.getLogger(ToasterProviderModule.class);
 
-    public ToasterProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    public ToasterProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public ToasterProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
-            ToasterProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public ToasterProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            final ToasterProviderModule oldModule, final java.lang.AutoCloseable oldInstance) {
 
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
     @Override
     protected void customValidation() {
-        // No need to validate dependencies, since all dependencies have mandatory true flag in yang
+        // No need to validate dependencies, since all dependencies have
+        // mandatory true flag in yang
         // config-subsystem will perform the validation for dependencies
     }
 
@@ -48,11 +53,12 @@ public final class ToasterProviderModule extends org.opendaylight.controller.con
         // Register to md-sal
         opendaylightToaster.setNotificationProvider(getNotificationServiceDependency());
 
-        DataProviderService dataBrokerService = getDataBrokerDependency();
+        DataBroker dataBrokerService = getDataBrokerDependency();
         opendaylightToaster.setDataProvider(dataBrokerService);
 
-        final ListenerRegistration<DataChangeListener> dataChangeListenerRegistration =
-                dataBrokerService.registerDataChangeListener( OpendaylightToaster.TOASTER_IID, opendaylightToaster );
+        final ListenerRegistration<DataChangeListener> dataChangeListenerRegistration = dataBrokerService
+                .registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, OpendaylightToaster.TOASTER_IID,
+                        opendaylightToaster, DataChangeScope.SUBTREE);
 
         final BindingAwareBroker.RpcRegistration<ToasterService> rpcRegistration = getRpcRegistryDependency()
                 .addRpcImplementation(ToasterService.class, opendaylightToaster);
index 2ecd7e7b684fe8bdafd6af17527cbb21daeee83f..ec352e8f510dad03911be2ad2eeb0ec6a5c44542 100644 (file)
@@ -17,29 +17,30 @@ import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.opendaylight.controller.config.yang.config.toaster_provider.impl.ToasterProviderRuntimeMXBean;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.RestockToasterInput;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster.ToasterStatus;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.RestockToasterInput;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterBuilder;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBreadBuilder;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestockedBuilder;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 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;
 
@@ -56,7 +57,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
     private static final DisplayString TOASTER_MODEL_NUMBER = new DisplayString("Model 1 - Binding Aware");
 
     private NotificationProviderService notificationProvider;
-    private DataBrokerService dataProvider;
+    private DataBroker dataProvider;
 
     private final ExecutorService executor;
 
@@ -76,11 +77,11 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
         executor = Executors.newFixedThreadPool(1);
     }
 
-    public void setNotificationProvider(NotificationProviderService salService) {
+    public void setNotificationProvider(final NotificationProviderService salService) {
         this.notificationProvider = salService;
     }
 
-    public void setDataProvider(DataBrokerService salDataProvider) {
+    public void setDataProvider(final DataBroker salDataProvider) {
         this.dataProvider = salDataProvider;
         updateStatus();
     }
@@ -94,9 +95,9 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
         executor.shutdown();
 
         if (dataProvider != null) {
-            final DataModificationTransaction t = dataProvider.beginTransaction();
-            t.removeOperationalData(TOASTER_IID);
-            t.commit().get();
+            WriteTransaction t = dataProvider.newWriteOnlyTransaction();
+            t.delete(LogicalDatastoreType.OPERATIONAL,TOASTER_IID);
+            t.commit().get(); // FIXME: This call should not be blocking.
         }
     }
 
@@ -118,8 +119,8 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
      * Implemented from the DataChangeListener interface.
      */
     @Override
-    public void onDataChanged( DataChangeEvent<InstanceIdentifier<?>, DataObject> change ) {
-        DataObject dataObject = change.getUpdatedConfigurationData().get( TOASTER_IID );
+    public void onDataChanged( final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change ) {
+        DataObject dataObject = change.getUpdatedSubtree();
         if( dataObject instanceof Toaster )
         {
             Toaster toaster = (Toaster) dataObject;
@@ -150,7 +151,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
      * RestConf RPC call implemented from the ToasterService interface.
      */
     @Override
-    public Future<RpcResult<Void>> makeToast(MakeToastInput input) {
+    public Future<RpcResult<Void>> makeToast(final MakeToastInput input) {
         LOG.info("makeToast: " + input);
 
         synchronized (taskLock) {
@@ -191,7 +192,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
      * ToasterRestocked notification.
      */
     @Override
-    public Future<RpcResult<java.lang.Void>> restockToaster(RestockToasterInput input) {
+    public Future<RpcResult<java.lang.Void>> restockToaster(final RestockToasterInput input) {
         LOG.info( "restockToaster: " + input );
 
         synchronized( taskLock ) {
@@ -226,12 +227,11 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
 
     private void updateStatus() {
         if (dataProvider != null) {
-            final DataModificationTransaction t = dataProvider.beginTransaction();
-            t.removeOperationalData(TOASTER_IID);
-            t.putOperationalData(TOASTER_IID, buildToaster());
+            WriteTransaction tx = dataProvider.newWriteOnlyTransaction();
+            tx.put(LogicalDatastoreType.OPERATIONAL,TOASTER_IID, buildToaster());
 
             try {
-                t.commit().get();
+                tx.commit().get();
             } catch (InterruptedException | ExecutionException e) {
                 LOG.warn("Failed to update toaster status, operational otherwise", e);
             }
@@ -249,7 +249,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
 
         final MakeToastInput toastRequest;
 
-        public MakeToastTask(MakeToastInput toast) {
+        public MakeToastTask(final MakeToastInput toast) {
             toastRequest = toast;
         }
 
index d6de5cfd17136d625a205b0b77122b2143c803fc..8de0c98c63e98f136ac91c98b1792fb040e0be63 100644 (file)
@@ -53,7 +53,7 @@ module toaster-provider-impl {
                 uses config:service-ref {
                     refine type {
                         mandatory false;
-                        config:required-identity mdsal:binding-data-broker;
+                        config:required-identity mdsal:binding-async-data-broker;
                     }
                 }
             }
index 0ae33b8c71fa93add1914d79c595c14538b0737f..29a27e2bb2a2cdfc85c7b49eada243bdc9f8a531 100644 (file)
@@ -48,9 +48,13 @@ public class StatisticsRequestScheduler implements DataTransactionListener {
     private final TimerTask task = new TimerTask() {
         @Override
         public void run() {
-            long now = System.nanoTime();
-            if(now > lastRequestTime+TimeUnit.MILLISECONDS.toNanos(REQUEST_MONITOR_INTERVAL)){
-                requestStatistics();
+            try{
+                long now = System.nanoTime();
+                if(now > lastRequestTime+TimeUnit.MILLISECONDS.toNanos(REQUEST_MONITOR_INTERVAL)){
+                    requestStatistics();
+                }
+            }catch (IllegalArgumentException | IllegalStateException | NullPointerException e){
+                srsLogger.warn("Exception occured while sending statistics request : {}",e);
             }
         }
     };
index a51f6c2f9f0eb6669ace2e8febe1404f8189df51..2c8571ca64369c80748ee5d1b157a39017c1db86 100644 (file)
@@ -28,7 +28,6 @@
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
-      <version>2.4</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
index 55244d3c902015f0b5e6247a079bb34520459702..fe1813a19943dfe7f3446b55f9c49b1986df6729 100644 (file)
@@ -34,7 +34,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.osgi</groupId>
index 08f3c73ac2646025ff8e617a4cc0a95f3afec492..8720c654c61f993f09d6503305fdc471d4065a94 100644 (file)
@@ -8,12 +8,14 @@
 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.api.xml.XmlNetconfConstants;
 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;
 
 public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
 
index 68c8c6fce39eed748dcd9f9725c1c0c16c85c133..5d5721a6f870534c4e33df2942164287f4bfcfb6 100644 (file)
@@ -8,9 +8,9 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
 
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
-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;
index 1492066289d0569933e3b51a574bc03488a42df3..5d41b784f5cdaa4ff264774b05069ad6e83f3ff3 100644 (file)
@@ -16,6 +16,7 @@ import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -23,13 +24,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+
 import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 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.w3c.dom.Document;
 import org.w3c.dom.Element;
index ff1d719c57877c2df4710701d9d6f0bd65075b07..0b33b553207bf15a8b7a58c6007e0c867e296cea 100644 (file)
@@ -11,16 +11,20 @@ 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 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;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
@@ -33,7 +37,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 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;
index 0c2b0e228e8c6763aea207c978aabdc02cd11dc1..eaab30b53be90d90c4aa8a94ff6c30cae2c6b1fb 100644 (file)
@@ -9,15 +9,18 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
 import com.google.common.base.Optional;
+
 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.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 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.w3c.dom.Document;
 import org.w3c.dom.Element;
index 559de7a756f51db69d5047c5c1bd0ac6918832ea..37ad2bb22260ab45027b635d5671da8077d823b7 100644 (file)
@@ -11,16 +11,18 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.confi
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectNameAttributeReadingStrategy;
 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.w3c.dom.Document;
 import org.w3c.dom.Element;
 
 import javax.management.ObjectName;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
index b9518dc4d8825df28b875dbe03ccae8142fd7ca0..b1df316b1acb81010ce3a9e85d20c7b04b004f4e 100644 (file)
@@ -12,14 +12,17 @@ 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.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-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;
index d49fe1a11629b0c5a9110b82973eac91ea25ba44..8eaaecfbb4d90904e16f7853980ea872b81fb97b 100644 (file)
@@ -13,9 +13,9 @@ import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 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;
index 96a43b104d7d58a687f68744f79f6536b669f468..3cf702ed7f1b8b532d0a6834b787ee6140bc6fc7 100644 (file)
@@ -9,14 +9,15 @@
     package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
 import com.google.common.base.Optional;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 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.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 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;
index 1a7d50e5fabbc91f1359a3295a80f3f0418d6340..f443111525c8cdd154690444f9b23bca24bb4b37 100644 (file)
@@ -9,15 +9,16 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
 import com.google.common.base.Optional;
+
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 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.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 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;
index 319f539c25f02e9cbddf28b62288b5805fea8fd2..543a2c4a630d90de73dbf7aa0f837bf7dd2328f7 100644 (file)
@@ -13,12 +13,15 @@ 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;
@@ -27,6 +30,7 @@ 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.api.xml.XmlNetconfConstants;
 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;
@@ -39,7 +43,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.edi
 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 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.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
index 47220f18571a275641a7f0671cfe6da9e0e2ff1d..a3d97b1b398aacc8221b2a0ee076d6b52f3b406f 100644 (file)
@@ -11,10 +11,13 @@ 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.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementDefinition;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved;
@@ -24,7 +27,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.Dat
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
index 867ad603623b7998612dab84c906323d7aea8942..fc95046dfdbef94e3e139480cae950c7010a83f9 100644 (file)
@@ -9,14 +9,18 @@
 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.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 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.runtime.InstanceRuntime;
@@ -30,7 +34,6 @@ import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceExcept
 import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
 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 org.w3c.dom.Document;
index bc059d345c647d2ea3316efea1887be1eee39a56..fee3036214010d9dfe23453b62dee2cb70df2a17 100644 (file)
@@ -14,6 +14,7 @@ import javax.management.ObjectName;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
@@ -25,7 +26,6 @@ import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceExcept
 import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
 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;
index 98eb17699973cc1e2448c5072421a0e29b205280..21021fec55661f69cd2c1e19325f0dd651e07193 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ru
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
@@ -18,6 +19,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribute;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.AttributeMappingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectMapper;
@@ -31,7 +33,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 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;
@@ -40,6 +41,7 @@ import org.w3c.dom.Element;
 
 import javax.management.ObjectName;
 import javax.management.openmbean.OpenType;
+
 import java.util.Map;
 
 public class RuntimeRpc extends AbstractConfigNetconfOperation {
index 5cf7f30abcaa5cf356a2faf89635c0cb1ee06f63..7fd8928928feb8814b0eb003c61e2c51152beef5 100644 (file)
@@ -11,11 +11,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ru
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.ModuleRpcs;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 
 import javax.management.ObjectName;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Matcher;
index 1069858b4777008a321b7021beb172ca951675df..f5fe089d4d80d1b614636b9522e0963ac2d922c9 100644 (file)
@@ -95,8 +95,10 @@ public class NetconfOperationServiceImpl implements NetconfOperationService {
         Set<Capability> capabilities = new HashSet<>();
         // [RFC6241] 8.3.  Candidate Configuration Capability
         capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0"));
+
+        // TODO rollback on error not supported EditConfigXmlParser:100
         // [RFC6241] 8.5.  Rollback-on-Error Capability
-        capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:rollback-on-error:1.0"));
+        // capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:rollback-on-error:1.0"));
 
         Set<Module> modules = yangStoreSnapshot.getModules();
         for (Module module : modules) {
index 782998067f80d5fc35a1249dedbaa8e0dcf4e37b..827708f31ceb52fbc39bd8c202fa630cf698d225 100644 (file)
@@ -9,6 +9,13 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
 
 import com.google.common.collect.Maps;
+
+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.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslator;
 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry;
@@ -21,18 +28,12 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
 public class YangStoreSnapshotImpl implements YangStoreSnapshot {
     private static final Logger logger = LoggerFactory.getLogger(YangStoreSnapshotImpl.class);
 
 
     private final Map<String /* Namespace from yang file */,
-            Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> moduleMXBeanEntryMap;
+    Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> moduleMXBeanEntryMap;
 
 
     private final Map<QName, Map<String, ModuleMXBeanEntry>> qNamesToIdentitiesToModuleMXBeanEntries;
@@ -40,7 +41,7 @@ public class YangStoreSnapshotImpl implements YangStoreSnapshot {
     private final SchemaContext schemaContext;
 
 
-    public YangStoreSnapshotImpl(SchemaContext resolveSchemaContext) {
+    public YangStoreSnapshotImpl(final SchemaContext resolveSchemaContext) {
         logger.trace("Resolved modules:{}", resolveSchemaContext.getModules());
         this.schemaContext = resolveSchemaContext;
         // JMX generator
@@ -60,7 +61,7 @@ public class YangStoreSnapshotImpl implements YangStoreSnapshot {
                     qNamesToSIEs.put(sieEntry.getKey(), sieEntry.getValue());
                 } else {
                     throw new IllegalStateException("Cannot add two SIE with same qname "
-                                    + sieEntry.getValue());
+                            + sieEntry.getValue());
                 }
             }
         }
@@ -75,7 +76,7 @@ public class YangStoreSnapshotImpl implements YangStoreSnapshot {
             TypeProviderWrapper typeProviderWrapper = new TypeProviderWrapper(
                     new TypeProviderImpl(resolveSchemaContext));
 
-            QName qName = new QName(module.getNamespace(), module.getRevision(), module.getName());
+            QName qName = QName.create(module.getNamespace(), module.getRevision(), module.getName());
 
             Map<String /* MB identity local name */, ModuleMXBeanEntry> namesToMBEs =
                     Collections.unmodifiableMap(ModuleMXBeanEntry.create(module, qNamesToSIEs, resolveSchemaContext,
@@ -105,7 +106,7 @@ public class YangStoreSnapshotImpl implements YangStoreSnapshot {
     }
 
     @Override
-    public String getModuleSource(org.opendaylight.yangtools.yang.model.api.ModuleIdentifier moduleIdentifier) {
+    public String getModuleSource(final org.opendaylight.yangtools.yang.model.api.ModuleIdentifier moduleIdentifier) {
         return schemaContext.getModuleSource(moduleIdentifier).get();
     }
 
index 41301543a33f54754f0ccfc7bda24f2a9b818f74..e41b174b664740c685faa041d64c208630bf21c2 100644 (file)
@@ -28,6 +28,7 @@ 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;
@@ -42,10 +43,12 @@ 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;
@@ -80,6 +83,7 @@ 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.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.DiscardChanges;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
@@ -96,7 +100,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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
index d393121a269700aeb1adda313eedff43b613a806..b5c5dd35442704253a4b1e906ab674e0b4a19b71 100644 (file)
@@ -11,9 +11,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 import org.junit.Test;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 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.w3c.dom.Element;
 
index a063f5786a8f4796d95023849fbc6243e873fa01..1e650c08b124a460c7d19f65200c1b0868ccee17 100644 (file)
@@ -8,14 +8,12 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
 
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.matchers.JUnitMatchers;
-import org.opendaylight.controller.config.api.LookupRegistry;
-import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
-import org.opendaylight.yangtools.yang.common.QName;
 
 import java.net.URI;
 import java.text.ParseException;
@@ -24,9 +22,12 @@ import java.util.Date;
 import java.util.Map;
 import java.util.Set;
 
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.opendaylight.controller.config.api.LookupRegistry;
+import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.yangtools.yang.common.QName;
 
 public class NetconfOperationServiceImplTest {
 
@@ -72,15 +73,15 @@ public class NetconfOperationServiceImplTest {
             Assert.assertThat(
                     message,
                     JUnitMatchers
-                            .containsString("missing from config subsystem but present in yangstore: [(namespace?revision=1970-01-01)qname2]"));
+                    .containsString("missing from config subsystem but present in yangstore: [(namespace?revision=1970-01-01)qname2]"));
             Assert.assertThat(
                     message,
                     JUnitMatchers
-                            .containsString("All modules present in config: [(namespace?revision=1970-01-01)qname1]"));
+                    .containsString("All modules present in config: [(namespace?revision=1970-01-01)qname1]"));
         }
     }
 
-    private YangStoreSnapshot mockYangStoreSnapshot(String... qnames) {
+    private YangStoreSnapshot mockYangStoreSnapshot(final String... qnames) {
         YangStoreSnapshot mock = mock(YangStoreSnapshot.class);
 
         Map<String, Map<String, ModuleMXBeanEntry>> map = Maps.newHashMap();
@@ -99,18 +100,18 @@ public class NetconfOperationServiceImplTest {
         return mock;
     }
 
-    private ModuleMXBeanEntry mockMBeanEntry(String qname) {
+    private ModuleMXBeanEntry mockMBeanEntry(final String qname) {
         ModuleMXBeanEntry mock = mock(ModuleMXBeanEntry.class);
         QName q = getQName(qname);
         doReturn(q).when(mock).getYangModuleQName();
         return mock;
     }
 
-    private QName getQName(String qname) {
-        return new QName(URI.create("namespace"), date1970_01_01, qname);
+    private QName getQName(final String qname) {
+        return QName.create(URI.create("namespace"), date1970_01_01, qname);
     }
 
-    private LookupRegistry mockJmxClient(String... visibleQNames) {
+    private LookupRegistry mockJmxClient(final String... visibleQNames) {
         LookupRegistry mock = mock(LookupRegistry.class);
         Set<String> qnames = Sets.newHashSet();
         for (String visibleQName : visibleQNames) {
index 957db50c61a8b7ca076fc26fcc2c9886251f73bb..eddad8b4c7c1df593c45a5f829c3c56828339e18 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.controller.netconf.persist.impl;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Function;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Collections2;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collection;
@@ -16,15 +21,15 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
-
 import javax.annotation.concurrent.Immutable;
-
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
@@ -33,7 +38,6 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.opendaylight.controller.netconf.util.NetconfUtil;
 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;
@@ -41,11 +45,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Collections2;
-
 @Immutable
 public class ConfigPusher {
     private static final Logger logger = LoggerFactory.getLogger(ConfigPusher.class);
@@ -84,7 +83,11 @@ public class ConfigPusher {
         ConflictingVersionException lastException;
         Stopwatch stopwatch = new Stopwatch().start();
         do {
-            try (NetconfOperationService operationService = getOperationServiceWithRetries(configSnapshotHolder.getCapabilities(), configSnapshotHolder.toString())) {
+            String idForReporting = configSnapshotHolder.toString();
+            SortedSet<String> expectedCapabilities = checkNotNull(configSnapshotHolder.getCapabilities(),
+                    "Expected capabilities must not be null - %s, check %s", idForReporting,
+                    configSnapshotHolder.getClass().getName());
+            try (NetconfOperationService operationService = getOperationServiceWithRetries(expectedCapabilities, idForReporting)) {
                 return pushConfig(configSnapshotHolder, operationService);
             } catch (ConflictingVersionException e) {
                 lastException = e;
@@ -252,7 +255,7 @@ public class ConfigPusher {
     private static NetconfMessage createEditConfigMessage(Element dataElement) throws NetconfDocumentedException {
         String editConfigResourcePath = "/netconfOp/editConfig.xml";
         try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcePath)) {
-            Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcePath);
+            checkNotNull(stream, "Unable to load resource " + editConfigResourcePath);
 
             Document doc = XmlUtil.readXmlToDocument(stream);
 
@@ -274,7 +277,7 @@ public class ConfigPusher {
     private static NetconfMessage getCommitMessage() {
         String resource = "/netconfOp/commit.xml";
         try (InputStream stream = ConfigPusher.class.getResourceAsStream(resource)) {
-            Preconditions.checkNotNull(stream, "Unable to load resource " + resource);
+            checkNotNull(stream, "Unable to load resource " + resource);
             return new NetconfMessage(XmlUtil.readXmlToDocument(stream));
         } catch (SAXException | IOException e) {
             // error reading the xml file bundled into the jar
index 6fb231d847f2c5ae8c2022a7951460e19199ff70..3f04010015e8291d8dbeb6e47415d6ab8a12ad3f 100644 (file)
@@ -7,20 +7,25 @@
  */
 package org.opendaylight.controller.netconf.persist.impl.osgi;
 
-import org.junit.matchers.JUnitMatchers;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 
+import org.junit.matchers.JUnitMatchers;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 final class TestingExceptionHandler implements Thread.UncaughtExceptionHandler {
 
+    private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterTest.class);
+
     private Throwable t;
 
     @Override
     public void uncaughtException(Thread t, Throwable e) {
+        logger.debug("Uncaught exception in thread {}", t, e);
         this.t = e;
     }
 
index 061fbd7c8c7a0179d4d6147d40733a251875bcb9..a15047224bfbd91d46bb91f731ef3eea34d61c47 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>ietf-netconf-monitoring-extension</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
@@ -48,6 +47,7 @@
           <instructions>
             <Private-Package></Private-Package>
             <Import-Package>javax.management,
+                            javax.xml.parsers,
                             org.opendaylight.controller.config.api,
                             org.opendaylight.controller.config.api.jmx,
                             org.opendaylight.protocol.framework,
@@ -62,6 +62,7 @@
                             com.google.common.base,</Import-Package>
             <Export-Package>org.opendaylight.controller.netconf.api,
                             org.opendaylight.controller.netconf.api.jmx,
+                            org.opendaylight.controller.netconf.api.xml,
                             org.opendaylight.controller.netconf.api.monitoring,</Export-Package>
           </instructions>
         </configuration>
index 1ecbc55b2a02ac7af0757e777d960956cfddc0a0..0c365b9d30ebcb5463440404b0c9d10a3a015d5c 100644 (file)
@@ -8,12 +8,30 @@
 
 package org.opendaylight.controller.netconf.api;
 
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_INFO;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_MESSAGE;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_SEVERITY;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_TAG;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_TYPE;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_ERROR;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
 
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * Checked exception to communicate an error that needs to be sent to the
@@ -23,7 +41,17 @@ public class NetconfDocumentedException extends Exception {
 
     private static final long serialVersionUID = 1L;
 
+    private final static Logger LOG = LoggerFactory.getLogger( NetconfDocumentedException.class );
 
+    private static final DocumentBuilderFactory BUILDER_FACTORY;
+
+    static {
+        BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
+        BUILDER_FACTORY.setNamespaceAware(true);
+        BUILDER_FACTORY.setCoalescing(true);
+        BUILDER_FACTORY.setIgnoringElementContentWhitespace(true);
+        BUILDER_FACTORY.setIgnoringComments(true);
+    }
 
     public enum ErrorType {
         transport, rpc, protocol, application;
@@ -31,12 +59,37 @@ public class NetconfDocumentedException extends Exception {
         public String getTagValue() {
             return name();
         }
+
+        public static ErrorType from( String text ) {
+            try {
+                return valueOf( text );
+            }
+            catch( Exception e ) {
+                return application;
+            }
+        }
     }
 
     public enum ErrorTag {
-        missing_attribute("missing-attribute"), unknown_element("unknown-element"), operation_not_supported(
-                "operation-not-supported"), bad_attribute("bad-attribute"), data_missing("data-missing"), operation_failed(
-                "operation-failed"), invalid_value("invalid-value"), malformed_message("malformed-message");
+        access_denied("access-denied"),
+        bad_attribute("bad-attribute"),
+        bad_element("bad-element"),
+        data_exists("data-exists"),
+        data_missing("data-missing"),
+        in_use("in-use"),
+        invalid_value("invalid-value"),
+        lock_denied("lock-denied"),
+        malformed_message("malformed-message"),
+        missing_attribute("missing-attribute"),
+        missing_element("missing-element"),
+        operation_failed("operation-failed"),
+        operation_not_supported("operation-not-supported"),
+        resource_denied("resource-denied"),
+        rollback_failed("rollback-failed"),
+        too_big("too-big"),
+        unknown_attribute("unknown-attribute"),
+        unknown_element("unknown-element"),
+        unknown_namespace("unknown-namespace");
 
         private final String tagValue;
 
@@ -47,6 +100,17 @@ public class NetconfDocumentedException extends Exception {
         public String getTagValue() {
             return this.tagValue;
         }
+
+        public static ErrorTag from( String text ) {
+            for( ErrorTag e: values() )
+            {
+                if( e.getTagValue().equals( text ) ) {
+                    return e;
+                }
+            }
+
+            return operation_failed;
+        }
     }
 
     public enum ErrorSeverity {
@@ -55,6 +119,15 @@ public class NetconfDocumentedException extends Exception {
         public String getTagValue() {
             return name();
         }
+
+        public static ErrorSeverity from( String text ) {
+            try {
+                return valueOf( text );
+            }
+            catch( Exception e ) {
+                return error;
+            }
+        }
     }
 
     private final ErrorType errorType;
@@ -118,6 +191,64 @@ public class NetconfDocumentedException extends Exception {
                 ErrorSeverity.error, errorInfo);
     }
 
+    public static NetconfDocumentedException fromXMLDocument( Document fromDoc ) {
+
+        ErrorType errorType = ErrorType.application;
+        ErrorTag errorTag = ErrorTag.operation_failed;
+        ErrorSeverity errorSeverity = ErrorSeverity.error;
+        Map<String, String> errorInfo = null;
+        String errorMessage = "";
+
+        Node rpcReply = fromDoc.getDocumentElement();
+
+        // FIXME: BUG? - we only handle one rpc-error.
+
+        NodeList replyChildren = rpcReply.getChildNodes();
+        for( int i = 0; i < replyChildren.getLength(); i++ ) {
+            Node replyChild = replyChildren.item( i );
+            if( RPC_ERROR.equals( replyChild.getNodeName() ) )
+            {
+                NodeList rpcErrorChildren = replyChild.getChildNodes();
+                for( int j = 0; j < rpcErrorChildren.getLength(); j++ )
+                {
+                    Node rpcErrorChild = rpcErrorChildren.item( j );
+                    if( ERROR_TYPE.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorType = ErrorType.from( rpcErrorChild.getTextContent() );
+                    }
+                    else if( ERROR_TAG.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorTag = ErrorTag.from( rpcErrorChild.getTextContent() );
+                    }
+                    else if( ERROR_SEVERITY.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorSeverity = ErrorSeverity.from( rpcErrorChild.getTextContent() );
+                    }
+                    else if( ERROR_MESSAGE.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorMessage = rpcErrorChild.getTextContent();
+                    }
+                    else if( ERROR_INFO.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorInfo = parseErrorInfo( rpcErrorChild );
+                    }
+                }
+
+                break;
+            }
+        }
+
+        return new NetconfDocumentedException( errorMessage, errorType, errorTag, errorSeverity, errorInfo );
+    }
+
+    private static Map<String, String> parseErrorInfo( Node node ) {
+        Map<String, String> infoMap = new HashMap<>();
+        NodeList children = node.getChildNodes();
+        for( int i = 0; i < children.getLength(); i++ ) {
+            Node child = children.item( i );
+            if( child.getNodeType() == Node.ELEMENT_NODE ) {
+                infoMap.put( child.getNodeName(), child.getTextContent() );
+            }
+        }
+
+        return infoMap;
+    }
+
     public ErrorType getErrorType() {
         return this.errorType;
     }
@@ -134,6 +265,53 @@ public class NetconfDocumentedException extends Exception {
         return this.errorInfo;
     }
 
+    public Document toXMLDocument() {
+        Document doc = null;
+        try {
+            doc = BUILDER_FACTORY.newDocumentBuilder().newDocument();
+
+            Node rpcReply = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_REPLY_KEY );
+            doc.appendChild( rpcReply );
+
+            Node rpcError = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_ERROR );
+            rpcReply.appendChild( rpcError );
+
+            rpcError.appendChild( createTextNode( doc, ERROR_TYPE, getErrorType().getTagValue() ) );
+            rpcError.appendChild( createTextNode( doc, ERROR_TAG, getErrorTag().getTagValue() ) );
+            rpcError.appendChild( createTextNode( doc, ERROR_SEVERITY, getErrorSeverity().getTagValue() ) );
+            rpcError.appendChild( createTextNode( doc, ERROR_MESSAGE, getLocalizedMessage() ) );
+
+            Map<String, String> errorInfoMap = getErrorInfo();
+            if( errorInfoMap != null && !errorInfoMap.isEmpty() ) {
+                /*
+                 * <error-info>
+                 *   <bad-attribute>message-id</bad-attribute>
+                 *   <bad-element>rpc</bad-element>
+                 * </error-info>
+                 */
+
+                Node errorInfoNode = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, ERROR_INFO );
+                errorInfoNode.setPrefix( rpcReply.getPrefix() );
+                rpcError.appendChild( errorInfoNode );
+
+                for ( Entry<String, String> entry : errorInfoMap.entrySet() ) {
+                    errorInfoNode.appendChild( createTextNode( doc, entry.getKey(), entry.getValue() ) );
+                }
+            }
+        }
+        catch( ParserConfigurationException e ) {
+            LOG.error( "Error outputting to XML document", e ); // this shouldn't happen
+        }
+
+        return doc;
+    }
+
+    private Node createTextNode( Document doc, String tag, String textContent ) {
+        Node node = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, tag );
+        node.setTextContent( textContent );
+        return node;
+    }
+
     @Override
     public String toString() {
         return "NetconfDocumentedException{" + "message=" + getMessage() + ", errorType=" + this.errorType
@@ -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.xml;
+package org.opendaylight.controller.netconf.api.xml;
 
 public final class XmlNetconfConstants {
 
@@ -34,6 +34,13 @@ public final class XmlNetconfConstants {
     public static final String RPC_KEY = "rpc";
     public static final String RPC_REPLY_KEY = "rpc-reply";
     public static final String RPC_ERROR = "rpc-error";
+    public static final String ERROR_TYPE = "error-type";
+    public static final String ERROR_TAG = "error-tag";
+    public static final String ERROR_SEVERITY = "error-severity";
+    public static final String ERROR_APP_TAG = "error-app-tag";
+    public static final String ERROR_PATH = "error-path";
+    public static final String ERROR_MESSAGE = "error-message";
+    public static final String ERROR_INFO = "error-info";
     public static final String NAME_KEY = "name";
     public static final String NOTIFICATION_ELEMENT_NAME = "notification";
 
diff --git a/opendaylight/netconf/netconf-api/src/test/java/org/opendaylight/controller/netconf/api/NetconfDocumentedExceptionTest.java b/opendaylight/netconf/netconf-api/src/test/java/org/opendaylight/controller/netconf/api/NetconfDocumentedExceptionTest.java
new file mode 100644 (file)
index 0000000..cdf8b91
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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.netconf.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+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.api.xml.XmlNetconfConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import com.google.common.collect.ImmutableMap;
+
+
+/**
+ * Unit tests for NetconfDocumentedException.
+ *
+ * @author Thomas Pantelis
+ */
+public class NetconfDocumentedExceptionTest {
+
+    private XPath xpath;
+
+    @Before
+    public void setUp() throws Exception {
+        XPathFactory xPathfactory = XPathFactory.newInstance();
+        xpath = xPathfactory.newXPath();
+        xpath.setNamespaceContext( new NamespaceContext() {
+            @Override
+            public Iterator<?> getPrefixes( String namespaceURI ) {
+                return Collections.singletonList( "netconf" ).iterator();
+            }
+
+            @Override
+            public String getPrefix( String namespaceURI ) {
+                return "netconf";
+            }
+
+            @Override
+            public String getNamespaceURI( String prefix ) {
+                return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
+            }
+        } );
+    }
+
+    @Test
+    public void testToAndFromXMLDocument() throws XPathExpressionException {
+        String errorMessage = "mock error message";
+        NetconfDocumentedException ex = new NetconfDocumentedException( errorMessage, null,
+                                                                        ErrorType.protocol,
+                                                                        ErrorTag.data_exists,
+                                                                        ErrorSeverity.warning,
+                                                                        ImmutableMap.of( "foo", "bar" ) );
+
+        Document doc = ex.toXMLDocument();
+        assertNotNull( "Document is null", doc );
+
+        Node rootNode = doc.getDocumentElement();
+
+        assertEquals( "getNamespaceURI", "urn:ietf:params:xml:ns:netconf:base:1.0", rootNode.getNamespaceURI() );
+        assertEquals( "getLocalName", "rpc-reply", rootNode.getLocalName() );
+
+        Node rpcErrorNode = getNode( "/netconf:rpc-reply/netconf:rpc-error", rootNode );
+        assertNotNull( "rpc-error not found", rpcErrorNode );
+
+        Node errorTypeNode = getNode( "netconf:error-type", rpcErrorNode );
+        assertNotNull( "error-type not found", errorTypeNode );
+        assertEquals( "error-type", ErrorType.protocol.getTagValue(),
+                      errorTypeNode.getTextContent() );
+
+        Node errorTagNode = getNode( "netconf:error-tag", rpcErrorNode );
+        assertNotNull( "error-tag not found", errorTagNode );
+        assertEquals( "error-tag", ErrorTag.data_exists.getTagValue(),
+                      errorTagNode.getTextContent() );
+
+        Node errorSeverityNode = getNode( "netconf:error-severity", rpcErrorNode );
+        assertNotNull( "error-severity not found", errorSeverityNode );
+        assertEquals( "error-severity", ErrorSeverity.warning.getTagValue(),
+                      errorSeverityNode.getTextContent() );
+
+        Node errorInfoNode = getNode( "netconf:error-info/netconf:foo", rpcErrorNode );
+        assertNotNull( "foo not found", errorInfoNode );
+        assertEquals( "foo", "bar", errorInfoNode.getTextContent() );
+
+        Node errorMsgNode = getNode( "netconf:error-message", rpcErrorNode );
+        assertNotNull( "error-message not found", errorMsgNode );
+        assertEquals( "error-message", errorMessage, errorMsgNode.getTextContent() );
+
+        // Test fromXMLDocument
+
+        ex = NetconfDocumentedException.fromXMLDocument( doc );
+
+        assertNotNull( "NetconfDocumentedException is null", ex );
+        assertEquals( "getErrorSeverity", ErrorSeverity.warning, ex.getErrorSeverity() );
+        assertEquals( "getErrorTag", ErrorTag.data_exists, ex.getErrorTag() );
+        assertEquals( "getErrorType", ErrorType.protocol, ex.getErrorType() );
+        assertEquals( "getLocalizedMessage", errorMessage, ex.getLocalizedMessage() );
+        assertEquals( "getErrorInfo", ImmutableMap.of( "foo", "bar" ), ex.getErrorInfo() );
+    }
+
+    @SuppressWarnings("unchecked")
+    <T> T getNode( String xpathExp, Node node ) throws XPathExpressionException {
+        return (T)xpath.compile( xpathExp ).evaluate( node, XPathConstants.NODE );
+    }
+}
+
diff --git a/opendaylight/netconf/netconf-cli/README b/opendaylight/netconf/netconf-cli/README
new file mode 100644 (file)
index 0000000..c6a0af4
--- /dev/null
@@ -0,0 +1,113 @@
+usage: 
+Submit address + port for initial TCP connection (PURE TCP CONNECTIONS ARE NOT SUPPORTED YET)
+Submit username + password in addition to address + port for initial SSH connection
+If no arguments(or unexpected combination) is submitted, cli will be started without initial connection
+To use with ODL controller, run with: java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar  --server localhost --port 1830 --username admin --password admin
+
+Generic cli for netconf devices
+
+optional arguments:
+  -h, --help             show this help message and exit
+
+TCP:
+  Base arguments to initiate TCP connection right away
+
+  --server SERVER        Netconf device ip-address/domain name
+  --port PORT            Netconf device port
+
+SSH:
+  SSH credentials, if provided, initial connection will be attempted using SSH
+
+  --username USERNAME    Username for SSH connection
+  --password PASSWORD    Password for SSH connection
+------------------------------------------------------------------------
+
+To run the cli execute:
+
+java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar --username user --password password --server serverIP --port optionalPort
+
+The cli will connect to the remote device automatically.
+The initialization may take a few moments depending on the size of schemas provided by the device.
+To view the progress, one can take a look inside netconfcli.log file (All logs are in this file starting with level TRACE).
+Cli does not print any logging messages to the console, only to the file.
+
+------------------------------------------------------------------------
+
+Correct initialization + connection should display following output:
+
+[maros@localhost target]$ java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar  --server localhost --port 1830 --username admin --password admin
+Connecting to localhost via SSH. Please wait.
+Cli is up, available commands:
+
+add-flow(sal-flow)                                                                            add-group(sal-group)                                                                          
+add-meter(sal-meter)                                                                          begin-transaction(sal-remote)                                                                 
+cancel-commit(ietf-netconf)                                                                   cancel-toast(toaster)                                                                         
+clear-toasts-made(toaster-provider-impl)                                                      close(netconf-cli)                                                                            
+close-session(ietf-netconf)                                                                   commit(ietf-netconf)                                                                          
+connect(netconf-cli)                                                                          copy-config(ietf-netconf)                                                                     
+create-data-change-event-subscription(sal-remote)                                             create-notification-stream(sal-remote)                                                        
+delete-config(ietf-netconf)                                                                   discard-changes(ietf-netconf)                                                                 
+disconnect(netconf-cli)                                                                       edit-config(ietf-netconf)                                                                     
+finish-transaction(flow-capable-transaction)                                                  get(ietf-netconf)                                                                             
+get-aggregate-flow-statistics-from-flow-table-for-all-flows(opendaylight-flow-statistics)     get-aggregate-flow-statistics-from-flow-table-for-given-match(opendaylight-flow-statistics)   
+get-all-flow-statistics-from-flow-table(opendaylight-flow-statistics)                         get-all-flows-statistics-from-all-flow-tables(opendaylight-flow-statistics)                   
+get-all-group-statistics(opendaylight-group-statistics)                                       get-all-meter-config-statistics(opendaylight-meter-statistics)                                
+get-all-meter-statistics(opendaylight-meter-statistics)                                       get-all-node-connectors-statistics(opendaylight-port-statistics)                              
+get-all-queues-statistics-from-all-ports(opendaylight-queue-statistics)                       get-all-queues-statistics-from-given-port(opendaylight-queue-statistics)                      
+get-config(ietf-netconf)                                                                      get-dead-events-count(threadpool-impl)                                                        
+get-flow-statistics-from-flow-table(opendaylight-flow-statistics)                             get-flow-tables-statistics(opendaylight-flow-table-statistics)                                
+get-group-description(opendaylight-group-statistics)                                          get-group-features(opendaylight-group-statistics)                                             
+get-group-statistics(opendaylight-group-statistics)                                           get-meter-features(opendaylight-meter-statistics)                                             
+get-meter-statistics(opendaylight-meter-statistics)                                           get-next-transaction-id(flow-capable-transaction)                                             
+get-node-connector-statistics(opendaylight-port-statistics)                                   get-queue(sal-queue)                                                                          
+get-queue-statistics-from-given-port(opendaylight-queue-statistics)                           get-schema(ietf-netconf-monitoring)                                                           
+help(netconf-cli)                                                                             kill-session(ietf-netconf)                                                                    
+lock(ietf-netconf)                                                                            make-scrambled-with-wheat(kitchen-service-impl)                                               
+make-toast(toaster)                                                                           remove-flow(sal-flow)                                                                         
+remove-group(sal-group)                                                                       remove-meter(sal-meter)                                                                       
+reset(config-logging)                                                                         restock-toaster(toaster)                                                                      
+shutdown(shutdown-impl)                                                                       solicit-refresh(flow-topology-discovery)                                                      
+transmit-packet(packet-processing)                                                            unlock(ietf-netconf)                                                                          
+update-flow(sal-flow)                                                                         update-group(sal-group)                                                                       
+update-meter(sal-meter)                                                                       update-port(sal-port)                                                                         
+update-table(sal-table)                                                                       validate(ietf-netconf)                                                                        
+
+netconf()>
+
+
+------------------------------------------------------------------------
+
+At this stage, any supported rpc can be invoked. To see all possible rpcs press TAB (serves as autocomplete). The output contains all the commands reported after at start-up
+
+------------------------------------------------------------------------
+
+Example step-by-step execution of get-config rpc:
+
+1. Type get-config, hit TAB, hit enter
+2. Cli will now walk all the input arguments of get-config rpc and ask for value
+3. Cli asks for filter value
+4. Submit filter (using TAB autocomplete) as a schema path or type "skip" (to not add any filter) and hit enter
+5. Cli asks for config source (e.g. which data-store to query)
+6. Use TAB to view options and submit either running or candidate data-store
+7. Cli will display configuration of the remote device e.g. :
+
+data {
+  a {
+    address {
+      last-name a
+      first-name o
+      street aaaaa
+    }
+    address {
+      last-name a
+      first-name t
+    }
+    address {
+      last-name a
+      first-name y
+    }
+  }
+}
+
+
+------------------------------------------------------------------------
diff --git a/opendaylight/netconf/netconf-cli/README_ODL b/opendaylight/netconf/netconf-cli/README_ODL
new file mode 100644 (file)
index 0000000..3a15454
--- /dev/null
@@ -0,0 +1,154 @@
+This file contains ODL controller specific examples:
+
+1A. Connecting to ODL controller automatically:
+    a. Make sure ODL controller is running on your or any other accessible device
+    b. Start the cli using this command (in folder controller/opendaylight/netconf/netconf-cli/target/):
+        java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar  --server localhost --port 1830 --username admin --password admin
+    c. The cli will start up in aprox. 20 seconds (Schema download might take some time on the first connection, subsequent attempts should take less time)
+    d. You should see the list of commands avaliable in the controller e.g.:
+        add-flow(sal-flow)                                                                            add-group(sal-group)                                                                          
+        add-meter(sal-meter)                                                                          begin-transaction(sal-remote)                                                                 
+        cancel-commit(ietf-netconf)                                                                   cancel-toast(toaster)                                                                         
+        clear-toasts-made(toaster-provider-impl)                                                      close(netconf-cli)                                                                            
+        close-session(ietf-netconf)                                                                   commit(ietf-netconf)                                                                          
+        connect(netconf-cli)                                                                          copy-config(ietf-netconf)                                                                     
+        create-data-change-event-subscription(sal-remote)                                             ....
+
+
+1B. Connecting to ODL from the CLI:
+    a. Make sure ODL controller is running on your or any other accessible device
+    b. Start the cli using this command (in folder controller/opendaylight/netconf/netconf-cli/target/):
+        java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar
+    c. The cli will start app right away (few seconds)
+    d. You should see only the basic commands e.g. connect, close, help, disconnect 
+    e. Type connect, hit TAB, hit ENTER
+    f. Cli will ask for connect arguments: [address-name, address-port, user-name, user-password]
+    g. Address-name
+        The cli will ask what type of address you want to provide (domain-name or ip-address). This is caused by the yang model for connect command, the address-name is of type ietf-inet-types:host, which is a union of domain-name and ip-address.
+        Submit "domain-name" (TAB can be used for autocompete)
+        Now you need to provide value, submit "localhost" (TAB can be used for autocomplete, as "localhost" is the default value)
+    h. Address-port
+        Submit 1830 (default port for netconf SSH server in ODL)
+    i. User-name
+        Submit "admin"
+    j. User-password
+        Submit "admin"
+    k. The connection will be up in aprox. 20 seconds (Schema download might take some time on the first connection, subsequent attempts should take less time)
+    l. You should see the list of commands available in the controller
+
+
+2.  Disconnecting from ODL in the CLI
+    a. Execute scenario 1A or 1B
+    b. Type "disconn", hit TAB, hit Enter
+    c. You should see the following output:
+        status Connection disconnected
+    d. Use TAB to see available commands, only local commands are present now
+    e. Now you can use the connect command(as in 1B) to connect again
+
+
+3.  Using help command
+    a. Help command can be executed in connected as well as disconnected state
+    b. Type "help", hit TAB, hit Enter
+    c. You should see the help conent containing the list of all available commands with description for each of them e.g.
+        commands  {
+          commands [id=close(netconf-cli)] {
+            id close(netconf-cli)
+            description Close the whole cli
+          }
+          commands [id=help(netconf-cli)] {
+            id help(netconf-cli)
+            description Display help
+          }
+          commands [id=disconnect(netconf-cli)] {
+            id disconnect(netconf-cli)
+            description Disconnect from a netconf device that is currently connected
+          }
+          commands [id=connect(netconf-cli)] {
+            id connect(netconf-cli)
+            description Connect to a remote netconf device, if not connected yet. Connection initialization is blocking and might take some time, depending on amount of yang schemas in remote device.
+          }
+        }
+
+
+4.  Executing get-config command (get-config(ietf-netconf))
+    a. Execute scenario 1A or 1B
+    b. Type "get-config", hit TAB, hit Enter
+    c. Cli will ask for get-config arguments: [filter, source]
+    d. Filter
+        Submit "skip" (This will ignore the filter attribute, ODL does not support filtering at this moment, but will be supported in near future)
+    e. Source
+        You have to choose from candidate, running, startup. Submit running.
+    f. You should see the whole configuration of the ODL e.g.:
+        data {
+          modules {
+            module  {
+              module [name=toaster-provider-impl] {
+                name toaster-provider-impl
+                type (urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?revision=2014-01-31)toaster-provider-impl
+                choice configuration (toaster-provider-impl)  {
+                    ...
+
+
+5.  Executing get command (get(ietf-netconf))
+    a. Execute scenario 1A or 1B
+    b. Type "get(", hit TAB, hit Enter
+    c. Cli will ask for get arguments: [filter]
+    d. Filter
+        Submit "skip" (This will ignore the filter attribute, ODL does not support filtering at this moment, but will be supported in near future)
+    f. You should see the whole data-tree of the ODL
+
+
+6.  Executing edit-config command (edit-config(ietf-netconf))
+    a. Execute scenario 1A or 1B
+    b. Type "edit", hit TAB, hit Enter
+    c. Cli will ask for edit-config arguments: [default-operation, edit-content, error-option, target, test-option]
+    d. Config
+        Config contains the data to be edited
+        1. First you have to specify a path pointing to a concrete data node. Use TAB to help with autocomplete.
+        Submit "modules(config)/module(config)/"
+        Module node is of type list and now you have to construct a whole new list entry for the module list.
+        2. The cli will ask for these nodes: [configuration, name, type]
+            Name - Submit any name e.g. newModule
+            Type - For Type you have to pick from available module types in the ODL, hit TAB for hints
+               Submit "threadfactory-naming(threadpool-impl)" to create a new instance of threadfactory in the ODL.
+            Configuration - For configuration you have to pick from available module types again
+               Submit "threadfactory-naming" to match previous module type
+               The cli will now ask for threadfactory-naming specific configuration: [prefix]
+                    Prefix - Submit any string
+        
+        The cli will now if you want to create another module entry.
+        Submit "N".
+    e. Default-operation
+        Submit "skip" to skip or pick from available e.g. merge, replace etc.
+    f. Error-option
+        Submit "skip" to skip option.
+    g. Config-target
+        This is a choice between running and candidate. Submit candidate to edit configuration only in the candidate datastore.
+    h. Test-option
+        Submit "skip" to skip option.
+    i. You should see OK response
+    j. You can check the candidate datastore change by executing get-config command as in scenario 4, but pick candidate as the source.
+    k. You should see this module in the output:
+        module [name=newModule] {
+            name newModule
+            type (urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?revision=2013-04-05)threadfactory-naming
+            choice configuration (threadfactory-naming)  {
+              name-prefix prefix
+            }
+          }
+
+
+7. Commiting changes from candidate to running datastore
+    a. Execute scenario 6.
+    b. Type commit, hit TAB, hit Enter
+    c. Cli will ask for commit arguments: [confirm-timeout, confirmed, persist, persist-id]. We will skip all these arguments since they are not supported in ODL. Cli should be able to detect this and not ask for them. This is a TODO, by supporting feature/if-feature detection in the CLI.
+    d. Confirm-timeout
+        Skip
+    e. Confirmed
+        N
+    f. Persist
+        Skip
+    g. Persist-id
+        Skip
+    h. You should see OK response
+    i. You can check the candidate datastore change by executing get-config command as in scenario 4.
diff --git a/opendaylight/netconf/netconf-cli/pom.xml b/opendaylight/netconf/netconf-cli/pom.xml
new file mode 100644 (file)
index 0000000..cd7a1aa
--- /dev/null
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- 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-cli</artifactId>
+  <packaging>jar</packaging>
+  <name>${project.artifactId}</name>
+
+  <!--
+  <properties>
+    <checkstyle.skip>true</checkstyle.skip>
+  </properties> -->
+
+  <dependencies>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <!--TODO configure properly -->
+    </dependency>
+    <dependency>
+      <groupId>jline</groupId>
+      <artifactId>jline</artifactId>
+      <version>2.11</version>
+    </dependency>
+    <dependency>
+      <groupId>net.sourceforge.argparse4j</groupId>
+      <artifactId>argparse4j</artifactId>
+      <version>0.4.3</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-core-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-netconf-connector</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>mockito-configuration</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-impl</artifactId>
+      <!--        <version>0.6.2-SNAPSHOT</version>-->
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-json</artifactId>
+      <version>0.6.2-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-model-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-parser-impl</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifest>
+              <mainClass>org.opendaylight.controller.netconf.cli.Main</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <configuration></configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  <mainClass>org.opendaylight.controller.netconf.cli.Main</mainClass>
+                </transformer>
+              </transformers>
+              <shadedArtifactAttached>true</shadedArtifactAttached>
+              <shadedClassifierName>executable</shadedClassifierName>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/Cli.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/Cli.java
new file mode 100644 (file)
index 0000000..a49c7b9
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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.netconf.cli;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import jline.console.UserInterruptException;
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+import org.opendaylight.controller.netconf.cli.commands.Command;
+import org.opendaylight.controller.netconf.cli.commands.CommandConstants;
+import org.opendaylight.controller.netconf.cli.commands.CommandDispatcher;
+import org.opendaylight.controller.netconf.cli.commands.CommandInvocationException;
+import org.opendaylight.controller.netconf.cli.commands.input.Input;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.Output;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.controller.netconf.cli.writer.WriteException;
+import org.opendaylight.controller.netconf.cli.writer.Writer;
+import org.opendaylight.controller.netconf.cli.writer.impl.CompositeNodeWriter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+
+/**
+ * The top level cli state that dispatches command executions
+ */
+public class Cli implements Runnable {
+    private final CommandDispatcher commandRegistry;
+    private final CommandArgHandlerRegistry argumentHandlerRegistry;
+    private final SchemaContextRegistry schemaContextRegistry;
+    private final ConsoleIO consoleIO;
+
+    public Cli(final ConsoleIO consoleIO, final CommandDispatcher commandRegistry,
+            final CommandArgHandlerRegistry argumentHandlerRegistry, final SchemaContextRegistry schemaContextRegistry) {
+        this.consoleIO = consoleIO;
+        this.commandRegistry = commandRegistry;
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+        this.schemaContextRegistry = schemaContextRegistry;
+    }
+
+    @Override
+    public void run() {
+        try {
+            consoleIO.writeLn("Cli is up, available commands:");
+            final RootConsoleContext consoleContext = new RootConsoleContext(commandRegistry);
+            consoleIO.enterContext(consoleContext);
+            consoleIO.complete();
+            consoleIO.writeLn("");
+
+            while (true) {
+                final String commandName = consoleIO.read();
+                final Optional<Command> commandOpt = commandRegistry.getCommand(commandName);
+
+                if (commandOpt.isPresent() == false) {
+                    continue;
+                }
+
+                final Command command = commandOpt.get();
+                try {
+                    consoleIO.enterContext(command.getConsoleContext());
+                    final Output response = command.invoke(handleInput(command.getInputDefinition()));
+                    handleOutput(command, response);
+                } catch (final CommandInvocationException e) {
+                    consoleIO.write(e.getMessage());
+                } catch (final UserInterruptException e) {
+                    consoleIO.writeLn("Command " + command.getCommandId() + " was terminated.");
+                } finally {
+                    consoleIO.leaveContext();
+                }
+
+            }
+        } catch (final IOException e) {
+            throw new RuntimeException("IO failure", e);
+        }
+    }
+
+    private void handleOutput(final Command command, final Output response) {
+        final OutputDefinition outputDefinition = command.getOutputDefinition();
+
+        final Writer<DataSchemaNode> outHandler = argumentHandlerRegistry.getGenericWriter();
+        if (outputDefinition.isEmpty()) {
+            handleEmptyOutput(command, response);
+        } else {
+            handleRegularOutput(response, outputDefinition, outHandler);
+        }
+    }
+
+    private void handleRegularOutput(final Output response, final OutputDefinition outputDefinition,
+            final Writer<DataSchemaNode> outHandler) {
+        final Map<DataSchemaNode, List<Node<?>>> unwrap = response.unwrap(outputDefinition);
+
+        for (final DataSchemaNode schemaNode : unwrap.keySet()) {
+            Preconditions.checkNotNull(schemaNode);
+
+            try {
+
+                // FIXME move custom writer to GenericWriter/Serializers ...
+                // this checks only first level
+                final Optional<Class<? extends Writer<DataSchemaNode>>> customReaderClassOpt = tryGetCustomHandler(schemaNode);
+
+                if (customReaderClassOpt.isPresent()) {
+                    final Writer<DataSchemaNode> customReaderInstance = argumentHandlerRegistry
+                            .getCustomWriter(customReaderClassOpt.get());
+                    Preconditions.checkNotNull(customReaderInstance, "Unknown custom writer: %s",
+                            customReaderClassOpt.get());
+                    customReaderInstance.write(schemaNode, unwrap.get(schemaNode));
+                } else {
+                    outHandler.write(schemaNode, unwrap.get(schemaNode));
+                }
+
+            } catch (final WriteException e) {
+                throw new IllegalStateException("Unable to write value for: " + schemaNode.getQName() + " from: "
+                        + unwrap.get(schemaNode), e);
+            }
+        }
+    }
+
+    private void handleEmptyOutput(final Command command, final Output response) {
+        try {
+            new CompositeNodeWriter(consoleIO, new OutFormatter()).write(null,
+                    Collections.<Node<?>> singletonList(response.getOutput()));
+        } catch (final WriteException e) {
+            throw new IllegalStateException("Unable to write value for: " + response.getOutput().getNodeType()
+                    + " from: " + command.getCommandId(), e);
+        }
+    }
+
+    private Input handleInput(final InputDefinition inputDefinition) {
+        List<Node<?>> allArgs = Collections.emptyList();
+        try {
+            if (!inputDefinition.isEmpty()) {
+                allArgs = argumentHandlerRegistry.getGenericReader(schemaContextRegistry.getLocalSchemaContext()).read(
+                        inputDefinition.getInput());
+            }
+        } catch (final ReadingException e) {
+            throw new IllegalStateException("Unable to read value for: " + inputDefinition.getInput().getQName(), e);
+        }
+
+        return new Input(allArgs);
+    }
+
+    // TODO move tryGet to GenericWriter, GenericReader has the same code
+    private <T> Optional<Class<? extends T>> tryGetCustomHandler(final DataSchemaNode dataSchemaNode) {
+
+        for (final UnknownSchemaNode unknownSchemaNode : dataSchemaNode.getUnknownSchemaNodes()) {
+
+            if (isExtenstionForCustomHandler(unknownSchemaNode)) {
+                final String argumentHandlerClassName = unknownSchemaNode.getNodeParameter();
+                try {
+                    final Class<?> argumentClass = Class.forName(argumentHandlerClassName);
+                    // TODO add check before cast
+                    return Optional.<Class<? extends T>> of((Class<? extends T>) argumentClass);
+                } catch (final ClassNotFoundException e) {
+                    throw new IllegalArgumentException("Unknown custom reader class " + argumentHandlerClassName
+                            + " for: " + dataSchemaNode.getQName());
+                }
+            }
+        }
+
+        return Optional.absent();
+    }
+
+    private boolean isExtenstionForCustomHandler(final UnknownSchemaNode unknownSchemaNode) {
+        final QName qName = unknownSchemaNode.getExtensionDefinition().getQName();
+        return qName.equals(CommandConstants.ARG_HANDLER_EXT_QNAME);
+    }
+
+    private static final class RootConsoleContext implements ConsoleContext {
+
+        private final Completer completer;
+
+        public RootConsoleContext(final CommandDispatcher commandRegistry) {
+            completer = new CommandCompleter(commandRegistry);
+        }
+
+        @Override
+        public Completer getCompleter() {
+            return completer;
+        }
+
+        @Override
+        public Optional<String> getPrompt() {
+            return Optional.absent();
+        }
+
+        private class CommandCompleter extends StringsCompleter {
+
+            private final CommandDispatcher commandRegistry;
+
+            public CommandCompleter(final CommandDispatcher commandRegistry) {
+                this.commandRegistry = commandRegistry;
+            }
+
+            @Override
+            public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+                getStrings().clear();
+                getStrings().addAll(commandRegistry.getCommandIds());
+                return super.complete(buffer, cursor, candidates);
+            }
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/CommandArgHandlerRegistry.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/CommandArgHandlerRegistry.java
new file mode 100644 (file)
index 0000000..2eab22a
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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.netconf.cli;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.Reader;
+import org.opendaylight.controller.netconf.cli.reader.custom.ConfigReader;
+import org.opendaylight.controller.netconf.cli.reader.custom.EditContentReader;
+import org.opendaylight.controller.netconf.cli.reader.custom.FilterReader;
+import org.opendaylight.controller.netconf.cli.reader.custom.PasswordReader;
+import org.opendaylight.controller.netconf.cli.reader.impl.GenericReader;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.controller.netconf.cli.writer.Writer;
+import org.opendaylight.controller.netconf.cli.writer.custom.DataWriter;
+import org.opendaylight.controller.netconf.cli.writer.impl.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Keeps custom and generic input/output arguments handlers. Custom handlers are
+ * constructed lazily, due to remote schema context acquisition.
+ */
+public class CommandArgHandlerRegistry {
+
+    private final ConsoleIO consoleIO;
+    private final SchemaContextRegistry schemaContextRegistry;
+
+    private final Map<Class<? extends Reader<? extends DataSchemaNode>>, ReaderProvider> customReaders = Maps
+            .newHashMap();
+    private final Map<Class<? extends Writer<DataSchemaNode>>, WriterProvider> customWriters = Maps.newHashMap();
+
+    public CommandArgHandlerRegistry(final ConsoleIO consoleIO, final SchemaContextRegistry schemaContextRegistry) {
+        this.consoleIO = consoleIO;
+        this.schemaContextRegistry = schemaContextRegistry;
+
+        setUpReaders();
+        setUpWriters();
+    }
+
+    private void setUpWriters() {
+        customWriters.put(DataWriter.class, new DataWriterProvider());
+    }
+
+    private void setUpReaders() {
+        customReaders.put(PasswordReader.class, new PasswordReaderProvider());
+        customReaders.put(FilterReader.class, new FilterReaderProvider());
+        customReaders.put(ConfigReader.class, new ConfigReaderProvider());
+        customReaders.put(EditContentReader.class, new EditContentReaderProvider());
+    }
+
+    public synchronized Reader<? extends DataSchemaNode> getCustomReader(
+            final Class<? extends Reader<DataSchemaNode>> readerType) {
+        return customReaders.get(readerType).provide(consoleIO, this, schemaContextRegistry);
+    }
+
+    private static SchemaContext getRemoteSchema(final Class<?> handlerType,
+            final SchemaContextRegistry schemaContextRegistry) {
+        final Optional<SchemaContext> remoteSchemaContext = schemaContextRegistry.getRemoteSchemaContext();
+        Preconditions.checkState(remoteSchemaContext.isPresent(),
+                "Remote schema context not acquired yet, cannot get handler %s", handlerType);
+        return remoteSchemaContext.get();
+    }
+
+    public synchronized Reader<DataSchemaNode> getGenericReader(final SchemaContext schemaContext) {
+        return new GenericReader(consoleIO, this, schemaContext);
+    }
+
+    public synchronized Reader<DataSchemaNode> getGenericReader(final SchemaContext schemaContext,
+            final boolean readConfigNode) {
+        return new GenericReader(consoleIO, this, schemaContext, readConfigNode);
+    }
+
+    public synchronized Writer<DataSchemaNode> getCustomWriter(final Class<? extends Writer<DataSchemaNode>> writerType) {
+        return customWriters.get(writerType).provide(consoleIO, getRemoteSchema(writerType, schemaContextRegistry),
+                this);
+    }
+
+    public synchronized Writer<DataSchemaNode> getGenericWriter() {
+        return new NormalizedNodeWriter(consoleIO, new OutFormatter());
+    }
+
+    /**
+     * Reader providers, in order to construct readers lazily
+     */
+    private static interface ReaderProvider {
+        Reader<? extends DataSchemaNode> provide(ConsoleIO consoleIO,
+                final CommandArgHandlerRegistry commandArgHandlerRegistry,
+                final SchemaContextRegistry schemaContextRegistry);
+    }
+
+    private static final class FilterReaderProvider implements ReaderProvider {
+        @Override
+        public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
+                final CommandArgHandlerRegistry commandArgHandlerRegistry,
+                final SchemaContextRegistry schemaContextRegistry) {
+            return new FilterReader(consoleIO, getRemoteSchema(FilterReader.class, schemaContextRegistry));
+        }
+    }
+
+    private static final class ConfigReaderProvider implements ReaderProvider {
+        @Override
+        public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
+                final CommandArgHandlerRegistry commandArgHandlerRegistry,
+                final SchemaContextRegistry schemaContextRegistry) {
+            return new ConfigReader(consoleIO, getRemoteSchema(ConfigReader.class, schemaContextRegistry),
+                    commandArgHandlerRegistry);
+        }
+    }
+
+    private static final class EditContentReaderProvider implements ReaderProvider {
+        @Override
+        public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
+                final CommandArgHandlerRegistry commandArgHandlerRegistry,
+                final SchemaContextRegistry schemaContextRegistry) {
+            return new EditContentReader(consoleIO, commandArgHandlerRegistry, getRemoteSchema(EditContentReader.class,
+                    schemaContextRegistry));
+        }
+    }
+
+    private static final class PasswordReaderProvider implements ReaderProvider {
+        @Override
+        public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
+                final CommandArgHandlerRegistry commandArgHandlerRegistry,
+                final SchemaContextRegistry schemaContextRegistry) {
+            return new PasswordReader(consoleIO, schemaContextRegistry.getLocalSchemaContext());
+        }
+    }
+
+    /**
+     * Writer providers, in order to construct readers lazily
+     */
+    private static interface WriterProvider {
+        Writer<DataSchemaNode> provide(ConsoleIO consoleIO, SchemaContext schema,
+                final CommandArgHandlerRegistry commandArgHandlerRegistry);
+    }
+
+    private class DataWriterProvider implements WriterProvider {
+        @Override
+        public Writer<DataSchemaNode> provide(final ConsoleIO consoleIO, final SchemaContext schema,
+                final CommandArgHandlerRegistry commandArgHandlerRegistry) {
+            return new DataWriter(consoleIO, new OutFormatter(), schema);
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/Main.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/Main.java
new file mode 100644 (file)
index 0000000..8605501
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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.netconf.cli;
+
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import net.sourceforge.argparse4j.ArgumentParsers;
+import net.sourceforge.argparse4j.inf.ArgumentGroup;
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+import net.sourceforge.argparse4j.inf.ArgumentParserException;
+import net.sourceforge.argparse4j.inf.Namespace;
+import org.opendaylight.controller.netconf.cli.commands.CommandDispatcher;
+import org.opendaylight.controller.netconf.cli.commands.local.Connect;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIOImpl;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Parse arguments, start remote device connection and start CLI after the
+ * connection is fully up
+ */
+public class Main {
+
+    public static void main(final String[] args) {
+        final CliArgumentParser cliArgs = new CliArgumentParser();
+        try {
+            cliArgs.parse(args);
+        } catch (final ArgumentParserException e) {
+            // Just end the cli, exception was handled by the CliArgumentParser
+            return;
+        }
+
+        final ConsoleIO consoleIO;
+        try {
+            consoleIO = new ConsoleIOImpl();
+        } catch (final IOException e) {
+            handleStartupException(e);
+            return;
+        }
+
+        final SchemaContext localSchema = CommandDispatcher.parseSchema(CommandDispatcher.LOCAL_SCHEMA_PATHS);
+        final SchemaContextRegistry schemaContextRegistry = new SchemaContextRegistry(localSchema);
+
+        final CommandDispatcher commandDispatcher = new CommandDispatcher();
+        final CommandArgHandlerRegistry argumentHandlerRegistry = new CommandArgHandlerRegistry(consoleIO,
+                schemaContextRegistry);
+        final NetconfDeviceConnectionManager connectionManager = new NetconfDeviceConnectionManager(commandDispatcher,
+                argumentHandlerRegistry, schemaContextRegistry, consoleIO);
+
+        commandDispatcher.addLocalCommands(connectionManager, localSchema, cliArgs.getConnectionTimeoutMs());
+
+        switch (cliArgs.connectionArgsPresent()) {
+        case TCP: {
+            // FIXME support pure TCP
+            handleRunningException(new UnsupportedOperationException("PURE TCP CONNECTIONS ARE NOT SUPPORTED YET, USE SSH INSTEAD BY PROVIDING USERNAME AND PASSWORD AS WELL"));
+            return;
+        }
+        case SSH: {
+            writeStatus(consoleIO, "Connecting to %s via SSH. Please wait.", cliArgs.getAddress());
+            connectionManager.connectBlocking(cliArgs.getAddress(), getClientSshConfig(cliArgs));
+            break;
+        }
+        case NONE: {/* Do not connect initially */
+            writeStatus(consoleIO, "No initial connection. To connect use the connect command");
+        }
+        }
+
+        try {
+            new Cli(consoleIO, commandDispatcher, argumentHandlerRegistry, schemaContextRegistry).run();
+        } catch (final Exception e) {
+            // TODO Running exceptions have to be handled properly
+            handleRunningException(e);
+            System.exit(0);
+        }
+    }
+
+    private static NetconfClientConfigurationBuilder getClientConfig(final CliArgumentParser cliArgs) {
+        return NetconfClientConfigurationBuilder.create().withAddress(cliArgs.getServerAddress())
+                .withConnectionTimeoutMillis(cliArgs.getConnectionTimeoutMs())
+                .withReconnectStrategy(Connect.getReconnectStrategy())
+                .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TCP);
+    }
+
+    private static NetconfClientConfigurationBuilder getClientSshConfig(final CliArgumentParser cliArgs) {
+        return NetconfClientConfigurationBuilder.create().withAddress(cliArgs.getServerAddress())
+                .withConnectionTimeoutMillis(cliArgs.getConnectionTimeoutMs())
+                .withReconnectStrategy(Connect.getReconnectStrategy())
+                .withAuthHandler(cliArgs.getCredentials())
+                .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH);
+    }
+
+    private static void handleStartupException(final IOException e) {
+        handleException(e, "Unable to initialize CLI");
+    }
+
+    private static void handleException(final Exception e, final String message) {
+        System.err.println(message);
+        e.printStackTrace(System.err);
+    }
+
+    private static void writeStatus(final ConsoleIO io, final String blueprint, final Object... args) {
+        try {
+            io.formatLn(blueprint, args);
+        } catch (final IOException e) {
+            handleStartupException(e);
+        }
+    }
+
+    private static void handleRunningException(final Exception e) {
+        handleException(e, "Unexpected CLI runtime exception");
+    }
+
+    private static final class CliArgumentParser {
+
+        public static final String USERNAME = "username";
+        public static final String PASSWORD = "password";
+        public static final String SERVER = "server";
+        public static final String PORT = "port";
+
+        public static final String CONNECT_TIMEOUT = "connectionTimeout";
+        public static final int DEFAULT_CONNECTION_TIMEOUT_MS = 50000;
+
+        private final ArgumentParser parser;
+        private Namespace parsed;
+
+        private CliArgumentParser() {
+            parser = ArgumentParsers.newArgumentParser("Netconf cli").defaultHelp(true)
+                    .description("Generic cli for netconf devices")
+                    .usage("Submit address + port for initial TCP connection (PURE TCP CONNECTIONS ARE NOT SUPPORTED YET)\n" +
+                            "Submit username + password in addition to address + port for initial SSH connection\n" +
+                            "If no arguments(or unexpected combination) is submitted, cli will be started without initial connection\n" +
+                            "To use with ODL controller, run with: java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar  --server localhost --port 1830 --username admin --password admin");
+
+            final ArgumentGroup tcpGroup = parser.addArgumentGroup("TCP")
+                    .description("Base arguments to initiate TCP connection right away");
+
+            tcpGroup.addArgument("--" + SERVER).help("Netconf device ip-address/domain name");
+            tcpGroup.addArgument("--" + PORT).type(Integer.class).help("Netconf device port");
+            tcpGroup.addArgument("--" + CONNECT_TIMEOUT)
+                    .type(Integer.class)
+                    .setDefault(DEFAULT_CONNECTION_TIMEOUT_MS)
+                    .help("Timeout(in ms) for connection to succeed, if the connection is not fully established by the time is up, " +
+                            "connection attempt is considered a failure. This attribute is not working as expected yet");
+
+            final ArgumentGroup sshGroup = parser.addArgumentGroup("SSH")
+                    .description("SSH credentials, if provided, initial connection will be attempted using SSH");
+
+            sshGroup.addArgument("--" + USERNAME).help("Username for SSH connection");
+            sshGroup.addArgument("--" + PASSWORD).help("Password for SSH connection");
+        }
+
+        public void parse(final String[] args) throws ArgumentParserException {
+            try {
+                this.parsed = parser.parseArgs(args);
+            } catch (final ArgumentParserException e) {
+                parser.handleError(e);
+                throw e;
+            }
+        }
+
+        public InetSocketAddress getServerAddress() {
+            try {
+                return new InetSocketAddress(InetAddress.getByName(getAddress()), getPort());
+            } catch (final UnknownHostException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
+        private Integer getPort() {
+            checkParsed();
+            return parsed.getInt(PORT);
+        }
+
+        private String getAddress() {
+            checkParsed();
+            return getString(SERVER);
+        }
+
+        private Integer getConnectionTimeoutMs() {
+            checkParsed();
+            return parsed.getInt(CONNECT_TIMEOUT);
+        }
+
+        private void checkParsed() {
+            Preconditions.checkState(parsed != null, "No arguments were parsed yet");
+        }
+
+        public String getUsername() {
+            checkParsed();
+            return getString(USERNAME);
+        }
+
+        private String getString(final String key) {
+            return parsed.getString(key);
+        }
+
+        public LoginPassword getCredentials() {
+            return new LoginPassword(getUsername(), getPassword());
+        }
+
+        public String getPassword() {
+            checkParsed();
+            return getString(PASSWORD);
+        }
+
+        public InitialConnectionType connectionArgsPresent() {
+            if(getAddress() != null && getPort() != null) {
+                if(getUsername() != null && getPassword() != null) {
+                    return InitialConnectionType.SSH;
+                }
+                return InitialConnectionType.TCP;
+            }
+            return InitialConnectionType.NONE;
+        }
+
+        enum InitialConnectionType {
+            TCP, SSH, NONE
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/NetconfDeviceConnectionHandler.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/NetconfDeviceConnectionHandler.java
new file mode 100644 (file)
index 0000000..bd092bc
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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.netconf.cli;
+
+import com.google.common.base.Optional;
+import jline.console.completer.Completer;
+import jline.console.completer.NullCompleter;
+import org.opendaylight.controller.netconf.cli.commands.CommandDispatcher;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+
+/**
+ * Implementation of RemoteDeviceHandler. Integrates cli with
+ * sal-netconf-connector.
+ */
+public class NetconfDeviceConnectionHandler implements RemoteDeviceHandler<NetconfSessionCapabilities> {
+
+    private final CommandDispatcher commandDispatcher;
+    private final SchemaContextRegistry schemaContextRegistry;
+    private final ConsoleIO console;
+    private final String deviceId;
+
+    private boolean up = false;
+
+    public NetconfDeviceConnectionHandler(final CommandDispatcher commandDispatcher,
+            final SchemaContextRegistry schemaContextRegistry, final ConsoleIO console, final String deviceId) {
+        this.commandDispatcher = commandDispatcher;
+        this.schemaContextRegistry = schemaContextRegistry;
+        this.console = console;
+        this.deviceId = deviceId;
+    }
+
+    @Override
+    public synchronized void onDeviceConnected(final SchemaContextProvider contextProvider,
+            final NetconfSessionCapabilities capabilities, final RpcImplementation rpcImplementation) {
+        console.enterRootContext(new ConsoleContext() {
+
+            @Override
+            public Optional<String> getPrompt() {
+                return Optional.of(deviceId);
+            }
+
+            @Override
+            public Completer getCompleter() {
+                return new NullCompleter();
+            }
+        });
+
+        // TODO Load schemas for base netconf + inet types from remote device if
+        // possible
+        // TODO detect netconf base version
+        // TODO detect inet types version
+        commandDispatcher.addRemoteCommands(rpcImplementation, contextProvider.getSchemaContext());
+        schemaContextRegistry.setRemoteSchemaContext(contextProvider.getSchemaContext());
+        up = true;
+        this.notify();
+    }
+
+    /**
+     * @return true if connection was fully established
+     */
+    public synchronized boolean isUp() {
+        return up;
+    }
+
+    @Override
+    public synchronized void onDeviceDisconnected() {
+        console.leaveRootContext();
+        commandDispatcher.removeRemoteCommands();
+        schemaContextRegistry.setRemoteSchemaContext(null);
+        up = false;
+    }
+
+    @Override
+    public void onNotification(final CompositeNode compositeNode) {
+        // FIXME
+    }
+
+    @Override
+    public void close() {
+        // FIXME
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/NetconfDeviceConnectionManager.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/NetconfDeviceConnectionManager.java
new file mode 100644 (file)
index 0000000..3dd892e
--- /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.netconf.cli;
+
+import com.google.common.base.Preconditions;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.opendaylight.controller.netconf.cli.commands.CommandDispatcher;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
+import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+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;
+import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders;
+
+/**
+ * Manages connect/disconnect to 1 remote device
+ */
+public class NetconfDeviceConnectionManager implements Closeable {
+
+    private final CommandDispatcher commandDispatcher;
+    private final SchemaContextRegistry schemaContextRegistry;
+    private final ConsoleIO console;
+
+    private final ExecutorService executor;
+    private final NioEventLoopGroup nettyThreadGroup;
+    private final NetconfClientDispatcherImpl netconfClientDispatcher;
+
+    // Connection
+    private NetconfDeviceConnectionHandler handler;
+    private NetconfDevice device;
+    private NetconfDeviceCommunicator listener;
+
+    public NetconfDeviceConnectionManager(final CommandDispatcher commandDispatcher,
+            final CommandArgHandlerRegistry argumentHandlerRegistry, final SchemaContextRegistry schemaContextRegistry,
+            final ConsoleIO consoleIO) {
+        this.commandDispatcher = commandDispatcher;
+        this.schemaContextRegistry = schemaContextRegistry;
+        this.console = consoleIO;
+
+        executor = Executors.newSingleThreadExecutor();
+        nettyThreadGroup = new NioEventLoopGroup();
+        netconfClientDispatcher = new NetconfClientDispatcherImpl(nettyThreadGroup, nettyThreadGroup,
+                new HashedWheelTimer());
+    }
+
+    // TODO we receive configBuilder in order to add SessionListener, Session
+    // Listener should not be part of config
+    public synchronized void connect(final String name, final NetconfClientConfigurationBuilder configBuilder) {
+        // TODO change IllegalState exceptions to custom ConnectionException
+        Preconditions.checkState(listener == null, "Already connected");
+
+        final RemoteDeviceId deviceId = new RemoteDeviceId(name);
+
+        handler = new NetconfDeviceConnectionHandler(commandDispatcher, schemaContextRegistry,
+                console, name);
+        device = NetconfDevice.createNetconfDevice(deviceId, getGlobalNetconfSchemaProvider(), executor, handler);
+        listener = new NetconfDeviceCommunicator(deviceId, device);
+        configBuilder.withSessionListener(listener);
+        listener.initializeRemoteConnection(netconfClientDispatcher, configBuilder.build());
+    }
+
+    /**
+     * Blocks thread until connection is fully established
+     */
+    public synchronized Set<String> connectBlocking(final String name, final NetconfClientConfigurationBuilder configBuilder) {
+        this.connect(name, configBuilder);
+        synchronized (handler) {
+            while (handler.isUp() == false) {
+                try {
+                    // TODO implement Timeout for unsuccessful connection
+                    handler.wait();
+                } catch (final InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    throw new IllegalArgumentException(e);
+                }
+            }
+        }
+
+        return commandDispatcher.getRemoteCommandIds();
+    }
+
+    public synchronized void disconnect() {
+        Preconditions.checkState(listener != null, "Not connected yet");
+        Preconditions.checkState(handler.isUp(), "Not connected yet");
+        listener.close();
+        listener = null;
+        device = null;
+        handler.close();
+        handler = null;
+    }
+
+    private static AbstractCachingSchemaSourceProvider<String, InputStream> getGlobalNetconfSchemaProvider() {
+        // FIXME move to args
+        final String storageFile = "cache/schema";
+        final File directory = new File(storageFile);
+        final SchemaSourceProvider<String> defaultProvider = SchemaSourceProviders.noopProvider();
+        return FilesystemSchemaCachingProvider.createFromStringSourceProvider(defaultProvider, directory);
+    }
+
+    @Override
+    public void close() throws IOException {
+        executor.shutdownNow();
+        nettyThreadGroup.shutdownGracefully();
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/SchemaContextRegistry.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/SchemaContextRegistry.java
new file mode 100644 (file)
index 0000000..5c3cfe7
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.netconf.cli;
+
+import com.google.common.base.Optional;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Contains the local schema context (containing local commands) and remote schema context (remote commands)
+ *
+ * Remote commands are set only after the connection is fully established. So classes using the remote schema context
+ */
+public class SchemaContextRegistry {
+
+    private final SchemaContext localSchemaContext;
+    private SchemaContext remoteSchemaContext;
+
+    public SchemaContextRegistry(final SchemaContext localSchemaContext) {
+        this.localSchemaContext = localSchemaContext;
+    }
+
+    public synchronized Optional<SchemaContext> getRemoteSchemaContext() {
+        return Optional.fromNullable(remoteSchemaContext);
+    }
+
+    public SchemaContext getLocalSchemaContext() {
+        return localSchemaContext;
+    }
+
+    public synchronized void setRemoteSchemaContext(final SchemaContext remoteSchemaContext) {
+        this.remoteSchemaContext = remoteSchemaContext;
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/AbstractCommand.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/AbstractCommand.java
new file mode 100644 (file)
index 0000000..f02ce74
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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.netconf.cli.commands;
+
+import com.google.common.base.Optional;
+import jline.console.completer.Completer;
+import jline.console.completer.NullCompleter;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public abstract class AbstractCommand implements Command {
+
+    private final QName qName;
+    private final InputDefinition args;
+    private final OutputDefinition output;
+    private final String description;
+
+    public AbstractCommand(final QName qName, final InputDefinition args, final OutputDefinition output,
+            final String description) {
+        this.qName = qName;
+        this.args = args;
+        this.output = output;
+        this.description = description;
+    }
+
+    protected static OutputDefinition getOutputDefinition(final RpcDefinition rpcDefinition) {
+        final ContainerSchemaNode output = rpcDefinition.getOutput();
+        return output != null ? OutputDefinition.fromOutput(output) : OutputDefinition.empty();
+    }
+
+    protected static InputDefinition getInputDefinition(final RpcDefinition rpcDefinition) {
+        final ContainerSchemaNode input = rpcDefinition.getInput();
+        return InputDefinition.fromInput(input);
+    }
+
+    @Override
+    public InputDefinition getInputDefinition() {
+        return args;
+    }
+
+    @Override
+    public OutputDefinition getOutputDefinition() {
+        return output;
+    }
+
+    @Override
+    public QName getCommandId() {
+        return qName;
+    }
+
+    @Override
+    public ConsoleContext getConsoleContext() {
+        return new ConsoleContext() {
+
+            @Override
+            public Completer getCompleter() {
+                return new NullCompleter();
+            }
+
+            @Override
+            public Optional<String> getPrompt() {
+                return Optional.of(qName.getLocalName());
+            }
+        };
+    }
+
+    @Override
+    public Optional<String> getCommandDescription() {
+        return Optional.fromNullable(description);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/Command.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/Command.java
new file mode 100644 (file)
index 0000000..1435abd
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.netconf.cli.commands;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.cli.commands.input.Input;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.Output;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * Local command e.g. help or remote rpc e.g. get-config must conform to this interface
+ */
+public interface Command {
+
+    Output invoke(Input inputArgs) throws CommandInvocationException;
+
+    InputDefinition getInputDefinition();
+
+    OutputDefinition getOutputDefinition();
+
+    QName getCommandId();
+
+    Optional<String> getCommandDescription();
+
+    ConsoleContext getConsoleContext();
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandConstants.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandConstants.java
new file mode 100644 (file)
index 0000000..7159af5
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.netconf.cli.commands;
+
+import java.net.URI;
+import org.opendaylight.controller.netconf.cli.io.IOUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class CommandConstants {
+
+    // Local command ids are defined here, this links the implementation to the rpc definition in yang
+    // Better way needs to be found to provide this link instead of hardcoded QNames (e.g. yang extension)
+    public static final QName HELP_QNAME = QName.create(URI.create("netconf:cli"), IOUtil.parseDate("2014-05-22"), "help");
+    public static final QName CLOSE_QNAME = QName.create(HELP_QNAME, "close");
+    public static final QName CONNECT_QNAME = QName.create(HELP_QNAME, "connect");
+    public static final QName DISCONNECT_QNAME = QName.create(CONNECT_QNAME, "disconnect");
+
+    public static final QName ARG_HANDLER_EXT_QNAME = QName.create(
+            URI.create("urn:ietf:params:xml:ns:netconf:base:1.0:cli"), IOUtil.parseDate("2014-05-26"),
+            "argument-handler");
+
+    public static final QName NETCONF_BASE_QNAME = QName.create("urn:ietf:params:xml:ns:netconf:base:1.0", "2011-06-01",
+            "netconf");
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandDispatcher.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandDispatcher.java
new file mode 100644 (file)
index 0000000..ec7b5b4
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * 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.netconf.cli.commands;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.controller.netconf.cli.NetconfDeviceConnectionHandler;
+import org.opendaylight.controller.netconf.cli.NetconfDeviceConnectionManager;
+import org.opendaylight.controller.netconf.cli.commands.local.Close;
+import org.opendaylight.controller.netconf.cli.commands.local.Connect;
+import org.opendaylight.controller.netconf.cli.commands.local.Disconnect;
+import org.opendaylight.controller.netconf.cli.commands.local.Help;
+import org.opendaylight.controller.netconf.cli.commands.remote.RemoteCommand;
+import org.opendaylight.controller.netconf.cli.io.IOUtil;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+/**
+ * The registry of available commands local + remote. Created from schema contexts.
+ */
+public class CommandDispatcher {
+
+    // TODO extract interface
+
+    private final Map<QName, Command> localCommands = Maps.newHashMap();
+    private final Map<String, QName> nameToQNameLocal = Maps.newHashMap();
+
+    private final Map<QName, Command> remoteCommands = Maps.newHashMap();
+    private final Map<String, QName> nameToQNameRemote = Maps.newHashMap();
+
+    public synchronized Map<QName, Command> getCommands() {
+        return Collections.unmodifiableMap(mergeCommands());
+    }
+
+    private Map<QName, Command> mergeCommands() {
+        // TODO cache this merged map
+        return mergeMaps(remoteCommands, localCommands);
+    }
+
+    private Map<String, QName> mergeCommandIds() {
+        // TODO cache this merged map
+        return mergeMaps(nameToQNameRemote, nameToQNameLocal);
+    }
+
+    private <K, V> Map<K, V> mergeMaps(final Map<K, V> remoteMap, final Map<K, V> localMap) {
+        final Map<K, V> mergedCommands = Maps.newHashMap();
+        mergedCommands.putAll(remoteMap);
+        mergedCommands.putAll(localMap);
+        return mergedCommands;
+    }
+
+    public synchronized Set<String> getCommandIds() {
+        return mergeCommandIds().keySet();
+    }
+
+    public synchronized Set<String> getRemoteCommandIds() {
+        return nameToQNameRemote.keySet();
+    }
+
+    public synchronized Optional<Command> getCommand(final String nameWithModule) {
+        final QName commandQName = mergeCommandIds().get(nameWithModule);
+        final Map<QName, Command> qNameCommandMap = mergeCommands();
+        if(commandQName == null || qNameCommandMap.containsKey(commandQName) == false) {
+            return Optional.absent();
+        }
+
+        return Optional.of(qNameCommandMap.get(commandQName));
+    }
+
+    public synchronized Optional<Command> getCommand(final QName qName) {
+        return Optional.fromNullable(mergeCommands().get(qName));
+    }
+
+    private static Optional<Command> getCommand(final Map<String, QName> commandNameMap, final Map<QName, Command> commands, final String nameWithModule) {
+        final QName qName = commandNameMap.get(nameWithModule);
+        if(qName == null)
+            return Optional.absent();
+
+        final Command command = commands.get(qName);
+        if(command == null) {
+            return Optional.absent();
+        }
+
+        return Optional.of(command);
+    }
+
+    public static final Collection<String> BASE_NETCONF_SCHEMA_PATHS = Lists.newArrayList("/schema/remote/ietf-netconf.yang",
+            "/schema/common/netconf-cli-ext.yang", "/schema/common/ietf-inet-types.yang");
+
+    public synchronized void addRemoteCommands(final RpcImplementation rpcInvoker, final SchemaContext remoteSchema) {
+        this.addRemoteCommands(rpcInvoker, remoteSchema, parseSchema(BASE_NETCONF_SCHEMA_PATHS));
+    }
+
+    public synchronized void addRemoteCommands(final RpcImplementation rpcInvoker, final SchemaContext remoteSchema, final SchemaContext baseNetconfSchema) {
+        for (final SchemaContext context : Lists.newArrayList(remoteSchema, baseNetconfSchema)) {
+            for (final Module module : context.getModules()) {
+                for (final RpcDefinition rpcDefinition : module.getRpcs()) {
+                    final Command command = RemoteCommand.fromRpc(rpcDefinition, rpcInvoker);
+                    remoteCommands.put(rpcDefinition.getQName(), command);
+                    nameToQNameRemote.put(getCommandName(rpcDefinition, module), rpcDefinition.getQName());
+                }
+            }
+        }
+    }
+
+    public synchronized void removeRemoteCommands() {
+        remoteCommands.clear();
+        nameToQNameRemote.clear();
+    }
+
+    public static final Collection<String> LOCAL_SCHEMA_PATHS = Lists.newArrayList("/schema/local/netconf-cli.yang", "/schema/common/netconf-cli-ext.yang",
+            "/schema/common/ietf-inet-types.yang");
+
+    public synchronized void addLocalCommands(final NetconfDeviceConnectionManager connectionManager, final SchemaContext localSchema, final Integer connectionTimeout) {
+        for (final Module module : localSchema.getModules()) {
+            for (final RpcDefinition rpcDefinition : module.getRpcs()) {
+
+                // FIXME make local commands extensible
+                // e.g. by yang extension defining java class to be instantiated
+                // problem is with command specific resources
+                // e.g. Help would need command registry
+                final Command localCommand;
+                if (rpcDefinition.getQName().equals(CommandConstants.HELP_QNAME)) {
+                    localCommand = Help.create(rpcDefinition, this);
+                } else if (rpcDefinition.getQName().equals(CommandConstants.CLOSE_QNAME)) {
+                    localCommand = Close.create(rpcDefinition);
+                } else if (rpcDefinition.getQName().equals(CommandConstants.CONNECT_QNAME)) {
+                    localCommand = Connect.create(rpcDefinition, connectionManager, connectionTimeout);
+                } else if (rpcDefinition.getQName().equals(CommandConstants.DISCONNECT_QNAME)) {
+                    localCommand = Disconnect.create(rpcDefinition, connectionManager);
+                } else {
+                    throw new IllegalStateException("No command implementation available for local command: " + rpcDefinition.getQName());
+                }
+
+                localCommands.put(localCommand.getCommandId(), localCommand);
+                nameToQNameLocal.put(getCommandName(rpcDefinition, module), localCommand.getCommandId());
+            }
+        }
+    }
+
+    private static String getCommandName(final RpcDefinition rpcDefinition, final Module module) {
+        return IOUtil.qNameToKeyString(rpcDefinition.getQName(), module.getName());
+    }
+
+    public static SchemaContext parseSchema(final Collection<String> yangPath) {
+        final YangParserImpl yangParserImpl = new YangParserImpl();
+        // TODO change deprecated method
+        final Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(loadYangs(yangPath));
+        return yangParserImpl.resolveSchemaContext(modules);
+    }
+
+    private static List<InputStream> loadYangs(final Collection<String> yangPaths) {
+
+        return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
+                new Function<String, InputStream>() {
+                    @Override
+                    public InputStream apply(final String input) {
+                        final InputStream resourceAsStream = NetconfDeviceConnectionHandler.class.getResourceAsStream(input);
+                        Preconditions.checkNotNull(resourceAsStream, "File %s was null", input);
+                        return resourceAsStream;
+                    }
+                }));
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandInvocationException.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/CommandInvocationException.java
new file mode 100644 (file)
index 0000000..e38f45f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.netconf.cli.commands;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class CommandInvocationException extends Exception {
+
+    public CommandInvocationException(final QName qName, final Throwable cause) {
+        this("Command " + qName + " invocation failed: " + cause.getMessage(), cause);
+    }
+
+    protected CommandInvocationException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+
+    public static class CommandTimeoutException extends CommandInvocationException {
+
+        public CommandTimeoutException(final QName qName, final Throwable e) {
+            super("Command " + qName + " timed out: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/input/Input.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/input/Input.java
new file mode 100644 (file)
index 0000000..02173ac
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.netconf.cli.commands.input;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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;
+
+/**
+ * Input arguments for and rpc/command execution
+ */
+public class Input {
+
+    private final List<Node<?>> args;
+
+    private final Map<String, Node<?>> nameToArg = new HashMap<String, Node<?>>();
+
+    public Input(final List<Node<?>> args) {
+        // FIXME empty Input should be constructed from static factory method
+        if(args.isEmpty()) {
+            this.args = Collections.emptyList();
+            return;
+        }
+
+        final Node<?> input = args.iterator().next();
+        Preconditions
+                .checkArgument(input instanceof CompositeNode, "Input container has to be of type composite node.");
+        this.args = ((CompositeNode) input).getValue();
+
+        for (final Node<?> arg : this.args) {
+            nameToArg.put(arg.getNodeType().getLocalName(), arg);
+        }
+    }
+
+    public Node<?> getArg(final String name) {
+        return nameToArg.get(name);
+    }
+
+    public CompositeNode wrap(final QName rpcQName) {
+        return new CompositeNodeTOImpl(rpcQName, null, args);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/input/InputDefinition.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/input/InputDefinition.java
new file mode 100644 (file)
index 0000000..83e1b19
--- /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.netconf.cli.commands.input;
+
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+
+/**
+ * The definition of input arguments represented by schema nodes parsed from
+ * yang rpc definition
+ */
+public class InputDefinition {
+
+    private final ContainerSchemaNode inputContainer;
+
+    public InputDefinition(final ContainerSchemaNode inputContainer) {
+        this.inputContainer = inputContainer;
+    }
+
+    public static InputDefinition fromInput(final ContainerSchemaNode input) {
+        return new InputDefinition(input);
+    }
+
+    public ContainerSchemaNode getInput() {
+        return inputContainer;
+    }
+
+    // FIXME add empty as in output
+    public boolean isEmpty() {
+        return inputContainer == null;
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Close.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Close.java
new file mode 100644 (file)
index 0000000..c43432d
--- /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.netconf.cli.commands.local;
+
+import org.opendaylight.controller.netconf.cli.commands.AbstractCommand;
+import org.opendaylight.controller.netconf.cli.commands.Command;
+import org.opendaylight.controller.netconf.cli.commands.CommandInvocationException;
+import org.opendaylight.controller.netconf.cli.commands.input.Input;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.Output;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+/**
+ * Local command to shut down the cli
+ */
+public class Close extends AbstractCommand {
+
+    public Close(final QName qName, final InputDefinition args, final OutputDefinition output, final String description) {
+        super(qName, args, output, description);
+    }
+
+    @Override
+    public Output invoke(final Input inputArgs) throws CommandInvocationException {
+        // FIXME clean up, close session and then close
+        System.exit(0);
+        return null;
+    }
+
+    public static Command create(final RpcDefinition rpcDefinition) {
+        return new Close(rpcDefinition.getQName(), getInputDefinition(rpcDefinition),
+                getOutputDefinition(rpcDefinition), rpcDefinition.getDescription());
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Connect.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Connect.java
new file mode 100644 (file)
index 0000000..f702aa3
--- /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.netconf.cli.commands.local;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Set;
+import org.opendaylight.controller.netconf.cli.NetconfDeviceConnectionManager;
+import org.opendaylight.controller.netconf.cli.commands.AbstractCommand;
+import org.opendaylight.controller.netconf.cli.commands.Command;
+import org.opendaylight.controller.netconf.cli.commands.input.Input;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.Output;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.yangtools.yang.common.QName;
+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.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+/**
+ * Local command to connect to a remote device
+ */
+public class Connect extends AbstractCommand {
+
+    private final NetconfDeviceConnectionManager connectManager;
+    private final Integer connectionTimeout;
+
+    private Connect(final QName qName, final InputDefinition args, final OutputDefinition output,
+                    final NetconfDeviceConnectionManager connectManager, final String description, final Integer connectionTimeout) {
+        super(qName, args, output, description);
+        this.connectManager = connectManager;
+        this.connectionTimeout = connectionTimeout;
+    }
+
+    @Override
+    public Output invoke(final Input inputArgs) {
+        final NetconfClientConfigurationBuilder config = getConfig(inputArgs);
+        return invoke(config, getArgument(inputArgs, "address-name", String.class));
+    }
+
+    private Output invoke(final NetconfClientConfigurationBuilder config, final String addressName) {
+        final Set<String> remoteCmds = connectManager.connectBlocking(addressName, config);
+
+        final ArrayList<Node<?>> output = Lists.newArrayList();
+        output.add(new SimpleNodeTOImpl<>(QName.create(getCommandId(), "status"), null, "Connection initiated"));
+
+        for (final String cmdId : remoteCmds) {
+            output.add(new SimpleNodeTOImpl<>(QName.create(getCommandId(), "remote-commands"), null, cmdId));
+        }
+
+        return new Output(new CompositeNodeTOImpl(getCommandId(), null, output));
+    }
+
+    private NetconfClientConfigurationBuilder getConfig(final Input inputArgs) {
+
+        final ReconnectStrategy strategy = getReconnectStrategy();
+
+        final String address = getArgument(inputArgs, "address-name", String.class);
+        final Integer port = getArgument(inputArgs, "address-port", Integer.class);
+        final String username = getArgument(inputArgs, "user-name", String.class);
+        final String passwd = getArgument(inputArgs, "user-password", String.class);
+
+        final InetSocketAddress inetAddress;
+        try {
+            inetAddress = new InetSocketAddress(InetAddress.getByName(address), port);
+        } catch (final UnknownHostException e) {
+            throw new IllegalArgumentException("Unable to use address: " + address, e);
+        }
+
+        return NetconfClientConfigurationBuilder.create().withAddress(inetAddress)
+                .withConnectionTimeoutMillis(connectionTimeout)
+                .withReconnectStrategy(strategy)
+                .withAuthHandler(new LoginPassword(username, passwd))
+                .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH);
+    }
+
+    private <T> Optional<T> getArgumentOpt(final Input inputArgs, final String argName, final Class<T> type) {
+        final QName argQName = QName.create(getCommandId(), argName);
+        final Node<?> argumentNode = inputArgs.getArg(argName);
+        if (argumentNode == null) {
+            return Optional.absent();
+        }
+        Preconditions.checkArgument(argumentNode instanceof SimpleNode, "Only simple type argument supported, %s",
+                argQName);
+
+        final Object value = argumentNode.getValue();
+        Preconditions.checkArgument(type.isInstance(value), "Unexpected instance type: %s for argument: %s",
+                value.getClass(), argQName);
+        return Optional.of(type.cast(value));
+    }
+
+    private <T> T getArgument(final Input inputArgs, final String argName, final Class<T> type) {
+        final Optional<T> argumentOpt = getArgumentOpt(inputArgs, argName, type);
+        Preconditions.checkState(argumentOpt.isPresent(), "Argument: %s is missing but is required", argName);
+        return argumentOpt.get();
+    }
+
+    public static ReconnectStrategy getReconnectStrategy() {
+        // FIXME move to args either start-up args or input nodes for connect or both
+        return new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 1000);
+    }
+
+    public static Command create(final RpcDefinition rpcDefinition, final NetconfDeviceConnectionManager connectManager, final Integer connectionTimeout) {
+        return new Connect(rpcDefinition.getQName(), getInputDefinition(rpcDefinition),
+                getOutputDefinition(rpcDefinition), connectManager, rpcDefinition.getDescription(), connectionTimeout);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Disconnect.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Disconnect.java
new file mode 100644 (file)
index 0000000..723e484
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.netconf.cli.commands.local;
+
+import com.google.common.collect.Lists;
+import org.opendaylight.controller.netconf.cli.NetconfDeviceConnectionManager;
+import org.opendaylight.controller.netconf.cli.commands.AbstractCommand;
+import org.opendaylight.controller.netconf.cli.commands.Command;
+import org.opendaylight.controller.netconf.cli.commands.input.Input;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.Output;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+/**
+ * Local disconnect command
+ */
+public class Disconnect extends AbstractCommand {
+
+    private final NetconfDeviceConnectionManager connectionManager;
+
+    public Disconnect(final QName qName, final InputDefinition inputDefinition,
+            final OutputDefinition outputDefinition, final NetconfDeviceConnectionManager connectionManager,
+            final String description) {
+        super(qName, inputDefinition, outputDefinition, description);
+        this.connectionManager = connectionManager;
+    }
+
+    @Override
+    public Output invoke(final Input inputArgs) {
+        connectionManager.disconnect();
+
+        return new Output(new CompositeNodeTOImpl(getCommandId(), null,
+                Lists.<Node<?>> newArrayList(new SimpleNodeTOImpl<>(new QName(getCommandId(), "status"), null,
+                        "Connection disconnected"))));
+    }
+
+    public static Command create(final RpcDefinition rpcDefinition,
+            final NetconfDeviceConnectionManager commandDispatcher) {
+        return new Disconnect(rpcDefinition.getQName(), getInputDefinition(rpcDefinition),
+                getOutputDefinition(rpcDefinition), commandDispatcher, rpcDefinition.getDescription());
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Help.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/local/Help.java
new file mode 100644 (file)
index 0000000..1816469
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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.netconf.cli.commands.local;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.commands.AbstractCommand;
+import org.opendaylight.controller.netconf.cli.commands.Command;
+import org.opendaylight.controller.netconf.cli.commands.CommandDispatcher;
+import org.opendaylight.controller.netconf.cli.commands.input.Input;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.Output;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+/**
+ * Local Help command. Displays all commands with description.
+ */
+public class Help extends AbstractCommand {
+
+    private final CommandDispatcher commandDispatcher;
+
+    public Help(final QName qName, final InputDefinition argsDefinition, final OutputDefinition output, final String description, final CommandDispatcher commandDispatcher) {
+        super(qName, argsDefinition, output, description);
+        this.commandDispatcher = commandDispatcher;
+    }
+
+    @Override
+    public Output invoke(final Input inputArgs) {
+        final ArrayList<Node<?>> value = Lists.newArrayList();
+
+        for (final String id : commandDispatcher.getCommandIds()) {
+            final Optional<Command> cmd = commandDispatcher.getCommand(id);
+            Preconditions.checkState(cmd.isPresent(), "Command %s has to be present in command dispatcher", id);
+            final Optional<String> description = cmd.get().getCommandDescription();
+            final List<Node<?>> nameAndDescription = Lists.newArrayList();
+            nameAndDescription.add(NodeFactory.createImmutableSimpleNode(QName.create(getCommandId(), "id"), null, id));
+            if(description.isPresent()) {
+                nameAndDescription.add(NodeFactory.createImmutableSimpleNode(QName.create(getCommandId(), "description"), null, description.get()));
+            }
+            value.add(ImmutableCompositeNode.create(QName.create(getCommandId(), "commands"), nameAndDescription));
+        }
+
+        return new Output(new CompositeNodeTOImpl(getCommandId(), null, value));
+    }
+
+    public static Command create(final RpcDefinition rpcDefinition, final CommandDispatcher commandDispatcher) {
+        return new Help(rpcDefinition.getQName(), getInputDefinition(rpcDefinition), getOutputDefinition(rpcDefinition), rpcDefinition.getDescription(), commandDispatcher);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/output/Output.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/output/Output.java
new file mode 100644 (file)
index 0000000..c366c89
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.netconf.cli.commands.output;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.util.List;
+import java.util.Map;
+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.model.api.DataSchemaNode;
+
+/**
+ * Output values for and rpc/command execution
+ */
+public class Output {
+
+    private final CompositeNode output;
+
+    public Output(final CompositeNode output) {
+        this.output = output;
+    }
+
+    public Map<DataSchemaNode, List<Node<?>>> unwrap(final OutputDefinition outputDefinition) {
+        Preconditions.checkArgument(outputDefinition.isEmpty() == false);
+
+        final Map<QName, DataSchemaNode> mappedSchemaNodes = mapOutput(outputDefinition);
+        final Map<DataSchemaNode, List<Node<?>>> mappedNodesToSchema = Maps.newHashMap();
+
+        for (final Node<?> node : output.getValue()) {
+            final DataSchemaNode schemaNode = mappedSchemaNodes.get(node.getKey().withoutRevision());
+            final List<Node<?>> list = mappedNodesToSchema.get(schemaNode) == null ? Lists.<Node<?>> newArrayList()
+                    : mappedNodesToSchema.get(schemaNode);
+            list.add(node);
+            mappedNodesToSchema.put(schemaNode, list);
+        }
+
+        return mappedNodesToSchema;
+    }
+
+    public CompositeNode getOutput() {
+        return output;
+    }
+
+    private Map<QName, DataSchemaNode> mapOutput(final OutputDefinition outputDefinition) {
+        final Map<QName, DataSchemaNode> mapped = Maps.newHashMap();
+        for (final DataSchemaNode dataSchemaNode : outputDefinition) {
+            // without revision since data QNames come without revision
+            mapped.put(dataSchemaNode.getQName().withoutRevision(), dataSchemaNode);
+        }
+
+        return mapped;
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/output/OutputDefinition.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/output/OutputDefinition.java
new file mode 100644 (file)
index 0000000..66d0d4d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.netconf.cli.commands.output;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * The definition of output elements represented by schema nodes parsed from yang rpc definition
+ */
+public class OutputDefinition implements Iterable<DataSchemaNode> {
+
+    public static final OutputDefinition EMPTY_OUTPUT = new OutputDefinition(Collections.<DataSchemaNode>emptySet());
+    private final Set<DataSchemaNode> childNodes;
+
+    public OutputDefinition(final Set<DataSchemaNode> childNodes) {
+        this.childNodes = childNodes;
+    }
+
+    @Override
+    public Iterator<DataSchemaNode> iterator() {
+        return childNodes.iterator();
+    }
+
+    public static OutputDefinition fromOutput(final ContainerSchemaNode output) {
+        Preconditions.checkNotNull(output);
+        return new OutputDefinition(output.getChildNodes());
+    }
+
+    public static OutputDefinition empty() {
+        return EMPTY_OUTPUT;
+    }
+
+    public boolean isEmpty() {
+        return this == EMPTY_OUTPUT;
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/remote/RemoteCommand.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/commands/remote/RemoteCommand.java
new file mode 100644 (file)
index 0000000..05b9e85
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.netconf.cli.commands.remote;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.opendaylight.controller.netconf.cli.commands.AbstractCommand;
+import org.opendaylight.controller.netconf.cli.commands.Command;
+import org.opendaylight.controller.netconf.cli.commands.CommandInvocationException;
+import org.opendaylight.controller.netconf.cli.commands.input.Input;
+import org.opendaylight.controller.netconf.cli.commands.input.InputDefinition;
+import org.opendaylight.controller.netconf.cli.commands.output.Output;
+import org.opendaylight.controller.netconf.cli.commands.output.OutputDefinition;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+/**
+ * Generic remote command implementation that sends the rpc xml to the remote device and waits for response
+ * Waiting is limited with TIMEOUT
+ */
+public class RemoteCommand extends AbstractCommand {
+
+    // TODO make this configurable
+    private static final long DEFAULT_TIMEOUT = 10000;
+    private static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
+    private final RpcImplementation rpc;
+
+    public RemoteCommand(final QName qName, final InputDefinition args, final OutputDefinition output, final String description, final RpcImplementation rpc) {
+        super(qName, args, output, description);
+        this.rpc = rpc;
+    }
+
+    @Override
+    public Output invoke(final Input inputArgs) throws CommandInvocationException {
+        final ListenableFuture<RpcResult<CompositeNode>> invokeRpc = rpc.invokeRpc(getCommandId(), inputArgs.wrap(getCommandId()));
+        try {
+            return new Output(invokeRpc.get(DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNIT).getResult());
+        } catch (final ExecutionException e) {
+            throw new CommandInvocationException(getCommandId(), e);
+        } catch (final TimeoutException e) {
+            // Request timed out, cancel request
+            invokeRpc.cancel(true);
+            throw new CommandInvocationException.CommandTimeoutException(getCommandId(), e);
+        } catch (final InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Command fromRpc(final RpcDefinition rpcDefinition, final RpcImplementation rpcInvoker) {
+        final InputDefinition args = getInputDefinition(rpcDefinition);
+        final OutputDefinition retVal = getOutputDefinition(rpcDefinition);
+
+        return new RemoteCommand(rpcDefinition.getQName(), args, retVal, rpcDefinition.getDescription(), rpcInvoker);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/BaseConsoleContext.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/BaseConsoleContext.java
new file mode 100644 (file)
index 0000000..26e46d3
--- /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.netconf.cli.io;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import jline.console.completer.AggregateCompleter;
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public class BaseConsoleContext<T extends DataSchemaNode> implements ConsoleContext {
+
+    private static final Completer SKIP_COMPLETER = new StringsCompleter(IOUtil.SKIP);
+
+    private final T dataSchemaNode;
+
+    public BaseConsoleContext(final T dataSchemaNode) {
+        Preconditions.checkNotNull(dataSchemaNode);
+        this.dataSchemaNode = dataSchemaNode;
+    }
+
+    @Override
+    public Completer getCompleter() {
+        final ArrayList<Completer> completers = Lists.newArrayList(SKIP_COMPLETER);
+        completers.addAll(getAdditionalCompleters());
+        return new AggregateCompleter(completers);
+    }
+
+    protected List<Completer> getAdditionalCompleters() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Optional<String> getPrompt() {
+        return Optional.of(dataSchemaNode.getQName().getLocalName());
+    }
+
+    protected T getDataSchemaNode() {
+        return dataSchemaNode;
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleContext.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleContext.java
new file mode 100644 (file)
index 0000000..f4ebfca
--- /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.netconf.cli.io;
+
+import com.google.common.base.Optional;
+import jline.console.completer.Completer;
+
+/**
+ * Context to be set in the IO. Different prompts + completers are required in different contexts of the CLI.
+ */
+public interface ConsoleContext {
+
+    Completer getCompleter();
+
+    Optional<String> getPrompt();
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleIO.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleIO.java
new file mode 100644 (file)
index 0000000..6bffeac
--- /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.netconf.cli.io;
+
+import java.io.IOException;
+
+/**
+ * Definition of IO interface
+ */
+public interface ConsoleIO {
+
+    String read() throws IOException;
+
+    String read(Character mask) throws IOException;
+
+    void write(CharSequence data) throws IOException;
+
+    void writeLn(CharSequence data) throws IOException;
+
+    void formatLn(String format, Object... args) throws IOException;
+
+    void enterContext(ConsoleContext consoleContext);
+
+    void enterRootContext(ConsoleContext consoleContext);
+
+    void leaveContext();
+
+    void leaveRootContext();
+
+    void complete();
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleIOImpl.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/ConsoleIOImpl.java
new file mode 100644 (file)
index 0000000..5b7374a
--- /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.netconf.cli.io;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.PATH_SEPARATOR;
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.PROMPT_SUFIX;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.Iterator;
+import jline.console.ConsoleReader;
+import jline.console.completer.Completer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Jline based IO implementation
+ */
+public class ConsoleIOImpl implements ConsoleIO {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ConsoleIOImpl.class);
+
+    private final ConsoleReader console;
+    private final Deque<ConsoleContext> contexts = new ArrayDeque<>();
+
+    public ConsoleIOImpl() throws IOException {
+        console = new ConsoleReader();
+        console.setHandleUserInterrupt(true);
+        console.setPaginationEnabled(true);
+        console.setHistoryEnabled(true);
+
+        // TODO trifferedActions not supported by jline in current version
+        // https://github.com/jline/jline2/issues/149
+        console.addTriggeredAction('?', new QuestionMarkActionListener());
+    }
+
+    @Override
+    public String read() throws IOException {
+        return console.readLine().trim();
+    }
+
+    @Override
+    public String read(final Character mask) throws IOException {
+        return console.readLine(mask).trim();
+    }
+
+    @Override
+    public void write(final CharSequence data) throws IOException {
+        console.print(data);
+        console.flush();
+    }
+
+    @Override
+    public void writeLn(final CharSequence data) throws IOException {
+        console.println(data);
+        console.flush();
+    }
+
+    @Override
+    public void formatLn(final String format, final Object... args) throws IOException {
+        console.println(String.format(format, args));
+        console.flush();
+    }
+
+    @Override
+    public void enterContext(final ConsoleContext consoleContext) {
+        contexts.push(consoleContext);
+        enterCtx(consoleContext);
+    }
+
+
+    @Override
+    public void enterRootContext(final ConsoleContext consoleContext) {
+        contexts.addLast(consoleContext);
+        enterCtx(consoleContext);
+    }
+
+    private void enterCtx(final ConsoleContext consoleContext) {
+        setCompleter(consoleContext.getCompleter());
+        console.setPrompt(buildPrompt());
+    }
+
+    @Override
+    public void leaveContext() {
+        contexts.pollFirst();
+        leaveCtx();
+    }
+
+    @Override
+    public void leaveRootContext() {
+        contexts.pollLast();
+        leaveCtx();
+    }
+
+    private void leaveCtx() {
+        console.setPrompt(buildPrompt());
+        if (contexts.peek() != null) {
+            setCompleter(contexts.peek().getCompleter());
+        }
+    }
+
+    protected String buildPrompt() {
+        final StringBuilder newPrompt = new StringBuilder();
+
+        final Iterator<ConsoleContext> descendingIterator = contexts.descendingIterator();
+        while (descendingIterator.hasNext()) {
+            final ConsoleContext consoleContext = descendingIterator.next();
+            final Optional<String> promptPart = consoleContext.getPrompt();
+            if (promptPart.isPresent()) {
+                newPrompt.append(PATH_SEPARATOR);
+                newPrompt.append(promptPart.get());
+            }
+        }
+        if (newPrompt.length() ==0) {
+            newPrompt.append(PATH_SEPARATOR);
+        }
+
+        newPrompt.append(PROMPT_SUFIX);
+
+        return newPrompt.toString();
+    }
+
+    private void setCompleter(final Completer newCompleter) {
+        for (final Completer concreteCompleter : console.getCompleters()) {
+            console.removeCompleter(concreteCompleter);
+        }
+        console.addCompleter(newCompleter);
+    }
+
+    private class QuestionMarkActionListener implements ActionListener {
+        @Override
+        public void actionPerformed(final ActionEvent e) {
+            ConsoleIOImpl.this.complete();
+        }
+    }
+
+    public void complete() {
+        final ArrayList<CharSequence> candidates = Lists.newArrayList();
+        contexts.peek().getCompleter().complete("", 0, candidates);
+        try {
+            console.getCompletionHandler().complete(console, candidates, 0);
+        } catch (final IOException ex) {
+            throw new IllegalStateException("Unable to write to output", ex);
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/IOUtil.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/io/IOUtil.java
new file mode 100644 (file)
index 0000000..1817cdd
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.netconf.cli.io;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+public class IOUtil {
+
+    public static final String SKIP = "skip";
+    public static final String PROMPT_SUFIX = ">";
+    public static final String PATH_SEPARATOR = "/";
+
+    private IOUtil() {
+    }
+
+    public static boolean isQName(final String qName) {
+        final Matcher matcher = patternNew.matcher(qName);
+        return matcher.matches();
+    }
+
+    public static Date parseDate(final String revision) {
+        final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            return formatter.parse(revision);
+        } catch (final ParseException e) {
+            throw new IllegalArgumentException("Date not valid", e);
+        }
+    }
+
+    public static String listType(final SchemaNode schemaNode) {
+        if (schemaNode instanceof LeafListSchemaNode) {
+            return "Leaf-list";
+        } else if (schemaNode instanceof ListSchemaNode) {
+            return "List";
+        } else if (schemaNode instanceof LeafSchemaNode) {
+            return "Leaf";
+        }
+        // FIXME throw exception on unexpected state, not null/emptyString
+        return "";
+    }
+
+    public static String qNameToKeyString(final QName qName, final String moduleName) {
+        return String.format("%s(%s)", qName.getLocalName(), moduleName);
+    }
+
+    // TODO test and check regex + review format of string for QName
+    final static Pattern patternNew = Pattern.compile("([^\\)]+)\\(([^\\)]+)\\)");
+
+    public static QName qNameFromKeyString(final String qName, final Map<String, QName> mappedModules)
+            throws ReadingException {
+        final Matcher matcher = patternNew.matcher(qName);
+        if (!matcher.matches()) {
+            final String message = String.format("QName in wrong format: %s should be: %s", qName, patternNew);
+            throw new ReadingException(message);
+        }
+        final QName base = mappedModules.get(matcher.group(2));
+        if (base == null) {
+            final String message = String.format("Module %s cannot be found", matcher.group(2));
+            throw new ReadingException(message);
+        }
+        return QName.create(base, matcher.group(1));
+    }
+
+    public static boolean isSkipInput(final String rawValue) {
+        return rawValue.equals(SKIP);
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/AbstractReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/AbstractReader.java
new file mode 100644 (file)
index 0000000..6131eef
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.netconf.cli.reader;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import jline.console.completer.Completer;
+import jline.console.completer.NullCompleter;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+
+public abstract class AbstractReader<T extends DataSchemaNode> implements Reader<T> {
+
+    public static final NullContext NULL_CONTEXT = new NullContext();
+
+    // TODO make console private add protected getter
+    protected ConsoleIO console;
+    private final SchemaContext context;
+    private boolean readConfigNode = false;
+
+    public AbstractReader(final ConsoleIO console, final SchemaContext context) {
+        this.console = console;
+        this.context = context;
+    }
+
+    public AbstractReader(final ConsoleIO console, final SchemaContext context, final boolean readConfigNode) {
+        this(console, context);
+        this.readConfigNode = readConfigNode;
+    }
+
+    protected SchemaContext getSchemaContext() {
+        return context;
+    }
+
+    protected ConsoleIO getConsole() {
+        return console;
+    }
+
+    protected boolean getReadConfigNode() {
+        return readConfigNode;
+    }
+
+    @Override
+    public List<Node<?>> read(final T schemaNode) throws ReadingException {
+        if (isReadingWanted(schemaNode)) {
+            final ConsoleContext ctx = getContext(schemaNode);
+            console.enterContext(ctx);
+            try {
+                return readWithContext(schemaNode);
+            } catch (final IOException e) {
+                throw new ReadingException("Unable to read data from input for " + schemaNode.getQName(), e);
+            } finally {
+                console.leaveContext();
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    private boolean isReadingWanted(final DataSchemaNode node) {
+        if (readConfigNode && !node.isConfiguration()) {
+            return false;
+        }
+        return true;
+    }
+
+    // TODO javadoc
+
+    protected abstract List<Node<?>> readWithContext(T schemaNode) throws IOException, ReadingException;
+
+    protected abstract ConsoleContext getContext(T schemaNode);
+
+    protected Optional<String> getDefaultValue(final T schemaNode) {
+        String defaultValue = null;
+        if (schemaNode instanceof LeafSchemaNode) {
+            defaultValue = ((LeafSchemaNode) schemaNode).getDefault();
+        } else if (schemaNode instanceof ChoiceNode) {
+            defaultValue = ((ChoiceNode) schemaNode).getDefaultCase();
+        }
+
+        return Optional.fromNullable(defaultValue);
+    }
+
+    protected boolean isEmptyInput(final String rawValue) {
+        return Strings.isNullOrEmpty(rawValue);
+    }
+
+    protected static boolean isEmptyType(final TypeDefinition<?> type) {
+        return type instanceof EmptyTypeDefinition;
+    }
+
+    private static class NullContext implements ConsoleContext {
+        @Override
+        public Completer getCompleter() {
+            return new NullCompleter();
+        }
+
+        @Override
+        public Optional<String> getPrompt() {
+            return Optional.absent();
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/GenericListEntryReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/GenericListEntryReader.java
new file mode 100644 (file)
index 0000000..a30b182
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.netconf.cli.reader;
+
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * marker interface to mark reader which can be used with GenericListReader
+ */
+public interface GenericListEntryReader<T extends DataSchemaNode> extends Reader<T> {
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/Reader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/Reader.java
new file mode 100644 (file)
index 0000000..9f27b8f
--- /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.netconf.cli.reader;
+
+import java.util.List;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Generic provider(reader) of input arguments for commands
+ */
+public interface Reader<T extends DataSchemaNode> {
+
+    List<Node<?>> read(T schemaNode) throws ReadingException;
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/ReadingException.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/ReadingException.java
new file mode 100644 (file)
index 0000000..81915fc
--- /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.netconf.cli.reader;
+
+public class ReadingException extends Exception {
+
+    private static final long serialVersionUID = -298382323286156591L;
+
+    public ReadingException(final String msg, final Exception e) {
+        super(msg, e);
+    }
+
+    public ReadingException(final String msg) {
+        super(msg);
+    }
+
+    public static class IncorrectValueException extends ReadingException {
+
+        private static final long serialVersionUID = 164168437058431592L;
+
+        public IncorrectValueException(final String msg) {
+            super(msg);
+        }
+
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/ConfigReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/ConfigReader.java
new file mode 100644 (file)
index 0000000..95fc098
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * 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.netconf.cli.reader.custom;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.isSkipInput;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+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.net.URI;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import jline.console.completer.Completer;
+import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.io.IOUtil;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Custom reader implementation for filter elements in get/get-config rpcs. This
+ * reader overrides the default anyxml reader and reads filter as a schema path.
+ */
+public class ConfigReader extends AbstractReader<DataSchemaNode> {
+
+    public static final String SEPARATOR = "/";
+
+    private final CommandArgHandlerRegistry commandArgHandlerRegistry;
+    private final Map<String, QName> mappedModules;
+    private final Map<URI, QName> mappedModulesNamespace;
+
+    public ConfigReader(final ConsoleIO console, final SchemaContext remoteSchemaContext,
+            final CommandArgHandlerRegistry commandArgHandlerRegistry) {
+        super(console, remoteSchemaContext);
+        this.commandArgHandlerRegistry = commandArgHandlerRegistry;
+
+        mappedModules = Maps.newHashMap();
+        mappedModulesNamespace = Maps.newHashMap();
+        for (final Module module : remoteSchemaContext.getModules()) {
+            final QName moduleQName = QName.create(module.getNamespace(), module.getRevision(), module.getName());
+            mappedModules.put(moduleQName.getLocalName(), moduleQName);
+            mappedModulesNamespace.put(moduleQName.getNamespace(), moduleQName);
+        }
+    }
+
+    // FIXME refactor + unite common code with FilterReader
+
+    @Override
+    protected List<Node<?>> readWithContext(final DataSchemaNode schemaNode) throws IOException, ReadingException {
+        console.writeLn("Config " + schemaNode.getQName().getLocalName());
+        console.writeLn("Submit path of the data to edit. Use TAB for autocomplete");
+
+        final String rawValue = console.read();
+
+        // FIXME isSkip check should be somewhere in abstractReader
+        if (isSkipInput(rawValue) || Strings.isNullOrEmpty(rawValue)) {
+            return Collections.emptyList();
+        }
+
+        final List<QName> filterPartsQNames = Lists.newArrayList();
+
+        for (final String part : rawValue.split(SEPARATOR)) {
+            final QName qName = IOUtil.qNameFromKeyString(part, mappedModules);
+            filterPartsQNames.add(qName);
+        }
+
+        List<Node<?>> previous = readInnerNode(rawValue);
+
+        for (final QName qName : Lists.reverse(filterPartsQNames).subList(1, filterPartsQNames.size())) {
+            previous = Collections.<Node<?>> singletonList(new CompositeNodeTOImpl(qName, null,
+                    previous == null ? Collections.<Node<?>> emptyList() : previous));
+        }
+
+        final Node<?> newNode = previous == null ? null
+                : new CompositeNodeTOImpl(schemaNode.getQName(), null, previous);
+
+        return Collections.<Node<?>> singletonList(newNode);
+    }
+
+    private List<Node<?>> readInnerNode(final String pathString) throws ReadingException {
+        final Optional<DataSchemaNode> schema = getCurrentNode(getSchemaContext(), pathString);
+        Preconditions.checkState(schema.isPresent(), "Unable to find schema for %s", pathString);
+        return commandArgHandlerRegistry.getGenericReader(getSchemaContext(), true).read(schema.get());
+    }
+
+    @Override
+    protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
+        return new FilterConsoleContext(schemaNode, getSchemaContext());
+    }
+
+    private final class FilterConsoleContext extends BaseConsoleContext<DataSchemaNode> {
+
+        private final SchemaContext remoteSchemaContext;
+
+        public FilterConsoleContext(final DataSchemaNode schemaNode, final SchemaContext remoteSchemaContext) {
+            super(schemaNode);
+            this.remoteSchemaContext = remoteSchemaContext;
+        }
+
+        @Override
+        protected List<Completer> getAdditionalCompleters() {
+            return Collections.<Completer> singletonList(new FilterCompleter(remoteSchemaContext));
+        }
+    }
+
+    private final class FilterCompleter implements Completer {
+
+        private final SchemaContext remoteSchemaContext;
+
+        public FilterCompleter(final SchemaContext remoteSchemaContext) {
+            this.remoteSchemaContext = remoteSchemaContext;
+        }
+
+        @Override
+        public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+            final int idx = buffer.lastIndexOf(SEPARATOR);
+
+            final Optional<DataSchemaNode> currentNode = getCurrentNode(remoteSchemaContext, buffer);
+            if (currentNode.isPresent() && currentNode.get() instanceof DataNodeContainer) {
+                final Collection<DataSchemaNode> childNodes = ((DataNodeContainer) currentNode.get()).getChildNodes();
+                final Collection<String> transformed = Collections2.transform(childNodes,
+                        new Function<DataSchemaNode, String>() {
+                            @Override
+                            public String apply(final DataSchemaNode input) {
+                                return IOUtil.qNameToKeyString(input.getQName(),
+                                        mappedModulesNamespace.get(input.getQName().getNamespace()).getLocalName());
+                            }
+                        });
+
+                fillCandidates(buffer.substring(idx + 1), candidates, transformed);
+            }
+
+            return idx == -1 ? 0 : idx + 1;
+        }
+
+        private void fillCandidates(final String buffer, final List<CharSequence> candidates,
+                final Collection<String> transformed) {
+            final SortedSet<String> strings = new TreeSet<>(transformed);
+
+            if (buffer == null) {
+                candidates.addAll(strings);
+            } else {
+                for (final String match : strings.tailSet(buffer)) {
+                    if (!match.startsWith(buffer)) {
+                        break;
+                    }
+                    candidates.add(match);
+                }
+            }
+
+            if (candidates.size() == 1) {
+                candidates.set(0, candidates.get(0) + SEPARATOR);
+            }
+        }
+
+    }
+
+    private Optional<DataSchemaNode> getCurrentNode(DataSchemaNode parent, final String buffer) {
+        for (final String part : buffer.split(SEPARATOR)) {
+            if (IOUtil.isQName(part) == false) {
+                return Optional.of(parent);
+            }
+
+            final QName qName;
+            try {
+                qName = IOUtil.qNameFromKeyString(part, mappedModules);
+            } catch (final ReadingException e) {
+                return Optional.of(parent);
+            }
+            if (parent instanceof DataNodeContainer) {
+                parent = ((DataNodeContainer) parent).getDataChildByName(qName);
+            } else {
+                // This should check if we are at the end of buffer ?
+                return Optional.of(parent);
+            }
+        }
+        return Optional.of(parent);
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/EditContentReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/EditContentReader.java
new file mode 100644 (file)
index 0000000..af43d37
--- /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.netconf.cli.reader.custom;
+
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
+import org.opendaylight.controller.netconf.cli.commands.CommandConstants;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.controller.netconf.cli.reader.impl.ChoiceReader;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class EditContentReader extends ChoiceReader {
+
+    public static final QName EDIT_CONTENT_QNAME = QName.create(CommandConstants.NETCONF_BASE_QNAME, "edit-content");
+    public static final QName CONFIG_QNAME = QName.create(EDIT_CONTENT_QNAME, "config");
+
+    // FIXME this could be removed if feature/if-feature are supported
+
+    public EditContentReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry, final SchemaContext schemaContext) {
+        super(console, argumentHandlerRegistry, schemaContext);
+    }
+
+    @Override
+    public List<Node<?>> readWithContext(final ChoiceNode choiceNode) throws IOException, ReadingException {
+        Preconditions.checkState(choiceNode.getQName().equals(EDIT_CONTENT_QNAME), "Unexpected choice %s, expected %s", choiceNode, EDIT_CONTENT_QNAME);
+        final ChoiceCaseNode selectedCase = choiceNode.getCaseNodeByName(CONFIG_QNAME);
+        Preconditions.checkNotNull(selectedCase, "Unexpected choice %s, expected %s that contains %s", choiceNode, EDIT_CONTENT_QNAME, CONFIG_QNAME);
+        return readSelectedCase(selectedCase);
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/FilterReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/FilterReader.java
new file mode 100644 (file)
index 0000000..7b37f69
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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.netconf.cli.reader.custom;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.isSkipInput;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+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.net.URI;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import jline.console.completer.Completer;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.io.IOUtil;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Custom reader implementation for filter elements in get/get-config rpcs. This
+ * reader overrides the default anyxml reader and reads filter as a schema path.
+ */
+public class FilterReader extends AbstractReader<DataSchemaNode> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FilterReader.class);
+
+    public static final String SEPARATOR = "/";
+
+    private final Map<String, QName> mappedModules;
+    private final Map<URI, QName> mappedModulesNamespace;
+
+    public FilterReader(final ConsoleIO console, final SchemaContext remoteSchemaContext) {
+        super(console, remoteSchemaContext);
+
+        mappedModules = Maps.newHashMap();
+        mappedModulesNamespace = Maps.newHashMap();
+        for (final Module module : remoteSchemaContext.getModules()) {
+            final QName moduleQName = QName.create(module.getNamespace(), module.getRevision(), module.getName());
+            mappedModules.put(moduleQName.getLocalName(), moduleQName);
+            mappedModulesNamespace.put(moduleQName.getNamespace(), moduleQName);
+        }
+    }
+
+    // FIXME refactor
+
+    public static final QName FILTER_TYPE_QNAME = QName.create("urn:ietf:params:xml:ns:netconf:base:1.0", "2011-06-01",
+            "type");
+    public static final String FILTER_TYPE_VALUE_DEFAULT = "subtree";
+
+    @Override
+    protected List<Node<?>> readWithContext(final DataSchemaNode schemaNode) throws IOException, ReadingException {
+        boolean redSuccessfuly = false;
+        Node<?> newNode = null;
+        do {
+            console.writeLn("Filter " + schemaNode.getQName().getLocalName());
+            console.writeLn("Submit path of the data to retrieve. Use TAB for autocomplete");
+
+            final String rawValue = console.read();
+
+            // FIXME skip should be somewhere in abstractReader
+            if (isSkipInput(rawValue) || Strings.isNullOrEmpty(rawValue)) {
+                return Collections.emptyList();
+            }
+
+            final List<QName> filterPartsQNames = Lists.newArrayList();
+
+            try {
+                for (final String part : rawValue.split(SEPARATOR)) {
+                    final QName qName = IOUtil.qNameFromKeyString(part, mappedModules);
+                    filterPartsQNames.add(qName);
+                }
+
+                Node<?> previous = null;
+
+                for (final QName qName : Lists.reverse(filterPartsQNames)) {
+                    previous = new CompositeNodeTOImpl(qName, null,
+                            previous == null ? Collections.<Node<?>> emptyList()
+                                    : Collections.<Node<?>> singletonList(previous));
+                }
+
+                final Map<QName, String> attributes = Collections.singletonMap(FILTER_TYPE_QNAME,
+                        FILTER_TYPE_VALUE_DEFAULT);
+                newNode = previous == null ? null : ImmutableCompositeNode.create(schemaNode.getQName(), attributes,
+                        Collections.<Node<?>> singletonList(previous));
+                redSuccessfuly = true;
+            } catch (final ReadingException e) {
+                final String message = "Specified filter path isn't correct.";
+                LOG.error(message, e);
+                console.writeLn(message);
+            }
+        } while (!redSuccessfuly);
+        return Collections.<Node<?>> singletonList(newNode);
+    }
+
+    @Override
+    protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
+        return new FilterConsoleContext(schemaNode, getSchemaContext());
+    }
+
+    private final class FilterConsoleContext extends BaseConsoleContext<DataSchemaNode> {
+
+        private final SchemaContext remoteSchemaContext;
+
+        public FilterConsoleContext(final DataSchemaNode schemaNode, final SchemaContext remoteSchemaContext) {
+            super(schemaNode);
+            this.remoteSchemaContext = remoteSchemaContext;
+        }
+
+        @Override
+        protected List<Completer> getAdditionalCompleters() {
+            return Collections.<Completer> singletonList(new FilterCompleter(remoteSchemaContext));
+        }
+
+    }
+
+    private final class FilterCompleter implements Completer {
+
+        private final SchemaContext remoteSchemaContext;
+
+        // TODO add skip to filter completer, better soulution would be to add
+        // SKIP completer before context completer if possible
+
+        public FilterCompleter(final SchemaContext remoteSchemaContext) {
+            this.remoteSchemaContext = remoteSchemaContext;
+        }
+
+        @Override
+        public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+            final int idx = buffer.lastIndexOf(SEPARATOR);
+
+            final Optional<DataNodeContainer> currentNode = getCurrentNode(remoteSchemaContext, buffer);
+            if (currentNode.isPresent()) {
+
+                final Collection<String> transformed = Collections2.transform(currentNode.get().getChildNodes(),
+                        new Function<DataSchemaNode, String>() {
+                            @Override
+                            public String apply(final DataSchemaNode input) {
+                                return IOUtil.qNameToKeyString(input.getQName(),
+                                        mappedModulesNamespace.get(input.getQName().getNamespace()).getLocalName());
+                            }
+                        });
+
+                fillCandidates(buffer.substring(idx + 1), candidates, transformed);
+            }
+
+            return idx == -1 ? 0 : idx + 1;
+        }
+
+        private void fillCandidates(final String buffer, final List<CharSequence> candidates,
+                final Collection<String> transformed) {
+            final SortedSet<String> strings = new TreeSet<>(transformed);
+
+            if (buffer == null) {
+                candidates.addAll(strings);
+            } else {
+                for (final String match : strings.tailSet(buffer)) {
+                    if (!match.startsWith(buffer)) {
+                        break;
+                    }
+                    candidates.add(match);
+                }
+            }
+
+            if (candidates.size() == 1) {
+                candidates.set(0, candidates.get(0) + SEPARATOR);
+            }
+        }
+
+        private Optional<DataNodeContainer> getCurrentNode(DataNodeContainer parent, final String buffer) {
+            for (final String part : buffer.split(SEPARATOR)) {
+                if (!IOUtil.isQName(part)) {
+                    return Optional.of(parent);
+                }
+
+                QName qName;
+                try {
+                    qName = IOUtil.qNameFromKeyString(part, mappedModules);
+                } catch (final ReadingException e) {
+                    return Optional.of(parent);
+                }
+
+                final DataSchemaNode dataChildByName = parent.getDataChildByName(qName);
+                if (dataChildByName instanceof DataNodeContainer) {
+                    parent = (DataNodeContainer) dataChildByName;
+                } else {
+                    return Optional.absent();
+                }
+            }
+            return Optional.of(parent);
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/PasswordReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/custom/PasswordReader.java
new file mode 100644 (file)
index 0000000..4804455
--- /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.netconf.cli.reader.custom;
+
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import jline.console.completer.Completer;
+import jline.console.completer.NullCompleter;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.impl.BasicDataHolderReader;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public class PasswordReader extends BasicDataHolderReader<DataSchemaNode> {
+
+    private static final char PASSWORD_MASK = '*';
+
+    public PasswordReader(final ConsoleIO console, final SchemaContext schemaContext) {
+        super(console, schemaContext);
+    }
+
+    @Override
+    protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
+        return new BaseConsoleContext<DataSchemaNode>(schemaNode) {
+            @Override
+            public Completer getCompleter() {
+                return new NullCompleter();
+            }
+        };
+    }
+
+    @Override
+    protected TypeDefinition<?> getType(final DataSchemaNode schemaNode) {
+        Preconditions.checkArgument(schemaNode instanceof LeafSchemaNode);
+        return ((LeafSchemaNode)schemaNode).getType();
+    }
+
+    @Override
+    protected String readValue() throws IOException {
+        return console.read(PASSWORD_MASK);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/AnyXmlReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/AnyXmlReader.java
new file mode 100644 (file)
index 0000000..2ce2f64
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.isSkipInput;
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.listType;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+public class AnyXmlReader extends AbstractReader<AnyXmlSchemaNode> {
+
+    public AnyXmlReader(final ConsoleIO console, final SchemaContext schemaContext) {
+        super(console, schemaContext);
+    }
+
+    public AnyXmlReader(final ConsoleIO console, final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+    }
+
+    @Override
+    protected List<Node<?>> readWithContext(final AnyXmlSchemaNode schemaNode) throws IOException, ReadingException {
+        console.writeLn(listType(schemaNode) + " " + schemaNode.getQName().getLocalName());
+
+        final String rawValue = console.read();
+
+        Node<?> newNode = null;
+        if (!isSkipInput(rawValue)) {
+            final Optional<Node<?>> value = tryParse(rawValue);
+
+            if (value.isPresent()) {
+                newNode = NodeFactory.createImmutableCompositeNode(schemaNode.getQName(), null,
+                        Collections.<Node<?>> singletonList(value.get()));
+            } else {
+                newNode = NodeFactory.createImmutableSimpleNode(schemaNode.getQName(), null, rawValue);
+            }
+        }
+
+        final List<Node<?>> newNodes = new ArrayList<>();
+        newNodes.add(newNode);
+        return newNodes;
+    }
+
+    private Optional<Node<?>> tryParse(final String rawValue) {
+        try {
+            final Document dom = XmlUtil.readXmlToDocument(rawValue);
+            return Optional.<Node<?>> of(XmlDocumentUtils.toDomNode(dom));
+        } catch (SAXException | IOException e) {
+            // TODO log
+            return Optional.absent();
+        }
+    }
+
+    @Override
+    protected ConsoleContext getContext(final AnyXmlSchemaNode schemaNode) {
+        return new BaseConsoleContext<>(schemaNode);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/BasicDataHolderReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/BasicDataHolderReader.java
new file mode 100644 (file)
index 0000000..ef41e7f
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.isSkipInput;
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.listType;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashBiMap;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.io.IOUtil;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class BasicDataHolderReader<T extends DataSchemaNode> extends AbstractReader<T> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BasicDataHolderReader.class);
+    private DataHolderCompleter currentCompleter;
+
+    public BasicDataHolderReader(final ConsoleIO console, final SchemaContext schemaContext,
+            final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+    }
+
+    public BasicDataHolderReader(final ConsoleIO console, final SchemaContext schemaContext) {
+        super(console, schemaContext);
+    }
+
+    @Override
+    public List<Node<?>> readWithContext(final T schemaNode) throws IOException, ReadingException {
+        TypeDefinition<?> type = getType(schemaNode);
+        console.formatLn("Submit %s %s(%s)", listType(schemaNode), schemaNode.getQName().getLocalName(), type.getQName().getLocalName());
+
+        while (baseTypeFor(type) instanceof UnionTypeDefinition) {
+            final Optional<TypeDefinition<?>> optionalTypeDef = new UnionTypeReader(console).read(type);
+            if (!optionalTypeDef.isPresent()) {
+                return postSkipOperations(schemaNode);
+            }
+            type = optionalTypeDef.get();
+        }
+
+        if (currentCompleter == null) {
+            currentCompleter = getBaseCompleter(schemaNode);
+        }
+
+        // TODO what if type is leafref, instance-identifier?
+
+        // Handle empty type leaf by question
+        if (isEmptyType(type)) {
+            final Optional<Boolean> shouldAddEmpty = new DecisionReader().read(console, "Add empty type leaf %s ?",
+                    schemaNode.getQName().getLocalName());
+            if (shouldAddEmpty.isPresent()) {
+                if (shouldAddEmpty.get()) {
+                    return wrapValue(schemaNode, "");
+                } else {
+                    return Collections.emptyList();
+                }
+            } else {
+                return postSkipOperations(schemaNode);
+            }
+        }
+
+        final String rawValue = readValue();
+        if (isSkipInput(rawValue)) {
+            return postSkipOperations(schemaNode);
+        }
+
+        final Object resolvedValue = currentCompleter.resolveValue(rawValue);
+
+        // Reset state TODO should be in finally
+        currentCompleter = null;
+        return wrapValue(schemaNode, resolvedValue);
+    }
+
+    private List<Node<?>> postSkipOperations(final DataSchemaNode schemaNode) throws IOException {
+        console.formatLn("Skipping %s", schemaNode.getQName());
+        return Collections.emptyList();
+    }
+
+    private TypeDefinition<?> baseTypeFor(final TypeDefinition<?> type) {
+        if (type.getBaseType() != null) {
+            return baseTypeFor(type.getBaseType());
+        }
+        return type;
+    }
+
+    protected String readValue() throws IOException {
+        return console.read();
+    }
+
+    private List<Node<?>> wrapValue(final T schemaNode, final Object value) {
+        final Node<?> newNode = NodeFactory.createImmutableSimpleNode(schemaNode.getQName(), null, value);
+        return Collections.<Node<?>> singletonList(newNode);
+    }
+
+    protected abstract TypeDefinition<?> getType(final T schemaNode);
+
+    protected final DataHolderCompleter getBaseCompleter(final T schemaNode) {
+        final TypeDefinition<?> type = getType(schemaNode);
+        final DataHolderCompleter currentCompleter;
+
+        // Add enum completer
+        if (type instanceof EnumTypeDefinition) {
+            currentCompleter = new EnumDataHolderCompleter(type);
+        } else if (type instanceof IdentityrefTypeDefinition) {
+            currentCompleter = new IdentityRefDataHolderCompleter(type, getSchemaContext());
+        } else {
+            currentCompleter = new GeneralDataHolderCompleter(type);
+        }
+        this.currentCompleter = currentCompleter;
+        return currentCompleter;
+    }
+
+    private static interface DataHolderCompleter extends Completer {
+
+        Object resolveValue(String rawValue) throws ReadingException;
+    }
+
+    private static class GeneralDataHolderCompleter implements DataHolderCompleter {
+
+        private final Optional<TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>>> codec;
+        private final TypeDefinition<?> type;
+
+        public GeneralDataHolderCompleter(final TypeDefinition<?> type) {
+            this.type = type;
+            codec = getCodecForType(type);
+        }
+
+        protected TypeDefinition<?> getType() {
+            return type;
+        }
+
+        private Optional<TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>>> getCodecForType(
+                final TypeDefinition<?> type) {
+            if (type != null) {
+                return Optional
+                        .<TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>>> fromNullable(TypeDefinitionAwareCodec
+                                .from(type));
+            }
+            return Optional.absent();
+        }
+
+        @Override
+        public Object resolveValue(final String rawValue) throws ReadingException {
+            try {
+                return codec.isPresent() ? codec.get().deserialize(rawValue) : rawValue;
+            } catch (final RuntimeException e) {
+                final String message = "It wasn't possible deserialize value " + rawValue + ".";
+                LOG.error(message, e);
+                throw new ReadingException(message, e);
+            }
+        }
+
+        @Override
+        public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+            return 0;
+        }
+    }
+
+    private static final class EnumDataHolderCompleter extends GeneralDataHolderCompleter {
+
+        public EnumDataHolderCompleter(final TypeDefinition<?> type) {
+            super(type);
+        }
+
+        @Override
+        public Object resolveValue(final String rawValue) throws ReadingException {
+            return super.resolveValue(rawValue);
+        }
+
+        @Override
+        public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+            return new StringsCompleter(Collections2.transform(((EnumTypeDefinition) getType()).getValues(),
+                    new Function<EnumPair, String>() {
+                        @Override
+                        public String apply(final EnumPair input) {
+                            return input.getName();
+                        }
+                    })).complete(buffer, cursor, candidates);
+        }
+    }
+
+    private static final class IdentityRefDataHolderCompleter extends GeneralDataHolderCompleter {
+
+        private final BiMap<String, QName> identityMap;
+
+        public IdentityRefDataHolderCompleter(final TypeDefinition<?> type, final SchemaContext schemaContext) {
+            super(type);
+            this.identityMap = getIdentityMap(schemaContext);
+        }
+
+        private static BiMap<String, QName> getIdentityMap(final SchemaContext schemaContext) {
+            final BiMap<String, QName> identityMap = HashBiMap.create();
+            for (final Module module : schemaContext.getModules()) {
+                for (final IdentitySchemaNode identity : module.getIdentities()) {
+                    identityMap.put(getIdentityName(identity, module), identity.getQName());
+                }
+            }
+            return identityMap;
+        }
+
+        private static String getIdentityName(final IdentitySchemaNode rpcDefinition, final Module module) {
+            return IOUtil.qNameToKeyString(rpcDefinition.getQName(), module.getName());
+        }
+
+        @Override
+        public Object resolveValue(final String rawValue) throws ReadingException {
+            final QName qName = identityMap.get(rawValue);
+            if (qName == null) {
+                throw new ReadingException("No identity found for " + rawValue + " available " + identityMap.keySet());
+            }
+            return qName;
+        }
+
+        @Override
+        public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+
+            return new StringsCompleter(Collections2.transform(((IdentityrefTypeDefinition) getType()).getIdentity()
+                    .getDerivedIdentities(), new Function<IdentitySchemaNode, String>() {
+                @Override
+                public String apply(final IdentitySchemaNode input) {
+                    return identityMap.inverse().get(input.getQName());
+                }
+            })).complete(buffer, cursor, candidates);
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ChoiceReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ChoiceReader.java
new file mode 100644 (file)
index 0000000..1e69fbb
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.isSkipInput;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+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.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ChoiceReader extends AbstractReader<ChoiceNode> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ChoiceReader.class);
+
+    private final CommandArgHandlerRegistry argumentHandlerRegistry;
+
+    public ChoiceReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext) {
+        super(console, schemaContext);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    public ChoiceReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    @Override
+    public List<Node<?>> readWithContext(final ChoiceNode choiceNode) throws IOException, ReadingException {
+        final Map<String, ChoiceCaseNode> availableCases = collectAllCases(choiceNode);
+        console.formatLn("Select case for choice %s from: %s", choiceNode.getQName().getLocalName(),
+                formatSet(availableCases.keySet()));
+
+        ChoiceCaseNode selectedCase = null;
+        final String rawValue = console.read();
+        if (isSkipInput(rawValue)) {
+            return Collections.emptyList();
+        }
+
+        selectedCase = availableCases.get(rawValue);
+        if (selectedCase == null) {
+            final String message = String.format("Incorrect value (%s) for choice %s was selected.", rawValue,
+                    choiceNode.getQName().getLocalName());
+            LOG.error(message);
+            throw new ReadingException(message);
+        }
+
+        return readSelectedCase(selectedCase);
+    }
+
+    protected List<Node<?>> readSelectedCase(final ChoiceCaseNode selectedCase) throws ReadingException {
+        // IF there is a case that contains only one Empty type leaf, create the
+        // leaf without question, since the case was selected
+        if (containsOnlyOneEmptyLeaf(selectedCase)) {
+            final Node<?> newNode = NodeFactory.createImmutableSimpleNode(selectedCase.getChildNodes().iterator()
+                    .next().getQName(), null, null);
+            return Collections.<Node<?>> singletonList(newNode);
+        }
+
+        final List<Node<?>> newNodes = new ArrayList<>();
+        for (final DataSchemaNode schemaNode : selectedCase.getChildNodes()) {
+            newNodes.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(), getReadConfigNode()).read(
+                    schemaNode));
+        }
+        return newNodes;
+    }
+
+    private Object formatSet(final Set<String> values) {
+        final StringBuilder formatedValues = new StringBuilder();
+        for (final String value : values) {
+            formatedValues.append("\n  ");
+            formatedValues.append(value);
+        }
+        return formatedValues.toString();
+    }
+
+    private boolean containsOnlyOneEmptyLeaf(final ChoiceCaseNode selectedCase) {
+        if (selectedCase.getChildNodes().size() != 1) {
+            return false;
+        }
+        final DataSchemaNode next = selectedCase.getChildNodes().iterator().next();
+        if (next instanceof LeafSchemaNode) {
+            final TypeDefinition<?> type = ((LeafSchemaNode) next).getType();
+            if (isEmptyType(type)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Map<String, ChoiceCaseNode> collectAllCases(final ChoiceNode schemaNode) {
+        return Maps.uniqueIndex(schemaNode.getCases(), new Function<ChoiceCaseNode, String>() {
+            @Override
+            public String apply(final ChoiceCaseNode input) {
+                return input.getQName().getLocalName();
+            }
+        });
+    }
+
+    @Override
+    protected ConsoleContext getContext(final ChoiceNode schemaNode) {
+        return new BaseConsoleContext<ChoiceNode>(schemaNode) {
+            @Override
+            public List<Completer> getAdditionalCompleters() {
+                return Collections
+                        .<Completer> singletonList(new StringsCompleter(collectAllCases(schemaNode).keySet()));
+            }
+        };
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ContainerReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ContainerReader.java
new file mode 100644 (file)
index 0000000..8e9a29e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class ContainerReader extends AbstractReader<ContainerSchemaNode> {
+
+    private final CommandArgHandlerRegistry argumentHandlerRegistry;
+    private static final InputArgsLocalNameComparator CONTAINER_CHILDS_SORTER = new InputArgsLocalNameComparator();
+
+    public ContainerReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext) {
+        super(console, schemaContext);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    public ContainerReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    @Override
+    public List<Node<?>> readWithContext(final ContainerSchemaNode containerNode) throws IOException, ReadingException {
+        console.formatLn("Submit child nodes for container: %s, %s", containerNode.getQName().getLocalName(),
+                Collections2.transform(containerNode.getChildNodes(), new Function<DataSchemaNode, String>() {
+                    @Override
+                    public String apply(final DataSchemaNode input) {
+                        return input.getQName().getLocalName();
+                    }
+                }));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> compositeNodeBuilder = ImmutableCompositeNode.builder();
+        compositeNodeBuilder.setQName(containerNode.getQName());
+        final SeparatedNodes separatedNodes = SeparatedNodes.separateNodes(containerNode, getReadConfigNode());
+        for (final DataSchemaNode childNode : sortChildren(separatedNodes.getMandatoryNotKey())) {
+            final List<Node<?>> redNodes = argumentHandlerRegistry.getGenericReader(getSchemaContext(),
+                    getReadConfigNode()).read(childNode);
+            if (redNodes.isEmpty()) {
+                console.formatLn("No data specified for mandatory element %s.", childNode.getQName().getLocalName());
+                return Collections.emptyList();
+            } else {
+                compositeNodeBuilder.addAll(redNodes);
+            }
+        }
+
+        for (final DataSchemaNode childNode : sortChildren(separatedNodes.getOthers())) {
+            compositeNodeBuilder.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(),
+                    getReadConfigNode()).read(childNode));
+        }
+        return Collections.<Node<?>> singletonList(compositeNodeBuilder.toInstance());
+    }
+
+    private List<DataSchemaNode> sortChildren(final Set<DataSchemaNode> unsortedNodes) {
+        final List<DataSchemaNode> childNodes = Lists.newArrayList(unsortedNodes);
+        Collections.sort(childNodes, CONTAINER_CHILDS_SORTER);
+        return childNodes;
+    }
+
+    @Override
+    protected ConsoleContext getContext(final ContainerSchemaNode schemaNode) {
+        return new BaseConsoleContext<>(schemaNode);
+    }
+
+    private static class InputArgsLocalNameComparator implements Comparator<DataSchemaNode> {
+        @Override
+        public int compare(final DataSchemaNode o1, final DataSchemaNode o2) {
+            return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/DecisionReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/DecisionReader.java
new file mode 100644 (file)
index 0000000..b1e9a43
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.SKIP;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import jline.console.completer.AggregateCompleter;
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+import jline.internal.Log;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.io.IOUtil;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+
+public class DecisionReader {
+
+    private static final String YES = "Y";
+    private static final String NO = "N";
+    public static final Completer YES_NO_COMPLETER = new StringsCompleter(YES, NO);
+
+    public Optional<Boolean> read(final ConsoleIO console, final String questionMessageBlueprint,
+            final Object... questionMessageArgs) throws IOException, ReadingException {
+        final ConsoleContext ctx = getContext();
+        console.enterContext(ctx);
+        try {
+            console.formatLn(questionMessageBlueprint, questionMessageArgs);
+            final String rawValue = console.read();
+            if (YES.equals(rawValue.toUpperCase())) {
+                return Optional.of(Boolean.TRUE);
+            } else if (NO.equals(rawValue.toUpperCase())) {
+                return Optional.of(Boolean.FALSE);
+            } else if (SKIP.equals(rawValue)) {
+                return Optional.absent();
+            } else {
+                final String message = String.format("Incorrect possibility (%s) was selected", rawValue);
+                Log.error(message);
+                throw new ReadingException(message);
+            }
+        } finally {
+            console.leaveContext();
+        }
+    }
+
+    private static ConsoleContext getContext() {
+        return new ConsoleContext() {
+
+            @Override
+            public Optional<String> getPrompt() {
+                return Optional.absent();
+            }
+
+            @Override
+            public Completer getCompleter() {
+                return new AggregateCompleter(YES_NO_COMPLETER, new StringsCompleter(IOUtil.SKIP));
+            }
+
+        };
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/GenericListReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/GenericListReader.java
new file mode 100644 (file)
index 0000000..6cf8eb2
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.listType;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.GenericListEntryReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GenericListReader<T extends DataSchemaNode> extends AbstractReader<T> {
+    private static final Logger LOG = LoggerFactory.getLogger(GenericListReader.class);
+
+    private final GenericListEntryReader<T> concreteListEntryReader;
+
+    public GenericListReader(final ConsoleIO console, final GenericListEntryReader<T> concreteListEntryReader,
+            final SchemaContext schemaContext) {
+        super(console, schemaContext);
+        this.concreteListEntryReader = concreteListEntryReader;
+    }
+
+    public GenericListReader(final ConsoleIO console, final GenericListEntryReader<T> concreteListEntryReader,
+            final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+        this.concreteListEntryReader = concreteListEntryReader;
+    }
+
+    @Override
+    public List<Node<?>> readWithContext(final T schemaNode) throws IOException, ReadingException {
+        final List<Node<?>> newNodes = new ArrayList<>();
+        Optional<Boolean> readNextListEntry = Optional.of(Boolean.TRUE);
+        console.formatLn("Reading collection type argument: %s", schemaNode.getQName().getLocalName());
+        while (readNextListEntry.isPresent() && readNextListEntry.get()) {
+            try {
+                newNodes.addAll(concreteListEntryReader.read(schemaNode));
+            } catch (final ReadingException e) {
+                console.writeLn(e.getMessage());
+            }
+            readNextListEntry = new DecisionReader().read(console, "Add other entry to " + listType(schemaNode) + " "
+                    + schemaNode.getQName().getLocalName() + " " + " [Y|N]?");
+        }
+        console.formatLn("Collection type argument: %s read finished", schemaNode.getQName().getLocalName());
+
+        return newNodes;
+    }
+
+    @Override
+    protected ConsoleContext getContext(final T schemaNode) {
+        return new BaseConsoleContext<>(schemaNode);
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/GenericReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/GenericReader.java
new file mode 100644 (file)
index 0000000..8fbfbb7
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
+import org.opendaylight.controller.netconf.cli.commands.CommandConstants;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.GenericListEntryReader;
+import org.opendaylight.controller.netconf.cli.reader.Reader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+
+public class GenericReader extends AbstractReader<DataSchemaNode> {
+
+    private final CommandArgHandlerRegistry argumentHandlerRegistry;
+
+    public GenericReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext) {
+        super(console, schemaContext);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    public GenericReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    @Override
+    protected List<Node<?>> readWithContext(final DataSchemaNode schemaNode) throws IOException, ReadingException {
+        final Optional<Class<? extends Reader<DataSchemaNode>>> customReaderClassOpt = tryGetCustomHandler(schemaNode);
+
+        if (customReaderClassOpt.isPresent()) {
+            // TODO resolve class cast of generic custom readers
+            final Reader<DataSchemaNode> customReaderInstance = (Reader<DataSchemaNode>) argumentHandlerRegistry
+                    .getCustomReader(customReaderClassOpt.get());
+            Preconditions.checkNotNull(customReaderInstance, "Unknown custom reader: %s", customReaderClassOpt.get());
+            return customReaderInstance.read(schemaNode);
+        } else {
+            return readGeneric(schemaNode);
+        }
+
+        // TODO reuse instances
+    }
+
+    private List<Node<?>> readGeneric(final DataSchemaNode schemaNode) throws ReadingException, IOException {
+        final List<Node<?>> newNodes = new ArrayList<>();
+        boolean isRedCorrectly = false;
+        do {
+            try {
+                if (schemaNode instanceof LeafSchemaNode) {
+                    return new LeafReader(console, getSchemaContext(), getReadConfigNode())
+                            .read((LeafSchemaNode) schemaNode);
+                } else if (schemaNode instanceof ContainerSchemaNode) {
+                    return new ContainerReader(console, argumentHandlerRegistry, getSchemaContext(),
+                            getReadConfigNode()).read((ContainerSchemaNode) schemaNode);
+                } else if (schemaNode instanceof ListSchemaNode) {
+                    final GenericListEntryReader<ListSchemaNode> entryReader = new ListEntryReader(console,
+                            argumentHandlerRegistry, getSchemaContext(), getReadConfigNode());
+                    return new GenericListReader<>(console, entryReader, getSchemaContext(), getReadConfigNode())
+                            .read((ListSchemaNode) schemaNode);
+                } else if (schemaNode instanceof LeafListSchemaNode) {
+                    final GenericListEntryReader<LeafListSchemaNode> entryReader = new LeafListEntryReader(console,
+                            getSchemaContext(), getReadConfigNode());
+                    return new GenericListReader<>(console, entryReader, getSchemaContext(), getReadConfigNode())
+                            .read((LeafListSchemaNode) schemaNode);
+                } else if (schemaNode instanceof ChoiceNode) {
+                    return new ChoiceReader(console, argumentHandlerRegistry, getSchemaContext(), getReadConfigNode())
+                            .read((ChoiceNode) schemaNode);
+                } else if (schemaNode instanceof AnyXmlSchemaNode) {
+                    return new AnyXmlReader(console, getSchemaContext(), getReadConfigNode())
+                            .read((AnyXmlSchemaNode) schemaNode);
+                }
+                isRedCorrectly = true;
+            } catch (final ReadingException e) {
+                console.writeLn(e.getMessage());
+            }
+        } while (!isRedCorrectly);
+        return newNodes;
+    }
+
+    @Override
+    protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
+        // return null context, leave context to specific implementations
+        return NULL_CONTEXT;
+    }
+
+    private <T> Optional<Class<? extends T>> tryGetCustomHandler(final DataSchemaNode dataSchemaNode) {
+
+        for (final UnknownSchemaNode unknownSchemaNode : dataSchemaNode.getUnknownSchemaNodes()) {
+
+            if (isExtenstionForCustomHandler(unknownSchemaNode)) {
+                final String argumentHandlerClassName = unknownSchemaNode.getNodeParameter();
+                try {
+                    final Class<?> argumentClass = Class.forName(argumentHandlerClassName);
+                    // TODO add check before cast
+                    return Optional.<Class<? extends T>> of((Class<? extends T>) argumentClass);
+                } catch (final ClassNotFoundException e) {
+                    throw new IllegalArgumentException("Unknown custom reader class " + argumentHandlerClassName
+                            + " for: " + dataSchemaNode.getQName());
+                }
+            }
+        }
+
+        return Optional.absent();
+    }
+
+    private boolean isExtenstionForCustomHandler(final UnknownSchemaNode unknownSchemaNode) {
+        final QName qName = unknownSchemaNode.getExtensionDefinition().getQName();
+        return qName.equals(CommandConstants.ARG_HANDLER_EXT_QNAME);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/LeafListEntryReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/LeafListEntryReader.java
new file mode 100644 (file)
index 0000000..4ba3478
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import java.util.List;
+import jline.console.completer.Completer;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.GenericListEntryReader;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+class LeafListEntryReader extends BasicDataHolderReader<LeafListSchemaNode> implements
+        GenericListEntryReader<LeafListSchemaNode> {
+
+    public LeafListEntryReader(final ConsoleIO console, final SchemaContext schemaContext) {
+        super(console, schemaContext);
+    }
+
+    public LeafListEntryReader(final ConsoleIO console, final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+    }
+
+    @Override
+    protected TypeDefinition<?> getType(final LeafListSchemaNode schemaNode) {
+        return schemaNode.getType();
+    }
+
+    @Override
+    protected ConsoleContext getContext(final LeafListSchemaNode schemaNode) {
+        return new BaseConsoleContext<LeafListSchemaNode>(schemaNode) {
+
+            @Override
+            public Optional<String> getPrompt() {
+                return Optional.of("[entry]");
+            }
+
+            @Override
+            protected List<Completer> getAdditionalCompleters() {
+                return Lists.<Completer> newArrayList(getBaseCompleter(getDataSchemaNode()));
+            }
+        };
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/LeafReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/LeafReader.java
new file mode 100644 (file)
index 0000000..9a847f6
--- /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.netconf.cli.reader.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import java.util.List;
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public class LeafReader extends BasicDataHolderReader<LeafSchemaNode> {
+
+    public LeafReader(final ConsoleIO console, final SchemaContext schemaContext) {
+        super(console, schemaContext);
+    }
+
+    public LeafReader(final ConsoleIO console, final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+    }
+
+    @Override
+    protected TypeDefinition<?> getType(final LeafSchemaNode schemaNode) {
+        return schemaNode.getType();
+    }
+
+    @Override
+    protected ConsoleContext getContext(final LeafSchemaNode schemaNode) {
+        return new BaseConsoleContext<LeafSchemaNode>(schemaNode) {
+            @Override
+            public List<Completer> getAdditionalCompleters() {
+                final List<Completer> completers = Lists.<Completer> newArrayList(getBaseCompleter(schemaNode));
+                final Optional<String> defaultValue = getDefaultValue(schemaNode);
+                if (defaultValue.isPresent()) {
+                    completers.add(new StringsCompleter(defaultValue.get()));
+                }
+                return completers;
+            }
+        };
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ListEntryReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/ListEntryReader.java
new file mode 100644 (file)
index 0000000..97f7694
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.Collections2;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
+import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
+import org.opendaylight.controller.netconf.cli.reader.GenericListEntryReader;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class ListEntryReader extends AbstractReader<ListSchemaNode> implements GenericListEntryReader<ListSchemaNode> {
+    private static final Logger LOG = LoggerFactory.getLogger(ListEntryReader.class);
+
+    private final CommandArgHandlerRegistry argumentHandlerRegistry;
+
+    public ListEntryReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext) {
+        super(console, schemaContext);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    public ListEntryReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
+            final SchemaContext schemaContext, final boolean readConfigNode) {
+        super(console, schemaContext, readConfigNode);
+        this.argumentHandlerRegistry = argumentHandlerRegistry;
+    }
+
+    @Override
+    public List<Node<?>> readWithContext(final ListSchemaNode listNode) throws IOException, ReadingException {
+        console.formatLn("Submit child nodes for list entry: %s, %s", listNode.getQName().getLocalName(),
+                Collections2.transform(listNode.getChildNodes(), new Function<DataSchemaNode, String>() {
+                    @Override
+                    public String apply(final DataSchemaNode input) {
+                        return input.getQName().getLocalName();
+                    }
+                }));
+
+        final String listName = listNode.getQName().getLocalName();
+        final CompositeNodeBuilder<ImmutableCompositeNode> compositeNodeBuilder = ImmutableCompositeNode.builder();
+        compositeNodeBuilder.setQName(listNode.getQName());
+
+        final SeparatedNodes separatedChildNodes = SeparatedNodes.separateNodes(listNode, getReadConfigNode());
+
+        final List<Node<?>> nodes = readKeys(separatedChildNodes.getKeyNodes());
+        nodes.addAll(readMandatoryNotKeys(separatedChildNodes.getMandatoryNotKey()));
+        if (!separatedChildNodes.getOthers().isEmpty()) {
+            final Optional<Boolean> readNodesWhichAreNotKey = new DecisionReader().read(console,
+                    "Add non-key, non-mandatory nodes to list %s? [Y|N]", listName);
+            if (readNodesWhichAreNotKey.isPresent() && readNodesWhichAreNotKey.get()) {
+                nodes.addAll(readNotKeys(separatedChildNodes.getOthers()));
+            }
+        }
+
+        if (!nodes.isEmpty()) {
+            compositeNodeBuilder.addAll(nodes);
+            return Collections.<Node<?>> singletonList(compositeNodeBuilder.toInstance());
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    private List<Node<?>> readKeys(final Set<DataSchemaNode> keys) throws ReadingException, IOException {
+        final List<Node<?>> newNodes = new ArrayList<>();
+        console.writeLn("Reading keys:");
+        for (final DataSchemaNode key : keys) {
+            final List<Node<?>> readKey = new LeafReader(console, getSchemaContext(), getReadConfigNode())
+                    .read((LeafSchemaNode) key);
+            if (readKey.size() != 1) {
+                final String message = String.format(
+                        "Value for key element %s has to be set. Creation of this entry is canceled.", key.getQName()
+                                .getLocalName());
+                LOG.error(message);
+                throw new ReadingException(message);
+            }
+            newNodes.addAll(readKey);
+        }
+        return newNodes;
+    }
+
+    private List<Node<?>> readMandatoryNotKeys(final Set<DataSchemaNode> mandatoryNotKeys) throws ReadingException,
+            IOException {
+        final List<Node<?>> newNodes = new ArrayList<>();
+        console.writeLn("Reading mandatory not keys nodes:");
+
+        for (final DataSchemaNode mandatoryNode : mandatoryNotKeys) {
+            final List<Node<?>> redValue = argumentHandlerRegistry.getGenericReader(getSchemaContext(),
+                    getReadConfigNode()).read(mandatoryNode);
+            if (redValue.isEmpty()) {
+                final String message = String.format(
+                        "Value for mandatory element %s has to be set. Creation of this entry is canceled.",
+                        mandatoryNode.getQName().getLocalName());
+                LOG.error(message);
+                throw new ReadingException(message);
+            }
+            newNodes.addAll(redValue);
+        }
+        return newNodes;
+    }
+
+    private List<Node<?>> readNotKeys(final Set<DataSchemaNode> notKeys) throws ReadingException {
+        final List<Node<?>> newNodes = new ArrayList<>();
+        for (final DataSchemaNode notKey : notKeys) {
+            newNodes.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(), getReadConfigNode()).read(
+                    notKey));
+        }
+        return newNodes;
+    }
+
+    @Override
+    protected ConsoleContext getContext(final ListSchemaNode schemaNode) {
+        return new BaseConsoleContext<ListSchemaNode>(schemaNode) {
+            @Override
+            public Optional<String> getPrompt() {
+                return Optional.of("[entry]");
+            }
+        };
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/SeparatedNodes.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/SeparatedNodes.java
new file mode 100644 (file)
index 0000000..e05f786
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+class SeparatedNodes {
+    private final Set<DataSchemaNode> keyNodes;
+    private final Set<DataSchemaNode> mandatoryNotKey;
+    private final Set<DataSchemaNode> otherNodes;
+
+    public SeparatedNodes(final Set<DataSchemaNode> keyNodes, final Set<DataSchemaNode> mandatoryNotKey,
+            final Set<DataSchemaNode> otherNodes) {
+        this.keyNodes = keyNodes;
+        this.mandatoryNotKey = mandatoryNotKey;
+        this.otherNodes = otherNodes;
+    }
+
+    public Set<DataSchemaNode> getKeyNodes() {
+        return keyNodes;
+    }
+
+    public Set<DataSchemaNode> getMandatoryNotKey() {
+        return mandatoryNotKey;
+    }
+
+    public Set<DataSchemaNode> getOthers() {
+        return otherNodes;
+    }
+
+    static SeparatedNodes separateNodes(final DataNodeContainer dataNodeContainer) {
+        return separateNodes(dataNodeContainer, false);
+    }
+
+    static SeparatedNodes separateNodes(final DataNodeContainer dataNodeContainer, final boolean removeConfigFalseNodes) {
+        final Set<DataSchemaNode> keys = new HashSet<>();
+        final Set<DataSchemaNode> mandatoryNotKeys = new HashSet<>();
+        final Set<DataSchemaNode> others = new HashSet<>();
+
+        List<QName> keyQNames = Collections.emptyList();
+        if (dataNodeContainer instanceof ListSchemaNode) {
+            keyQNames = ((ListSchemaNode) dataNodeContainer).getKeyDefinition();
+        }
+
+        for (final DataSchemaNode dataSchemaNode : dataNodeContainer.getChildNodes()) {
+            if (removeConfigFalseNodes) {
+                if (!dataSchemaNode.isConfiguration()) {
+                    continue;
+                }
+            }
+            if (keyQNames.contains(dataSchemaNode.getQName())) {
+                Preconditions.checkArgument(dataSchemaNode instanceof LeafSchemaNode);
+                keys.add(dataSchemaNode);
+            } else if (dataSchemaNode.getConstraints().isMandatory()) {
+                mandatoryNotKeys.add(dataSchemaNode);
+            } else {
+                others.add(dataSchemaNode);
+            }
+        }
+
+        return new SeparatedNodes(keys, mandatoryNotKeys, others);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/UnionTypeReader.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/reader/impl/UnionTypeReader.java
new file mode 100644 (file)
index 0000000..e2d186b
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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.netconf.cli.reader.impl;
+
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.isSkipInput;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import jline.console.completer.AggregateCompleter;
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.io.IOUtil;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class UnionTypeReader {
+    private static final Logger LOG = LoggerFactory.getLogger(UnionTypeReader.class);
+
+    private final ConsoleIO console;
+
+    public UnionTypeReader(final ConsoleIO console) {
+        this.console = console;
+    }
+
+    public Optional<TypeDefinition<?>> read(final TypeDefinition<?> unionTypeDefinition) throws IOException,
+            ReadingException {
+        final ConsoleContext context = getContext(unionTypeDefinition);
+        console.enterContext(context);
+        try {
+            final Map<String, TypeDefinition<?>> mapping = ((UnionConsoleContext) context).getMenuItemMapping();
+            console.formatLn("The element is of type union. Choose concrete type from: %s", mapping.keySet());
+
+            final String rawValue = console.read();
+            if (isSkipInput(rawValue)) {
+                return Optional.absent();
+            }
+            final TypeDefinition<?> value = mapping.get(rawValue);
+            if (value != null) {
+                return Optional.<TypeDefinition<?>> of(value);
+            } else {
+                final String message = String.format("Incorrect type (%s) was specified for union type definition", rawValue);
+                LOG.error(message);
+                throw new ReadingException(message);
+            }
+        } finally {
+            console.leaveContext();
+        }
+    }
+
+    private UnionConsoleContext getContext(final TypeDefinition<?> typeDefinition) {
+        return new UnionConsoleContext(typeDefinition);
+    }
+
+    private class UnionConsoleContext implements ConsoleContext {
+
+        private final TypeDefinition<?> typeDef;
+        private final Map<String, TypeDefinition<?>> menuItemsToTypeDefinitions = new HashMap<>();
+
+        public UnionConsoleContext(final TypeDefinition<?> typeDef) {
+            this.typeDef = typeDef;
+        }
+
+        @Override
+        public Optional<String> getPrompt() {
+            return Optional.of("type[" + typeDef.getQName().getLocalName()  + "]");
+        }
+
+        @Override
+        public Completer getCompleter() {
+            List<TypeDefinition<?>> subtypesForMenu = resolveSubtypesFrom(typeDef);
+            if (subtypesForMenu.isEmpty()) {
+                subtypesForMenu = Collections.<TypeDefinition<?>> singletonList(typeDef);
+            }
+            final Collection<String> menuItems = toMenuItem(subtypesForMenu);
+            return new AggregateCompleter(new StringsCompleter(menuItems), new StringsCompleter(IOUtil.SKIP));
+        }
+
+        public Map<String, TypeDefinition<?>> getMenuItemMapping() {
+            return menuItemsToTypeDefinitions;
+        }
+
+        private Collection<String> toMenuItem(final List<TypeDefinition<?>> allTypesBehindUnion) {
+            final List<String> result = new ArrayList<String>();
+            for (final TypeDefinition<?> type : allTypesBehindUnion) {
+                final String menuItem = type.getQName().getLocalName();
+                menuItemsToTypeDefinitions.put(menuItem, type);
+                result.add(menuItem);
+            }
+            return result;
+        }
+
+        /**
+         *
+         * If union type is found in potentialEndTypeCandidate as subtype then
+         * it these subtypes become candidates.
+         *
+         * @param potentialEndTypeCandidate
+         *            candidate to node which has no union subtype
+         */
+        private List<TypeDefinition<?>> resolveSubtypesFrom(final TypeDefinition<?> potentialEndTypeCandidate) {
+            if (potentialEndTypeCandidate instanceof UnionTypeDefinition) {
+                return ((UnionTypeDefinition) potentialEndTypeCandidate).getTypes();
+            }
+            if (potentialEndTypeCandidate.getBaseType() == null) {
+                return Collections.emptyList();
+            }
+            return resolveSubtypesFrom(potentialEndTypeCandidate.getBaseType());
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/OutFormatter.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/OutFormatter.java
new file mode 100644 (file)
index 0000000..bed27b4
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.netconf.cli.writer;
+
+public class OutFormatter {
+
+    public static final String INDENT_STEP = "  ";
+    public static final String COMPOSITE_OPEN_NODE = " {";
+    public static final String COMPOSITE_CLOSE_NODE = "}";
+    public static final String NEW_LINE = "\n";
+
+    int indentLevel = -1;
+    private String currentIndent = "";
+
+    public OutFormatter indent(final StringBuilder buffer) {
+        buffer.append(currentIndent);
+        return this;
+    }
+
+    public OutFormatter openComposite(final StringBuilder buffer) {
+        buffer.append(COMPOSITE_OPEN_NODE);
+        return this;
+    }
+
+    public OutFormatter closeCompositeWithIndent(final StringBuilder buffer) {
+        buffer.append(currentIndent);
+        buffer.append(COMPOSITE_CLOSE_NODE);
+        return this;
+    }
+
+    public OutFormatter newLine(final StringBuilder buffer) {
+        buffer.append(NEW_LINE);
+        return this;
+    }
+
+    private void prepareIndent() {
+        final StringBuilder output = new StringBuilder();
+        for (int i = 0; i < indentLevel; i++) {
+            output.append(INDENT_STEP);
+        }
+        currentIndent = output.toString();
+    }
+
+    public OutFormatter increaseIndent() {
+        indentLevel++;
+        prepareIndent();
+        return this;
+    }
+
+    public OutFormatter decreaseIndent() {
+        indentLevel--;
+        prepareIndent();
+        return this;
+    }
+
+    public OutFormatter addStringWithIndent(final StringBuilder buffer, final String value) {
+        indent(buffer);
+        buffer.append(value);
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/WriteException.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/WriteException.java
new file mode 100644 (file)
index 0000000..b2cc456
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.netconf.cli.writer;
+
+public class WriteException extends Exception {
+
+    private static final long serialVersionUID = 8401242676753560336L;
+
+    public WriteException(final String msg, final Exception e) {
+        super(msg, e);
+    }
+
+    public WriteException(final String msg) {
+        super(msg);
+    }
+
+    public static class IncorrectNumberOfNodes extends WriteException {
+        private static final long serialVersionUID = 8910285140705622920L;
+
+        public IncorrectNumberOfNodes(final String msg) {
+            super(msg);
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/Writer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/Writer.java
new file mode 100644 (file)
index 0000000..ba3d876
--- /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.netconf.cli.writer;
+
+import java.util.List;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Generic handler(writer) of output elements for commands
+ */
+public interface Writer<T extends DataSchemaNode> {
+
+    void write(T dataSchemaNode, List<Node<?>> dataNodes) throws WriteException;
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/custom/DataWriter.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/custom/DataWriter.java
new file mode 100644 (file)
index 0000000..3724ecb
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.netconf.cli.writer.custom;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.controller.netconf.cli.writer.WriteException;
+import org.opendaylight.controller.netconf.cli.writer.impl.AbstractWriter;
+import org.opendaylight.controller.netconf.cli.writer.impl.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class DataWriter extends AbstractWriter<DataSchemaNode> {
+
+    private final OutFormatter out;
+    private final SchemaContext remoteSchemaContext;
+
+    public DataWriter(final ConsoleIO console, final OutFormatter out, final SchemaContext remoteSchemaContext) {
+        super(console);
+        this.out = out;
+        this.remoteSchemaContext = remoteSchemaContext;
+    }
+
+    @Override
+    protected void writeInner(final DataSchemaNode dataSchemaNode, final List<Node<?>> dataNodes) throws IOException, WriteException {
+        Preconditions.checkArgument(dataNodes.size() == 1, "Expected only 1 element for data node");
+        final Node<?> dataNode = dataNodes.get(0);
+        Preconditions.checkArgument(dataNode instanceof CompositeNode, "Unexpected node type: %s, should be %s", dataNode, CompositeNode.class);
+
+        StringBuilder output = new StringBuilder();
+        out.increaseIndent().addStringWithIndent(output, dataSchemaNode.getQName().getLocalName()).openComposite(output);
+        console.writeLn(output.toString());
+
+        for (final Node<?> childNode : ((CompositeNode) dataNode).getValue()) {
+            final Optional<DataSchemaNode> schemaNode = XmlDocumentUtils.findFirstSchema(childNode.getNodeType(), remoteSchemaContext.getDataDefinitions());
+            Preconditions.checkState(schemaNode.isPresent(), "Unknown data node %s, not defined in schema", childNode.getNodeType());
+            new NormalizedNodeWriter(console, out).write(schemaNode.get(), Collections.<Node<?>>singletonList(childNode));
+        }
+
+        output = new StringBuilder();
+        out.decreaseIndent().closeCompositeWithIndent(output);
+        console.writeLn(output.toString());
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/AbstractWriter.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/AbstractWriter.java
new file mode 100644 (file)
index 0000000..f9c4e84
--- /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.netconf.cli.writer.impl;
+
+import java.io.IOException;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.writer.WriteException;
+import org.opendaylight.controller.netconf.cli.writer.Writer;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public abstract class AbstractWriter<T extends DataSchemaNode> implements Writer<T> {
+
+    protected ConsoleIO console;
+
+    public AbstractWriter(final ConsoleIO console) {
+        this.console = console;
+    }
+
+    @Override
+    public void write(final T dataSchemaNode, final List<Node<?>> dataNodes) throws WriteException {
+        try {
+            writeInner(dataSchemaNode, dataNodes);
+        } catch (final IOException e) {
+            throw new WriteException("Unable to write data to output for " + dataSchemaNode.getQName(), e);
+        }
+    }
+
+    protected abstract void writeInner(final T dataSchemaNode, final List<Node<?>> dataNodes) throws IOException,
+            WriteException;
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/AugmentationNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/AugmentationNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..626bc4e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.cli.writer.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.AugmentationNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+final class AugmentationNodeCliSerializer extends AugmentationNodeBaseSerializer<String> {
+
+    private final NodeSerializerDispatcher<String> dispatcher;
+    private final OutFormatter out;
+
+    AugmentationNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
+        this.out = Preconditions.checkNotNull(out);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<String> serialize(final AugmentationSchema schema, final AugmentationNode node) {
+        final StringBuilder output = new StringBuilder();
+        out.increaseIndent();
+        out.addStringWithIndent(output, "augment");
+        out.openComposite(output);
+        out.newLine(output);
+
+        for (final String childOutput : super.serialize(schema, node)) {
+            output.append(childOutput);
+            out.newLine(output);
+        }
+
+        out.closeCompositeWithIndent(output);
+        out.decreaseIndent();
+        return Collections.singletonList(output.toString());
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<String> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/ChoiceNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/ChoiceNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..62845ad
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.cli.writer.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ChoiceNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+
+final class ChoiceNodeCliSerializer extends ChoiceNodeBaseSerializer<String> {
+    private final NodeSerializerDispatcher<String> dispatcher;
+    private final OutFormatter out;
+
+    ChoiceNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
+        this.out = Preconditions.checkNotNull(out);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<String> serialize(final ChoiceNode schema, final org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode node) {
+        final StringBuilder output = new StringBuilder();
+        out.increaseIndent();
+        out.addStringWithIndent(output, "choice ");
+        output.append(schema.getQName().getLocalName());
+        output.append(" (");
+        output.append(detectCase(schema, node));
+        output.append(") ");
+        out.openComposite(output);
+        out.newLine(output);
+
+        for (final String childOutput : super.serialize(schema, node)) {
+            output.append(childOutput);
+            out.newLine(output);
+        }
+
+        out.closeCompositeWithIndent(output);
+        out.decreaseIndent();
+        return Collections.singletonList(output.toString());
+    }
+
+    private String detectCase(final ChoiceNode schema, final org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode node) {
+        for (final DataContainerChild<? extends PathArgument, ?> caseChild : node.getValue()) {
+            final QName presentChildQName = caseChild.getNodeType();
+            for (final ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+                if (choiceCaseNode.getDataChildByName(presentChildQName) != null) {
+                    // Pick the first case that contains first child node
+                    return choiceCaseNode.getQName().getLocalName();
+                }
+            }
+        }
+
+        // Should not happen, nodes should come from one of the cases
+        throw new IllegalStateException("Choice node " + node + " does not conform to choice schema " + schema);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<String> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/CliOutputFromNormalizedNodeSerializerFactory.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/CliOutputFromNormalizedNodeSerializerFactory.java
new file mode 100644 (file)
index 0000000..cab07af
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.netconf.cli.writer.impl;
+
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+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.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializerFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+public final class CliOutputFromNormalizedNodeSerializerFactory implements FromNormalizedNodeSerializerFactory<String> {
+    private final ContainerNodeCliSerializer containerSerializer;
+    private final ChoiceNodeCliSerializer choiceSerializer;
+    private final AugmentationNodeCliSerializer augmentSerializer;
+    private final LeafNodeCliSerializer leafNodeSerializer;
+    private final LeafSetNodeCliSerializer leafSetSerializer;
+    private final MapNodeCliSerializer mapNodeSerializer;
+    private final LeafSetEntryNodeCliSerializer leafSetEntryNodeSerializer;
+    private final MapEntryNodeCliSerializer mapEntryNodeSerializer;
+    final NodeSerializerDispatcher<String> dispatcher = new NodeCliSerializerDispatcher(this);
+
+    private CliOutputFromNormalizedNodeSerializerFactory(final OutFormatter out, final XmlCodecProvider codecProvider) {
+
+        containerSerializer = new ContainerNodeCliSerializer(out, dispatcher);
+        choiceSerializer = new ChoiceNodeCliSerializer(out, dispatcher);
+        augmentSerializer = new AugmentationNodeCliSerializer(out, dispatcher);
+        leafNodeSerializer = new LeafNodeCliSerializer(out);
+
+        leafSetEntryNodeSerializer = new LeafSetEntryNodeCliSerializer(out);
+        leafSetSerializer = new LeafSetNodeCliSerializer(out, leafSetEntryNodeSerializer);
+
+        mapEntryNodeSerializer = new MapEntryNodeCliSerializer(out, dispatcher);
+        mapNodeSerializer = new MapNodeCliSerializer(out, mapEntryNodeSerializer);
+    }
+
+    public NodeSerializerDispatcher<String> getDispatcher() {
+        return dispatcher;
+    }
+
+    public static CliOutputFromNormalizedNodeSerializerFactory getInstance(final OutFormatter out,
+            final XmlCodecProvider codecProvider) {
+        return new CliOutputFromNormalizedNodeSerializerFactory(out, codecProvider);
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer() {
+        return augmentSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer() {
+        return choiceSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer() {
+        return containerSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer() {
+        return leafNodeSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer() {
+        return leafSetEntryNodeSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer() {
+        return leafSetSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, MapEntryNode, ListSchemaNode> getMapEntryNodeSerializer() {
+        return mapEntryNodeSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<String, MapNode, ListSchemaNode> getMapNodeSerializer() {
+        return mapNodeSerializer;
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/CompositeNodeWriter.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/CompositeNodeWriter.java
new file mode 100644 (file)
index 0000000..57d8f57
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.netconf.cli.writer.impl;
+
+import java.io.IOException;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.controller.netconf.cli.writer.WriteException;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public class CompositeNodeWriter extends AbstractWriter<DataSchemaNode> {
+
+    private final OutFormatter outFormatter;
+
+    public CompositeNodeWriter(final ConsoleIO console, final OutFormatter outFormatter) {
+        super(console);
+        this.outFormatter = outFormatter;
+    }
+
+    @Override
+    protected void writeInner(final DataSchemaNode dataSchemaNode, final List<Node<?>> dataNodes) throws IOException, WriteException {
+        final StringBuilder output = new StringBuilder();
+        writeNode(dataNodes, output);
+        console.writeLn(output);
+    }
+
+    private void writeNode(final List<Node<?>> dataNodes, final StringBuilder output) throws IOException, WriteException {
+        for (final Node<?> dataNode : dataNodes) {
+            outFormatter.increaseIndent();
+            outFormatter.addStringWithIndent(output, dataNode.getNodeType().getLocalName());
+            if (dataNode instanceof CompositeNode) {
+                outFormatter.openComposite(output);
+                outFormatter.newLine(output);
+                writeNode(((CompositeNode) dataNode).getValue(), output);
+                outFormatter.closeCompositeWithIndent(output);
+                outFormatter.newLine(output);
+            } else if (dataNode instanceof SimpleNode<?>) {
+                final SimpleNode<?> simpleNode = (SimpleNode<?>) dataNode;
+                output.append(" ");
+                output.append(simpleNode.getValue());
+                outFormatter.newLine(output);
+            }
+            outFormatter.decreaseIndent();
+        }
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/ContainerNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/ContainerNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..62b995e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.cli.writer.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ContainerNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+
+final class ContainerNodeCliSerializer extends ContainerNodeBaseSerializer<String> {
+
+    private final NodeSerializerDispatcher<String> dispatcher;
+    private final OutFormatter out;
+
+    ContainerNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
+        this.out = Preconditions.checkNotNull(out);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<String> serialize(final ContainerSchemaNode schema, final ContainerNode containerNode) {
+        final StringBuilder output = new StringBuilder();
+        out.increaseIndent();
+        out.addStringWithIndent(output, containerNode.getNodeType().getLocalName());
+        out.openComposite(output);
+        out.newLine(output);
+
+        for (final String childOutput : super.serialize(schema, containerNode)) {
+            output.append(childOutput);
+            out.newLine(output);
+        }
+
+        out.closeCompositeWithIndent(output);
+        out.decreaseIndent();
+        return Collections.singletonList(output.toString());
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<String> getNodeDispatcher() {
+        return dispatcher;
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..d3216c2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.cli.writer.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+final class LeafNodeCliSerializer extends LeafNodeBaseSerializer<String> {
+    private final OutFormatter out;
+
+    LeafNodeCliSerializer(final OutFormatter out) {
+        this.out = Preconditions.checkNotNull(out);
+    }
+
+    @Override
+    public String serializeLeaf(final LeafSchemaNode schema, final LeafNode<?> node) {
+        final StringBuilder output = new StringBuilder();
+        out.increaseIndent();
+        out.addStringWithIndent(output, node.getNodeType().getLocalName());
+        output.append(" ");
+        output.append(node.getValue());
+        out.decreaseIndent();
+        return output.toString();
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafSetEntryNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafSetEntryNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..4937432
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.cli.writer.impl;
+
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+final class LeafSetEntryNodeCliSerializer extends LeafSetEntryNodeBaseSerializer<String> {
+
+    private final OutFormatter out;
+
+    public LeafSetEntryNodeCliSerializer(final OutFormatter out) {
+        this.out = out;
+    }
+
+    @Override
+    protected String serializeLeaf(final LeafListSchemaNode schema, final LeafSetEntryNode<?> node) {
+        final StringBuilder output = new StringBuilder();
+        out.increaseIndent();
+        out.addStringWithIndent(output, node.getValue().toString());
+        out.decreaseIndent();
+        return output.toString();
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafSetNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/LeafSetNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..8d618e8
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.cli.writer.impl;
+
+import java.util.Collections;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+final class LeafSetNodeCliSerializer implements
+        FromNormalizedNodeSerializer<String, LeafSetNode<?>, LeafListSchemaNode> {
+    private final LeafSetEntryNodeCliSerializer leafSetEntryNodeSerializer;
+    private final OutFormatter out;
+
+    LeafSetNodeCliSerializer(final OutFormatter out, final LeafSetEntryNodeCliSerializer leafSetEntryNodeSerializer) {
+        this.out = out;
+        this.leafSetEntryNodeSerializer = leafSetEntryNodeSerializer;
+    }
+
+    @Override
+    public Iterable<String> serialize(final LeafListSchemaNode schema, final LeafSetNode<?> node) {
+        final StringBuilder output = new StringBuilder();
+        out.increaseIndent();
+        out.addStringWithIndent(output, node.getNodeType().getLocalName());
+        out.openComposite(output);
+        out.newLine(output);
+        for (final LeafSetEntryNode<?> leafEntryNode : node.getValue()) {
+            final Iterable<String> valueFromLeafSetEntry = leafSetEntryNodeSerializer.serialize(schema, leafEntryNode);
+            output.append(valueFromLeafSetEntry.iterator().next());
+            out.newLine(output);
+        }
+        out.closeCompositeWithIndent(output);
+        out.decreaseIndent();
+        return Collections.singletonList(output.toString());
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/MapEntryNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/MapEntryNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..15f86a7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.cli.writer.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.MapEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class MapEntryNodeCliSerializer extends MapEntryNodeBaseSerializer<String> {
+
+    private final NodeSerializerDispatcher<String> dispatcher;
+    private final OutFormatter out;
+
+    MapEntryNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
+        this.out = Preconditions.checkNotNull(out);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<String> serialize(final ListSchemaNode schema, final MapEntryNode node) {
+        final StringBuilder output = new StringBuilder();
+        out.increaseIndent();
+        out.addStringWithIndent(output, node.getNodeType().getLocalName());
+        serializeKeysIfPresent(node, output);
+
+        out.openComposite(output);
+        out.newLine(output);
+
+        for (final String childOutput : super.serialize(schema, node)) {
+            output.append(childOutput);
+            out.newLine(output);
+        }
+
+        out.closeCompositeWithIndent(output);
+        out.newLine(output);
+        out.decreaseIndent();
+        return Collections.singletonList(output.toString());
+    }
+
+    private void serializeKeysIfPresent(final MapEntryNode node, final StringBuilder output) {
+        final Map<QName, Object> keyValues = node.getIdentifier().getKeyValues();
+        if (keyValues.isEmpty()) {
+            return;
+        }
+
+        int i = 0;
+        output.append(" [");
+        for (final Entry<QName, Object> qNameObjectEntry : keyValues.entrySet()) {
+            output.append(qNameObjectEntry.getKey().getLocalName());
+            output.append("=");
+            output.append(qNameObjectEntry.getValue().toString());
+            if (++i != keyValues.size()) {
+                output.append(", ");
+            }
+        }
+        output.append("]");
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<String> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/MapNodeCliSerializer.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/MapNodeCliSerializer.java
new file mode 100644 (file)
index 0000000..b08acbf
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.cli.writer.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class MapNodeCliSerializer implements FromNormalizedNodeSerializer<String, MapNode, ListSchemaNode> {
+
+    private final FromNormalizedNodeSerializer<String, MapEntryNode, ListSchemaNode> mapEntrySerializer;
+    private final OutFormatter out;
+
+    MapNodeCliSerializer(final OutFormatter out, final MapEntryNodeCliSerializer mapEntrySerializer) {
+        this.out = Preconditions.checkNotNull(out);
+        this.mapEntrySerializer = mapEntrySerializer;
+    }
+
+    @Override
+    public Iterable<String> serialize(final ListSchemaNode schema, final MapNode node) {
+        final StringBuilder output = new StringBuilder();
+
+        out.increaseIndent();
+        out.addStringWithIndent(output, node.getNodeType().getLocalName());
+        output.append(" ");
+        out.openComposite(output);
+        out.newLine(output);
+
+        for (final MapEntryNode mapEntryNode : node.getValue()) {
+            final Iterable<String> valueFromLeafSetEntry = mapEntrySerializer.serialize(schema, mapEntryNode);
+            output.append(valueFromLeafSetEntry.iterator().next());
+        }
+
+        out.closeCompositeWithIndent(output);
+        out.decreaseIndent();
+
+        return Collections.singletonList(output.toString());
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NodeCliSerializerDispatcher.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NodeCliSerializerDispatcher.java
new file mode 100644 (file)
index 0000000..08abd47
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.cli.writer.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+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.MixinNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializerFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+public class NodeCliSerializerDispatcher implements NodeSerializerDispatcher<String> {
+    private final FromNormalizedNodeSerializerFactory<String> factory;
+
+    public NodeCliSerializerDispatcher(final FromNormalizedNodeSerializerFactory<String> factory) {
+        this.factory = Preconditions.checkNotNull(factory);
+    }
+
+    @Override
+    public final Iterable<String> dispatchChildElement(final Object childSchema,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        if (dataContainerChild instanceof ContainerNode) {
+            return onContainerNode(childSchema, dataContainerChild);
+        } else if (dataContainerChild instanceof LeafNode<?>) {
+            return onLeafNode(childSchema, dataContainerChild);
+        } else if (dataContainerChild instanceof MixinNode) {
+            if (dataContainerChild instanceof LeafSetNode<?>) {
+                return onLeafListNode(childSchema, dataContainerChild);
+            } else if (dataContainerChild instanceof MapNode) {
+                return onListNode(childSchema, dataContainerChild);
+            } else if (dataContainerChild instanceof ChoiceNode) {
+                return onChoiceNode(childSchema, dataContainerChild);
+            } else if (dataContainerChild instanceof AugmentationNode) {
+                return onAugmentationSchema(childSchema, dataContainerChild);
+            }
+        }
+        throw new IllegalArgumentException("Unable to serialize " + childSchema);
+    }
+
+    private Iterable<String> onAugmentationSchema(final Object childSchema,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        checkSchemaCompatibility(childSchema, AugmentationSchema.class, dataContainerChild);
+        return factory.getAugmentationNodeSerializer().serialize((AugmentationSchema) childSchema,
+                (AugmentationNode) dataContainerChild);
+    }
+
+    private Iterable<String> onChoiceNode(final Object childSchema,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        checkSchemaCompatibility(childSchema, org.opendaylight.yangtools.yang.model.api.ChoiceNode.class,
+                dataContainerChild);
+        return factory.getChoiceNodeSerializer().serialize(
+                (org.opendaylight.yangtools.yang.model.api.ChoiceNode) childSchema, (ChoiceNode) dataContainerChild);
+    }
+
+    private Iterable<String> onListNode(final Object childSchema,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        checkSchemaCompatibility(childSchema, ListSchemaNode.class, dataContainerChild);
+        return factory.getMapNodeSerializer().serialize((ListSchemaNode) childSchema, (MapNode) dataContainerChild);
+    }
+
+    private Iterable<String> onLeafListNode(final Object childSchema,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        checkSchemaCompatibility(childSchema, LeafListSchemaNode.class, dataContainerChild);
+        return factory.getLeafSetNodeSerializer().serialize((LeafListSchemaNode) childSchema,
+                (LeafSetNode<?>) dataContainerChild);
+    }
+
+    private Iterable<String> onLeafNode(final Object childSchema,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        checkSchemaCompatibility(childSchema, LeafSchemaNode.class, dataContainerChild);
+        final Iterable<String> elements = factory.getLeafNodeSerializer().serialize((LeafSchemaNode) childSchema,
+                (LeafNode<?>) dataContainerChild);
+        checkOnlyOneSerializedElement(elements, dataContainerChild);
+        return elements;
+    }
+
+    private static void checkOnlyOneSerializedElement(final Iterable<?> elements,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        final int size = Iterables.size(elements);
+        Preconditions.checkArgument(size == 1,
+                "Unexpected count of elements for entry serialized from: %s, should be 1, was: %s", dataContainerChild,
+                size);
+    }
+
+    private Iterable<String> onContainerNode(final Object childSchema,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        checkSchemaCompatibility(childSchema, ContainerSchemaNode.class, dataContainerChild);
+
+        final Iterable<String> elements = factory.getContainerNodeSerializer().serialize(
+                (ContainerSchemaNode) childSchema, (ContainerNode) dataContainerChild);
+        checkOnlyOneSerializedElement(elements, dataContainerChild);
+        return elements;
+    }
+
+    private static void checkSchemaCompatibility(final Object childSchema, final Class<?> containerSchemaNodeClass,
+            final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+        Preconditions.checkArgument(containerSchemaNodeClass.isAssignableFrom(childSchema.getClass()),
+                "Incompatible schema: %s with node: %s, expected: %s", childSchema, dataContainerChild,
+                containerSchemaNodeClass);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NormalizedNodeWriter.java b/opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NormalizedNodeWriter.java
new file mode 100644 (file)
index 0000000..eef9a39
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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.netconf.cli.writer.impl;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.controller.netconf.cli.writer.WriteException;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.json.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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;
+
+public class NormalizedNodeWriter extends AbstractWriter<DataSchemaNode> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodeWriter.class);
+    private final OutFormatter out;
+
+    public NormalizedNodeWriter(final ConsoleIO console, final OutFormatter out) {
+        super(console);
+        this.out = out;
+    }
+
+    public void writeInner(final DataSchemaNode dataSchemaNode, final List<Node<?>> dataNodes) throws WriteException,
+            IOException {
+
+        // TODO - add getDispatcher method to CnSnToNormalizedNodeParserFactory
+        // to be able call dispatchChildElement
+        final DataContainerChild<? extends PathArgument, ?> dataContainerChild = parseToNormalizedNode(dataNodes,
+                dataSchemaNode);
+
+        if (dataContainerChild != null) {
+            console.writeLn(serializeToCliOutput(dataContainerChild, dataSchemaNode));
+        }
+
+    }
+
+    private String serializeToCliOutput(final DataContainerChild<? extends PathArgument, ?> dataContainerChild,
+            final DataSchemaNode childSchema) {
+        final CliOutputFromNormalizedNodeSerializerFactory factorySerialization = CliOutputFromNormalizedNodeSerializerFactory
+                .getInstance(out, DomUtils.defaultValueCodecProvider());
+        final NodeSerializerDispatcher<String> dispatcher = factorySerialization.getDispatcher();
+        final Iterable<String> result = dispatcher.dispatchChildElement(childSchema, dataContainerChild);
+
+        if (result == null) {
+            return "";
+        }
+
+        final Iterator<String> output = result.iterator();
+        if (!output.hasNext()) {
+            return "";
+        }
+
+        return output.next();
+    }
+
+    private DataContainerChild<? extends PathArgument, ?> parseToNormalizedNode(final List<Node<?>> dataNodes,
+            final DataSchemaNode dataSchemaNode) {
+        final CnSnToNormalizedNodeParserFactory factoryParsing = CnSnToNormalizedNodeParserFactory.getInstance();
+        if (dataSchemaNode instanceof ContainerSchemaNode) {
+            return factoryParsing.getContainerNodeParser().parse(dataNodes, (ContainerSchemaNode) dataSchemaNode);
+        } else if (dataSchemaNode instanceof LeafSchemaNode) {
+            return factoryParsing.getLeafNodeParser().parse(dataNodes, (LeafSchemaNode) dataSchemaNode);
+        } else if (dataSchemaNode instanceof LeafListSchemaNode) {
+            return factoryParsing.getLeafSetNodeParser().parse(dataNodes, (LeafListSchemaNode) dataSchemaNode);
+        } else if (dataSchemaNode instanceof ListSchemaNode) {
+            return factoryParsing.getMapNodeParser().parse(dataNodes, (ListSchemaNode) dataSchemaNode);
+        } else if (dataSchemaNode instanceof ChoiceNode) {
+            return factoryParsing.getChoiceNodeParser().parse(dataNodes, (ChoiceNode) dataSchemaNode);
+        } else if (dataSchemaNode instanceof AugmentationSchema) {
+            return factoryParsing.getAugmentationNodeParser().parse(dataNodes, (AugmentationSchema) dataSchemaNode);
+        }
+        return null;
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/main/resources/logback.xml b/opendaylight/netconf/netconf-cli/src/main/resources/logback.xml
new file mode 100644 (file)
index 0000000..55eedc5
--- /dev/null
@@ -0,0 +1,31 @@
+
+<configuration scan="true">
+  <appender name="netconfcli.log" class="ch.qos.logback.core.FileAppender">
+    <file>netconfcli.log</file>
+
+    <encoder>
+      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level
+        %logger{35} - %msg%n</pattern>
+    </encoder>
+
+  </appender>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder
+      by default -->
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+      </pattern>
+    </encoder>
+  </appender>
+
+
+
+  <root level="trace">
+    <appender-ref ref="netconfcli.log" />
+    <!-- <appender-ref ref="STDOUT" /> -->
+  </root>
+
+  <!-- <logger name="org.opendaylight.yangtools.yang.model.api" level="TRACE"
+    additivity="false"> <appender-ref ref="netconfcli.log" /> </logger> -->
+</configuration>
diff --git a/opendaylight/netconf/netconf-cli/src/main/resources/schema/common/ietf-inet-types.yang b/opendaylight/netconf/netconf-cli/src/main/resources/schema/common/ietf-inet-types.yang
new file mode 100644 (file)
index 0000000..edd285d
--- /dev/null
@@ -0,0 +1,427 @@
+module ietf-inet-types {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+  prefix "inet";
+
+  organization
+   "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+  contact
+   "WG Web:   <http://tools.ietf.org/wg/netmod/>
+    WG List:  <mailto:netmod@ietf.org>
+
+    WG Chair: David Partain
+              <mailto:david.partain@ericsson.com>
+
+    WG Chair: David Kessens
+              <mailto:david.kessens@nsn.com>
+
+    Editor:   Juergen Schoenwaelder
+              <mailto:j.schoenwaelder@jacobs-university.de>";
+
+  description
+   "This module contains a collection of generally useful derived
+    YANG data types for Internet addresses and related things.
+
+    Copyright (c) 2010 IETF Trust and the persons identified as
+    authors of the code.  All rights reserved.
+
+
+
+    Redistribution and use in source and binary forms, with or without
+    modification, is permitted pursuant to, and subject to the license
+    terms contained in, the Simplified BSD License set forth in Section
+    4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+    (http://trustee.ietf.org/license-info).
+
+    This version of this YANG module is part of RFC 6021; see
+    the RFC itself for full legal notices.";
+
+  revision 2010-09-24 {
+    description
+     "Initial revision.";
+    reference
+     "RFC 6021: Common YANG Data Types";
+  }
+
+  /*** collection of protocol field related types ***/
+
+  typedef ip-version {
+    type enumeration {
+      enum unknown {
+        value "0";
+        description
+         "An unknown or unspecified version of the Internet protocol.";
+      }
+      enum ipv4 {
+        value "1";
+        description
+         "The IPv4 protocol as defined in RFC 791.";
+      }
+      enum ipv6 {
+        value "2";
+        description
+         "The IPv6 protocol as defined in RFC 2460.";
+      }
+    }
+    description
+     "This value represents the version of the IP protocol.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetVersion textual convention of the SMIv2.";
+    reference
+     "RFC  791: Internet Protocol
+      RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+      RFC 4001: Textual Conventions for Internet Network Addresses";
+  }
+
+  typedef dscp {
+    type uint8 {
+      range "0..63";
+    }
+    description
+     "The dscp type represents a Differentiated Services Code-Point
+      that may be used for marking packets in a traffic stream.
+
+      In the value set and its semantics, this type is equivalent
+      to the Dscp textual convention of the SMIv2.";
+    reference
+     "RFC 3289: Management Information Base for the Differentiated
+                Services Architecture
+      RFC 2474: Definition of the Differentiated Services Field
+                (DS Field) in the IPv4 and IPv6 Headers
+      RFC 2780: IANA Allocation Guidelines For Values In
+                the Internet Protocol and Related Headers";
+  }
+
+  typedef ipv6-flow-label {
+    type uint32 {
+      range "0..1048575";
+    }
+    description
+     "The flow-label type represents flow identifier or Flow Label
+      in an IPv6 packet header that may be used to discriminate
+      traffic flows.
+
+      In the value set and its semantics, this type is equivalent
+      to the IPv6FlowLabel textual convention of the SMIv2.";
+    reference
+     "RFC 3595: Textual Conventions for IPv6 Flow Label
+      RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+  }
+
+  typedef port-number {
+    type uint16 {
+      range "0..65535";
+    }
+    description
+     "The port-number type represents a 16-bit port number of an
+      Internet transport layer protocol such as UDP, TCP, DCCP, or
+      SCTP.  Port numbers are assigned by IANA.  A current list of
+      all assignments is available from <http://www.iana.org/>.
+
+      Note that the port number value zero is reserved by IANA.  In
+      situations where the value zero does not make sense, it can
+      be excluded by subtyping the port-number type.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetPortNumber textual convention of the SMIv2.";
+    reference
+     "RFC  768: User Datagram Protocol
+      RFC  793: Transmission Control Protocol
+      RFC 4960: Stream Control Transmission Protocol
+      RFC 4340: Datagram Congestion Control Protocol (DCCP)
+      RFC 4001: Textual Conventions for Internet Network Addresses";
+  }
+
+  /*** collection of autonomous system related types ***/
+
+  typedef as-number {
+    type uint32;
+    description
+     "The as-number type represents autonomous system numbers
+      which identify an Autonomous System (AS).  An AS is a set
+      of routers under a single technical administration, using
+      an interior gateway protocol and common metrics to route
+      packets within the AS, and using an exterior gateway
+      protocol to route packets to other ASs'.  IANA maintains
+      the AS number space and has delegated large parts to the
+      regional registries.
+
+      Autonomous system numbers were originally limited to 16
+      bits.  BGP extensions have enlarged the autonomous system
+      number space to 32 bits.  This type therefore uses an uint32
+      base type without a range restriction in order to support
+      a larger autonomous system number space.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetAutonomousSystemNumber textual convention of
+      the SMIv2.";
+    reference
+     "RFC 1930: Guidelines for creation, selection, and registration
+                of an Autonomous System (AS)
+      RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+      RFC 4893: BGP Support for Four-octet AS Number Space
+      RFC 4001: Textual Conventions for Internet Network Addresses";
+  }
+
+  /*** collection of IP address and hostname related types ***/
+
+  typedef ip-address {
+    type union {
+      type inet:ipv4-address;
+      type inet:ipv6-address;
+    }
+    description
+     "The ip-address type represents an IP address and is IP
+      version neutral.  The format of the textual representations
+      implies the IP version.";
+  }
+
+  typedef ipv4-address {
+    type string {
+      pattern
+        '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+      +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+      + '(%[\p{N}\p{L}]+)?';
+    }
+    description
+      "The ipv4-address type represents an IPv4 address in
+       dotted-quad notation.  The IPv4 address may include a zone
+       index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format for the zone index is the numerical
+       format";
+  }
+
+  typedef ipv6-address {
+    type string {
+      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+            + '(%[\p{N}\p{L}]+)?';
+      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+            + '(%.+)?';
+    }
+    description
+     "The ipv6-address type represents an IPv6 address in full,
+      mixed, shortened, and shortened-mixed notation.  The IPv6
+      address may include a zone index, separated by a % sign.
+
+
+
+
+
+      The zone index is used to disambiguate identical address
+      values.  For link-local addresses, the zone index will
+      typically be the interface index number or the name of an
+      interface.  If the zone index is not present, the default
+      zone of the device will be used.
+
+      The canonical format of IPv6 addresses uses the compressed
+      format described in RFC 4291, Section 2.2, item 2 with the
+      following additional rules: the :: substitution must be
+      applied to the longest sequence of all-zero 16-bit chunks
+      in an IPv6 address.  If there is a tie, the first sequence
+      of all-zero 16-bit chunks is replaced by ::.  Single
+      all-zero 16-bit chunks are not compressed.  The canonical
+      format uses lowercase characters and leading zeros are
+      not allowed.  The canonical format for the zone index is
+      the numerical format as described in RFC 4007, Section
+      11.2.";
+    reference
+     "RFC 4291: IP Version 6 Addressing Architecture
+      RFC 4007: IPv6 Scoped Address Architecture
+      RFC 5952: A Recommendation for IPv6 Address Text Representation";
+  }
+
+  typedef ip-prefix {
+    type union {
+      type inet:ipv4-prefix;
+      type inet:ipv6-prefix;
+    }
+    description
+     "The ip-prefix type represents an IP prefix and is IP
+      version neutral.  The format of the textual representations
+      implies the IP version.";
+  }
+
+  typedef ipv4-prefix {
+    type string {
+      pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+    }
+    description
+     "The ipv4-prefix type represents an IPv4 address prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal to 32.
+
+
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.
+
+      The canonical format of an IPv4 prefix has all bits of
+      the IPv4 address set to zero that are not part of the
+      IPv4 prefix.";
+  }
+
+  typedef ipv6-prefix {
+    type string {
+      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+            + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+            + '(/.+)';
+    }
+    description
+     "The ipv6-prefix type represents an IPv6 address prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal 128.
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.
+
+      The IPv6 address should have all bits that do not belong
+      to the prefix set to zero.
+
+      The canonical format of an IPv6 prefix has all bits of
+      the IPv6 address set to zero that are not part of the
+      IPv6 prefix.  Furthermore, IPv6 address is represented
+      in the compressed format described in RFC 4291, Section
+      2.2, item 2 with the following additional rules: the ::
+      substitution must be applied to the longest sequence of
+      all-zero 16-bit chunks in an IPv6 address.  If there is
+      a tie, the first sequence of all-zero 16-bit chunks is
+      replaced by ::.  Single all-zero 16-bit chunks are not
+      compressed.  The canonical format uses lowercase
+      characters and leading zeros are not allowed.";
+    reference
+     "RFC 4291: IP Version 6 Addressing Architecture";
+  }
+
+
+  /*** collection of domain name and URI types ***/
+
+  typedef domain-name {
+    type string {
+      pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+           +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+           +  '|\.';
+      length "1..253";
+    }
+    description
+     "The domain-name type represents a DNS domain name.  The
+      name SHOULD be fully qualified whenever possible.
+
+      Internet domain names are only loosely specified.  Section
+      3.5 of RFC 1034 recommends a syntax (modified in Section
+      2.1 of RFC 1123).  The pattern above is intended to allow
+      for current practice in domain name use, and some possible
+      future expansion.  It is designed to hold various types of
+      domain names, including names used for A or AAAA records
+      (host names) and other records, such as SRV records.  Note
+      that Internet host names have a stricter syntax (described
+      in RFC 952) than the DNS recommendations in RFCs 1034 and
+      1123, and that systems that want to store host names in
+      schema nodes using the domain-name type are recommended to
+      adhere to this stricter standard to ensure interoperability.
+
+      The encoding of DNS names in the DNS protocol is limited
+      to 255 characters.  Since the encoding consists of labels
+      prefixed by a length bytes and there is a trailing NULL
+      byte, only 253 characters can appear in the textual dotted
+      notation.
+
+      The description clause of schema nodes using the domain-name
+      type MUST describe when and how these names are resolved to
+      IP addresses.  Note that the resolution of a domain-name value
+      may require to query multiple DNS records (e.g., A for IPv4
+      and AAAA for IPv6).  The order of the resolution process and
+      which DNS record takes precedence can either be defined
+      explicitely or it may depend on the configuration of the
+      resolver.
+
+      Domain-name values use the US-ASCII encoding.  Their canonical
+      format uses lowercase US-ASCII characters.  Internationalized
+      domain names MUST be encoded in punycode as described in RFC
+      3492";
+    reference
+     "RFC  952: DoD Internet Host Table Specification
+      RFC 1034: Domain Names - Concepts and Facilities
+      RFC 1123: Requirements for Internet Hosts -- Application
+                and Support
+      RFC 2782: A DNS RR for specifying the location of services
+                (DNS SRV)
+      RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                Internationalized Domain Names in Applications
+                (IDNA)
+      RFC 5891: Internationalizing Domain Names in Applications
+                (IDNA): Protocol";
+  }
+
+  typedef host {
+    type union {
+      type inet:ip-address;
+      type inet:domain-name;
+    }
+    description
+     "The host type represents either an IP address or a DNS
+      domain name.";
+  }
+
+  typedef uri {
+    type string;
+    description
+     "The uri type represents a Uniform Resource Identifier
+      (URI) as defined by STD 66.
+
+      Objects using the uri type MUST be in US-ASCII encoding,
+      and MUST be normalized as described by RFC 3986 Sections
+      6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+      percent-encoding is removed, and all case-insensitive
+      characters are set to lowercase except for hexadecimal
+      digits, which are normalized to uppercase as described in
+      Section 6.2.2.1.
+
+      The purpose of this normalization is to help provide
+      unique URIs.  Note that this normalization is not
+      sufficient to provide uniqueness.  Two URIs that are
+      textually distinct after this normalization may still be
+      equivalent.
+
+      Objects using the uri type may restrict the schemes that
+      they permit.  For example, 'data:' and 'urn:' schemes
+      might not be appropriate.
+
+      A zero-length URI is not a valid URI.  This can be used to
+      express 'URI absent' where required.
+
+      In the value set and its semantics, this type is equivalent
+      to the Uri SMIv2 textual convention defined in RFC 5017.";
+    reference
+     "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+      RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                Group: Uniform Resource Identifiers (URIs), URLs,
+                and Uniform Resource Names (URNs): Clarifications
+                and Recommendations
+      RFC 5017: MIB Textual Conventions for Uniform Resource
+                Identifiers (URIs)";
+  }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/resources/schema/common/netconf-cli-ext.yang b/opendaylight/netconf/netconf-cli/src/main/resources/schema/common/netconf-cli-ext.yang
new file mode 100644 (file)
index 0000000..139778a
--- /dev/null
@@ -0,0 +1,18 @@
+module netconf-cli-ext {
+
+  namespace "urn:ietf:params:xml:ns:netconf:base:1.0:cli";
+
+  prefix cliext;
+
+    revision 2014-05-26 {
+      description
+        "Initial revision";
+    }
+
+  extension argument-handler {
+    description
+        "Links custom argument reader to an input argument";
+    argument "name";
+  }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/resources/schema/local/netconf-cli.yang b/opendaylight/netconf/netconf-cli/src/main/resources/schema/local/netconf-cli.yang
new file mode 100644 (file)
index 0000000..52f7b97
--- /dev/null
@@ -0,0 +1,97 @@
+module netconf-cli {
+
+  namespace "netconf:cli";
+  prefix ncli;
+
+  import ietf-inet-types { prefix inet; revision-date 2010-09-24; }
+  import netconf-cli-ext { prefix cliext; revision-date 2014-05-26; }
+
+
+    revision 2014-05-22 {
+      description
+       "Initial revision.";
+    }
+
+  extension java-class {
+      description
+          "This could be used to link between rpc yang definition and custom command implementation";
+
+      argument "name";
+  }
+
+  rpc help {
+    description
+        "Display help";
+
+    output {
+      list commands {
+
+        key "id";
+        leaf id {
+            type string;
+        }
+        leaf description {
+            type string;
+        }
+      }
+    }
+  }
+
+  rpc close {
+      description
+          "Close the whole cli";
+  }
+
+  rpc connect {
+
+        description
+            "Connect to a remote netconf device, if not connected yet. Connection initialization is blocking and might take some time, depending on amount of yang schemas in remote device.";
+
+      input {
+
+         // TODO yangtools keep input arguments unordered so the ordering in cli is random
+         leaf address-name {
+           type inet:host;
+           default localhost;
+         }
+
+         leaf address-port {
+           type inet:port-number;
+           default 830;
+         }
+
+          leaf user-name {
+           type string;
+         }
+
+        leaf user-password {
+            cliext:argument-handler org.opendaylight.controller.netconf.cli.reader.custom.PasswordReader;
+            type string;
+        }
+      }
+
+      output {
+        leaf status {
+            type string;
+        }
+
+        leaf-list remote-commands {
+            type string;
+        }
+      }
+  }
+
+
+  rpc disconnect {
+
+      description
+          "Disconnect from a netconf device that is currently connected";
+
+      output {
+        leaf status {
+            type string;
+        }
+      }
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/main/resources/schema/remote/ietf-netconf.yang b/opendaylight/netconf/netconf-cli/src/main/resources/schema/remote/ietf-netconf.yang
new file mode 100644 (file)
index 0000000..d41c2e3
--- /dev/null
@@ -0,0 +1,943 @@
+module ietf-netconf {
+
+  // the namespace for NETCONF XML definitions is unchanged
+  // from RFC 4741, which this document replaces
+  namespace "urn:ietf:params:xml:ns:netconf:base:1.0";
+
+  prefix nc;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  import netconf-cli-ext { prefix cliext; revision-date 2014-05-26; }
+
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "WG Web:   <http://tools.ietf.org/wg/netconf/>
+     WG List:  <netconf@ietf.org>
+
+     WG Chair: Bert Wijnen
+               <bertietf@bwijnen.net>
+
+     WG Chair: Mehmet Ersue
+               <mehmet.ersue@nsn.com>
+
+     Editor:   Martin Bjorklund
+               <mbj@tail-f.com>
+
+     Editor:   Juergen Schoenwaelder
+               <j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Andy Bierman
+               <andy.bierman@brocade.com>";
+  description
+    "NETCONF Protocol Data Types and Protocol Operations.
+
+     Copyright (c) 2011 IETF Trust and the persons identified as
+     the document authors.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6241; see
+     the RFC itself for full legal notices.";
+  revision 2011-06-01 {
+    description
+      "Initial revision";
+    reference
+      "RFC 6241: Network Configuration Protocol";
+  }
+
+  extension get-filter-element-attributes {
+    description
+      "If this extension is present within an 'anyxml'
+       statement named 'filter', which must be conceptually
+       defined within the RPC input section for the <get>
+       and <get-config> protocol operations, then the
+       following unqualified XML attribute is supported
+       within the <filter> element, within a <get> or
+       <get-config> protocol operation:
+
+         type : optional attribute with allowed
+                value strings 'subtree' and 'xpath'.
+                If missing, the default value is 'subtree'.
+
+       If the 'xpath' feature is supported, then the
+       following unqualified XML attribute is
+       also supported:
+
+         select: optional attribute containing a
+                 string representing an XPath expression.
+                 The 'type' attribute must be equal to 'xpath'
+                 if this attribute is present.";
+  }
+
+  // NETCONF capabilities defined as features
+  feature writable-running {
+    description
+      "NETCONF :writable-running capability;
+       If the server advertises the :writable-running
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.2";
+  }
+
+  feature candidate {
+    description
+      "NETCONF :candidate capability;
+       If the server advertises the :candidate
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.3";
+  }
+
+  feature confirmed-commit {
+    if-feature candidate;
+    description
+      "NETCONF :confirmed-commit:1.1 capability;
+       If the server advertises the :confirmed-commit:1.1
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+
+    reference "RFC 6241, Section 8.4";
+  }
+
+  feature rollback-on-error {
+    description
+      "NETCONF :rollback-on-error capability;
+       If the server advertises the :rollback-on-error
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.5";
+  }
+
+  feature validate {
+    description
+      "NETCONF :validate:1.1 capability;
+       If the server advertises the :validate:1.1
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.6";
+  }
+
+  feature startup {
+    description
+      "NETCONF :startup capability;
+       If the server advertises the :startup
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.7";
+  }
+
+  feature url {
+    description
+      "NETCONF :url capability;
+       If the server advertises the :url
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.8";
+  }
+
+  feature xpath {
+    description
+      "NETCONF :xpath capability;
+       If the server advertises the :xpath
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.9";
+  }
+
+  // NETCONF Simple Types
+
+  typedef session-id-type {
+    type uint32 {
+      range "1..max";
+    }
+    description
+      "NETCONF Session Id";
+  }
+
+  typedef session-id-or-zero-type {
+    type uint32;
+    description
+      "NETCONF Session Id or Zero to indicate none";
+  }
+  typedef error-tag-type {
+    type enumeration {
+       enum in-use {
+         description
+           "The request requires a resource that
+            already is in use.";
+       }
+       enum invalid-value {
+         description
+           "The request specifies an unacceptable value for one
+            or more parameters.";
+       }
+       enum too-big {
+         description
+           "The request or response (that would be generated) is
+            too large for the implementation to handle.";
+       }
+       enum missing-attribute {
+         description
+           "An expected attribute is missing.";
+       }
+       enum bad-attribute {
+         description
+           "An attribute value is not correct; e.g., wrong type,
+            out of range, pattern mismatch.";
+       }
+       enum unknown-attribute {
+         description
+           "An unexpected attribute is present.";
+       }
+       enum missing-element {
+         description
+           "An expected element is missing.";
+       }
+       enum bad-element {
+         description
+           "An element value is not correct; e.g., wrong type,
+            out of range, pattern mismatch.";
+       }
+       enum unknown-element {
+         description
+           "An unexpected element is present.";
+       }
+       enum unknown-namespace {
+         description
+           "An unexpected namespace is present.";
+       }
+       enum access-denied {
+         description
+           "Access to the requested protocol operation or
+            data model is denied because authorization failed.";
+       }
+       enum lock-denied {
+         description
+           "Access to the requested lock is denied because the
+            lock is currently held by another entity.";
+       }
+       enum resource-denied {
+         description
+           "Request could not be completed because of
+            insufficient resources.";
+       }
+       enum rollback-failed {
+         description
+           "Request to roll back some configuration change (via
+            rollback-on-error or <discard-changes> operations)
+            was not completed for some reason.";
+
+       }
+       enum data-exists {
+         description
+           "Request could not be completed because the relevant
+            data model content already exists.  For example,
+            a 'create' operation was attempted on data that
+            already exists.";
+       }
+       enum data-missing {
+         description
+           "Request could not be completed because the relevant
+            data model content does not exist.  For example,
+            a 'delete' operation was attempted on
+            data that does not exist.";
+       }
+       enum operation-not-supported {
+         description
+           "Request could not be completed because the requested
+            operation is not supported by this implementation.";
+       }
+       enum operation-failed {
+         description
+           "Request could not be completed because the requested
+            operation failed for some reason not covered by
+            any other error condition.";
+       }
+       enum partial-operation {
+         description
+           "This error-tag is obsolete, and SHOULD NOT be sent
+            by servers conforming to this document.";
+       }
+       enum malformed-message {
+         description
+           "A message could not be handled because it failed to
+            be parsed correctly.  For example, the message is not
+            well-formed XML or it uses an invalid character set.";
+       }
+     }
+     description "NETCONF Error Tag";
+     reference "RFC 6241, Appendix A";
+  }
+
+  typedef error-severity-type {
+    type enumeration {
+      enum error {
+        description "Error severity";
+      }
+      enum warning {
+        description "Warning severity";
+      }
+    }
+    description "NETCONF Error Severity";
+    reference "RFC 6241, Section 4.3";
+  }
+
+  typedef edit-operation-type {
+    type enumeration {
+      enum merge {
+        description
+          "The configuration data identified by the
+           element containing this attribute is merged
+           with the configuration at the corresponding
+           level in the configuration datastore identified
+           by the target parameter.";
+      }
+      enum replace {
+        description
+          "The configuration data identified by the element
+           containing this attribute replaces any related
+           configuration in the configuration datastore
+           identified by the target parameter.  If no such
+           configuration data exists in the configuration
+           datastore, it is created.  Unlike a
+           <copy-config> operation, which replaces the
+           entire target configuration, only the configuration
+           actually present in the config parameter is affected.";
+      }
+      enum create {
+        description
+          "The configuration data identified by the element
+           containing this attribute is added to the
+           configuration if and only if the configuration
+           data does not already exist in the configuration
+           datastore.  If the configuration data exists, an
+           <rpc-error> element is returned with an
+           <error-tag> value of 'data-exists'.";
+      }
+      enum delete {
+        description
+          "The configuration data identified by the element
+           containing this attribute is deleted from the
+           configuration if and only if the configuration
+           data currently exists in the configuration
+           datastore.  If the configuration data does not
+           exist, an <rpc-error> element is returned with
+           an <error-tag> value of 'data-missing'.";
+      }
+      enum remove {
+        description
+          "The configuration data identified by the element
+           containing this attribute is deleted from the
+           configuration if the configuration
+           data currently exists in the configuration
+           datastore.  If the configuration data does not
+           exist, the 'remove' operation is silently ignored
+           by the server.";
+      }
+    }
+    default "merge";
+    description "NETCONF 'operation' attribute values";
+    reference "RFC 6241, Section 7.2";
+  }
+
+  // NETCONF Standard Protocol Operations
+
+  rpc get-config {
+    description
+      "Retrieve all or part of a specified configuration.";
+
+    reference "RFC 6241, Section 7.1";
+
+    input {
+      container source {
+        description
+          "Particular configuration to retrieve.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration to retrieve.";
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.
+               This is optional-to-implement on the server because
+               not all servers will support filtering for this
+               datastore.";
+          }
+        }
+      }
+
+      anyxml filter {
+        description
+          "Subtree or XPath filter to use.";
+        nc:get-filter-element-attributes;
+        // TODO this extension should be augmented (anyxml nodes cannot be augmented)
+        // or we can identify custom input/output arguments by schemaPath defined for custom handlers
+        cliext:argument-handler org.opendaylight.controller.netconf.cli.reader.custom.FilterReader;
+      }
+    }
+
+    output {
+      anyxml data {
+        description
+          "Copy of the source datastore subset that matched
+           the filter criteria (if any).  An empty data container
+           indicates that the request did not produce any results.";
+       cliext:argument-handler org.opendaylight.controller.netconf.cli.writer.custom.DataWriter;
+     }
+    }
+  }
+
+  rpc edit-config {
+    description
+      "The <edit-config> operation loads all or part of a specified
+       configuration to the specified target configuration.";
+
+    reference "RFC 6241, Section 7.2";
+
+    input {
+      container target {
+        description
+          "Particular configuration to edit.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            if-feature writable-running;
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+        }
+      }
+
+      leaf default-operation {
+        type enumeration {
+          enum merge {
+            description
+              "The default operation is merge.";
+          }
+          enum replace {
+            description
+              "The default operation is replace.";
+          }
+          enum none {
+            description
+              "There is no default operation.";
+          }
+        }
+        default "merge";
+        description
+          "The default operation to use.";
+      }
+
+      leaf test-option {
+        if-feature validate;
+        type enumeration {
+          enum test-then-set {
+            description
+              "The server will test and then set if no errors.";
+          }
+          enum set {
+            description
+              "The server will set without a test first.";
+          }
+
+          enum test-only {
+            description
+              "The server will only test and not set, even
+               if there are no errors.";
+          }
+        }
+        default "test-then-set";
+        description
+          "The test option to use.";
+      }
+
+      leaf error-option {
+        type enumeration {
+          enum stop-on-error {
+            description
+              "The server will stop on errors.";
+          }
+          enum continue-on-error {
+            description
+              "The server may continue on errors.";
+          }
+          enum rollback-on-error {
+            description
+              "The server will roll back on errors.
+               This value can only be used if the 'rollback-on-error'
+               feature is supported.";
+          }
+        }
+        default "stop-on-error";
+        description
+          "The error option to use.";
+      }
+
+      choice edit-content {
+        mandatory true;
+        description
+          "The content for the edit operation.";
+
+        cliext:argument-handler org.opendaylight.controller.netconf.cli.reader.custom.EditContentReader;
+
+        anyxml config {
+          description
+            "Inline Config content.";
+          cliext:argument-handler org.opendaylight.controller.netconf.cli.reader.custom.ConfigReader;
+        }
+
+        leaf url {
+          if-feature url;
+          type inet:uri;
+          description
+            "URL-based config content.";
+        }
+      }
+    }
+  }
+
+  rpc copy-config {
+    description
+      "Create or replace an entire configuration datastore with the
+       contents of another complete configuration datastore.";
+
+    reference "RFC 6241, Section 7.3";
+
+    input {
+      container target {
+        description
+          "Particular configuration to copy to.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target of the copy operation.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            if-feature writable-running;
+            type empty;
+            description
+              "The running configuration is the config target.
+               This is optional-to-implement on the server.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config target.";
+          }
+        }
+      }
+
+      container source {
+        description
+          "Particular configuration to copy from.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration source for the copy operation.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config source.";
+          }
+          anyxml config {
+            description
+              "Inline Config content: <config> element.  Represents
+               an entire configuration datastore, not
+               a subset of the running datastore.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc delete-config {
+    description
+      "Delete a configuration datastore.";
+
+    reference "RFC 6241, Section 7.4";
+
+    input {
+      container target {
+        description
+          "Particular configuration to delete.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to delete.";
+
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc lock {
+    description
+      "The lock operation allows the client to lock the configuration
+       system of a device.";
+
+    reference "RFC 6241, Section 7.5";
+
+    input {
+      container target {
+        description
+          "Particular configuration to lock.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to lock.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config target.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc unlock {
+    description
+      "The unlock operation is used to release a configuration lock,
+       previously obtained with the 'lock' operation.";
+
+    reference "RFC 6241, Section 7.6";
+
+    input {
+      container target {
+        description
+          "Particular configuration to unlock.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to unlock.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config target.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc get {
+    description
+      "Retrieve running configuration and device state information.";
+
+    reference "RFC 6241, Section 7.7";
+
+    input {
+      anyxml filter {
+        description
+          "This parameter specifies the portion of the system
+           configuration and state data to retrieve.";
+        nc:get-filter-element-attributes;
+        // TODO this extension should be augmented (anyxml nodes cannot be augmented)
+        cliext:argument-handler org.opendaylight.controller.netconf.cli.reader.custom.FilterReader;
+      }
+    }
+
+    output {
+      anyxml data {
+        description
+          "Copy of the running datastore subset and/or state
+           data that matched the filter criteria (if any).
+           An empty data container indicates that the request did not
+           produce any results.";
+
+       cliext:argument-handler org.opendaylight.controller.netconf.cli.writer.custom.DataWriter;
+
+      }
+    }
+  }
+
+  rpc close-session {
+    description
+      "Request graceful termination of a NETCONF session.";
+
+    reference "RFC 6241, Section 7.8";
+  }
+
+  rpc kill-session {
+    description
+      "Force the termination of a NETCONF session.";
+
+    reference "RFC 6241, Section 7.9";
+
+    input {
+      leaf session-id {
+        type session-id-type;
+        mandatory true;
+        description
+          "Particular session to kill.";
+      }
+    }
+  }
+
+  rpc commit {
+    if-feature candidate;
+
+    description
+      "Commit the candidate configuration as the device's new
+       current configuration.";
+
+    reference "RFC 6241, Section 8.3.4.1";
+
+    input {
+      leaf confirmed {
+        if-feature confirmed-commit;
+        type empty;
+        description
+          "Requests a confirmed commit.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf confirm-timeout {
+        if-feature confirmed-commit;
+        type uint32 {
+          range "1..max";
+        }
+        units "seconds";
+        default "600";   // 10 minutes
+        description
+          "The timeout interval for a confirmed commit.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf persist {
+        if-feature confirmed-commit;
+        type string;
+        description
+          "This parameter is used to make a confirmed commit
+           persistent.  A persistent confirmed commit is not aborted
+           if the NETCONF session terminates.  The only way to abort
+           a persistent confirmed commit is to let the timer expire,
+           or to use the <cancel-commit> operation.
+
+           The value of this parameter is a token that must be given
+           in the 'persist-id' parameter of <commit> or
+           <cancel-commit> operations in order to confirm or cancel
+           the persistent confirmed commit.
+
+           The token should be a random string.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf persist-id {
+        if-feature confirmed-commit;
+        type string;
+        description
+          "This parameter is given in order to commit a persistent
+           confirmed commit.  The value must be equal to the value
+           given in the 'persist' parameter to the <commit> operation.
+           If it does not match, the operation fails with an
+          'invalid-value' error.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+    }
+  }
+
+  rpc discard-changes {
+    if-feature candidate;
+
+    description
+      "Revert the candidate configuration to the current
+       running configuration.";
+    reference "RFC 6241, Section 8.3.4.2";
+  }
+
+  rpc cancel-commit {
+    if-feature confirmed-commit;
+    description
+      "This operation is used to cancel an ongoing confirmed commit.
+       If the confirmed commit is persistent, the parameter
+       'persist-id' must be given, and it must match the value of the
+       'persist' parameter.";
+    reference "RFC 6241, Section 8.4.4.1";
+
+    input {
+      leaf persist-id {
+        type string;
+        description
+          "This parameter is given in order to cancel a persistent
+           confirmed commit.  The value must be equal to the value
+           given in the 'persist' parameter to the <commit> operation.
+           If it does not match, the operation fails with an
+          'invalid-value' error.";
+      }
+    }
+  }
+
+  rpc validate {
+    if-feature validate;
+
+    description
+      "Validates the contents of the specified configuration.";
+
+    reference "RFC 6241, Section 8.6.4.1";
+
+    input {
+      container source {
+        description
+          "Particular configuration to validate.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration source to validate.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config source.";
+          }
+          anyxml config {
+            description
+              "Inline Config content: <config> element.  Represents
+               an entire configuration datastore, not
+               a subset of the running datastore.";
+          }
+        }
+      }
+    }
+  }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/ConsoleIOTestImpl.java b/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/ConsoleIOTestImpl.java
new file mode 100644 (file)
index 0000000..29d7abd
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.netconf.cli;
+
+import java.io.IOException;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.controller.netconf.cli.io.ConsoleIOImpl;
+
+public class ConsoleIOTestImpl extends ConsoleIOImpl {
+
+    Map<String, Deque<String>> inputValues = new HashMap<>();
+    String lastMessage;
+    private final List<ValueForMessage> valuesForMessages;
+
+    public ConsoleIOTestImpl(final Map<String, Deque<String>> inputValues, final List<ValueForMessage> valuesForMessages)
+            throws IOException {
+        super();
+        this.inputValues = inputValues;
+        this.valuesForMessages = valuesForMessages;
+    }
+
+    StringBuilder output = new StringBuilder();
+
+    @Override
+    public String read() throws IOException {
+        final String prompt = buildPrompt();
+        output.append(prompt);
+        System.out.print(prompt);
+
+        String value = inputValues.get(prompt).pollFirst();
+        if (value == null) {
+            value = getValueForLastMessage();
+        }
+
+        value = value != null ? value : "****NO VALUE****";
+
+        output.append(value + "\n");
+        System.out.print(value + "\n");
+        return value;
+    }
+
+    private String getValueForLastMessage() {
+        for (final ValueForMessage valueForMessage : valuesForMessages) {
+            if (containsLastMessageKeyWords(valueForMessage.getKeyWords())) {
+                return valueForMessage.getValue();
+            }
+        }
+        return null;
+    }
+
+    private boolean containsLastMessageKeyWords(final List<String> keyWords) {
+        for (final String keyWord : keyWords) {
+            if (!lastMessage.contains(keyWord)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void write(final CharSequence data) throws IOException {
+        output.append(data);
+        lastMessage = (String) data;
+        System.out.print(data);
+    }
+
+    @Override
+    public void writeLn(final CharSequence data) throws IOException {
+        write(data);
+        output.append("\n");
+        System.out.print("\n");
+    }
+
+    public String getConsoleOutput() {
+        return output.toString();
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/NetconfCliTest.java b/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/NetconfCliTest.java
new file mode 100644 (file)
index 0000000..7d85aa4
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * 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.netconf.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.netconf.cli.io.IOUtil.PROMPT_SUFIX;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.cli.reader.ReadingException;
+import org.opendaylight.controller.netconf.cli.reader.impl.GenericReader;
+import org.opendaylight.controller.netconf.cli.writer.OutFormatter;
+import org.opendaylight.controller.netconf.cli.writer.WriteException;
+import org.opendaylight.controller.netconf.cli.writer.impl.NormalizedNodeWriter;
+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.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+@Ignore
+public class NetconfCliTest {
+
+    private final static YangContextParser parser = new YangParserImpl();
+
+    private static SchemaContext loadSchemaContext(final String resourceDirectory) throws IOException,
+            URISyntaxException {
+        final URI uri = NetconfCliTest.class.getResource(resourceDirectory).toURI();
+        final File testDir = new File(uri);
+        final String[] fileList = testDir.list();
+        final List<File> testFiles = new ArrayList<File>();
+        if (fileList == null) {
+            throw new FileNotFoundException(resourceDirectory);
+        }
+        for (final String fileName : fileList) {
+            if (new File(testDir, fileName).isDirectory() == false) {
+                testFiles.add(new File(testDir, fileName));
+            }
+        }
+        return parser.parseFiles(testFiles);
+    }
+
+    // @Ignore
+    @Test
+    public void cliTest() throws ReadingException, IOException, WriteException, URISyntaxException {
+
+        final SchemaContext schemaContext = loadSchemaContext("/schema-context");
+        assertNotNull(schemaContext);
+
+        final DataSchemaNode cont1 = findTopLevelElement("ns:model1", "2014-05-14", "cont1", schemaContext);
+        final Map<String, Deque<String>> values = new HashMap<>();
+
+        values.put(prompt("/cont1/cont11/lst111/[entry]/lf1111"), value("55", "32"));
+        values.put(prompt("/cont1/cont11/lst111/[entry]"), value("Y", "Y"));
+        values.put(prompt("/cont1/cont11/lst111/[entry]/cont111/lf1112"),
+                value("value for lf1112", "2value for lf1112"));
+        values.put(prompt("/cont1/cont11/lst111/[entry]/cont111/lflst1111"), value("Y", "N", "Y", "N"));
+        values.put(prompt("/cont1/cont11/lst111/[entry]/cont111/lflst1111/[entry]"), value("10", "15", "20", "30"));
+
+        values.put(prompt("/cont1/cont11/lst111"), value("Y", "N"));
+
+        values.put(prompt("/cont1/cont12/chcA"), value("AB"));
+        values.put(prompt("/cont1/cont12/chcA/cont12AB1/lf12AB1"), value("value for lf12AB1"));
+
+        values.put(prompt("/cont1/cont12/lst121/[entry]/lf1211"), value("value for lf12112", "2value for lf12112"));
+        values.put(prompt("/cont1/cont12/lst121/[entry]"), value("Y", "Y"));
+        values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211"), value("Y", "N", "Y", "N"));
+        values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211/[entry]"), value("Y", "Y", "Y", "Y"));
+        values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211/[entry]/lf12111"), value("5", "10", "21", "50"));
+        values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211/[entry]/lf12112"),
+                value("value for lf12112", "2value for lf12112", "3value for lf12112", "4value for lf12112"));
+
+        values.put(prompt("/cont1/cont12/lst121"), value("Y", "N"));
+
+        values.put(prompt("/cont1/cont12/lst122"), value("Y", "N"));
+
+        values.put(prompt("/cont1/lst11"), value("Y", "Y", "N"));
+        values.put(prompt("/cont1/lst11/[entry]"), value("Y", "Y", "Y"));
+        values.put(prompt("/cont1/lst11/[entry]/lf111"),
+                value("1value for lf111", "2value for lf111", "3value for lf111"));
+
+        values.put(prompt("/cont1/cont12/data"), value("<el1><el11>value</el11><el12>value1</el12></el1>"));
+
+        final List<ValueForMessage> valuesForMessages = new ArrayList<>();
+        valuesForMessages.add(new ValueForMessage("Y", "lst111", "[Y|N]"));
+        valuesForMessages.add(new ValueForMessage("Y", "lst121", "[Y|N]"));
+        valuesForMessages.add(new ValueForMessage("Y", "lst11", "[Y|N]"));
+
+        final ConsoleIOTestImpl console = new ConsoleIOTestImpl(values, valuesForMessages);
+
+        final List<Node<?>> redData = new GenericReader(console, new CommandArgHandlerRegistry(console,
+                new SchemaContextRegistry(schemaContext)), schemaContext).read(cont1);
+        assertNotNull(redData);
+       assertEquals(1, redData.size());
+
+        assertTrue(redData.get(0) instanceof CompositeNode);
+        final CompositeNode redTopLevelNode = (CompositeNode) redData.get(0);
+
+        System.out.println("============================");
+        new NormalizedNodeWriter(console, new OutFormatter()).write(cont1, redData);
+
+    }
+
+    private Deque<String> value(final String... values) {
+        return new ArrayDeque<>(Arrays.asList(values));
+    }
+
+    private String prompt(final String path) {
+        return "/localhost" + path + PROMPT_SUFIX;
+    }
+
+    private DataSchemaNode findTopLevelElement(final String namespace, final String revision,
+            final String topLevelElement, final SchemaContext schemaContext) {
+        final QName requiredElement = QName.create(namespace, revision, topLevelElement);
+        for (final DataSchemaNode dataSchemaNode : schemaContext.getChildNodes()) {
+            if (dataSchemaNode.getQName().equals(requiredElement)) {
+                return dataSchemaNode;
+            }
+        }
+        return null;
+
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/ValueForMessages.java b/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/ValueForMessages.java
new file mode 100644 (file)
index 0000000..2532b36
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.netconf.cli;
+
+import java.util.Arrays;
+import java.util.List;
+
+class ValueForMessage {
+    List<String> messageKeyWords;
+    String value;
+
+    public ValueForMessage(final String value, final String... messageKeyWords) {
+        this.messageKeyWords = Arrays.asList(messageKeyWords);
+        this.value = value;
+    }
+
+    public List<String> getKeyWords() {
+        return messageKeyWords;
+    }
+
+    public String getValue() {
+        return value;
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/io/IOUtilTest.java b/opendaylight/netconf/netconf-cli/src/test/java/org/opendaylight/controller/netconf/cli/io/IOUtilTest.java
new file mode 100644 (file)
index 0000000..2021bf7
--- /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.netconf.cli.io;
+
+import com.google.common.collect.Maps;
+import java.util.Map;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.cli.commands.CommandConstants;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class IOUtilTest {
+
+    @Test
+    public void testQNameFromKeyStringNew() throws Exception {
+        final String s = IOUtil.qNameToKeyString(CommandConstants.HELP_QNAME, "module");
+        final Map<String, QName> modulesMap = Maps.newHashMap();
+        modulesMap.put("module", new QName(CommandConstants.HELP_QNAME, "module"));
+        final QName qName = IOUtil.qNameFromKeyString(s, modulesMap);
+        Assert.assertEquals(CommandConstants.HELP_QNAME, qName);
+    }
+}
diff --git a/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/ietf-inet-types.yang b/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/ietf-inet-types.yang
new file mode 100644 (file)
index 0000000..de20feb
--- /dev/null
@@ -0,0 +1,418 @@
+ module ietf-inet-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+   prefix "inet";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types for Internet addresses and related things.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef ip-version {
+     type enumeration {
+       enum unknown {
+         value "0";
+         description
+          "An unknown or unspecified version of the Internet protocol.";
+       }
+       enum ipv4 {
+         value "1";
+         description
+          "The IPv4 protocol as defined in RFC 791.";
+       }
+       enum ipv6 {
+         value "2";
+         description
+          "The IPv6 protocol as defined in RFC 2460.";
+       }
+     }
+     description
+      "This value represents the version of the IP protocol.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetVersion textual convention of the SMIv2.";
+     reference
+      "RFC  791: Internet Protocol
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   typedef dscp {
+     type uint8 {
+       range "0..63";
+     }
+     description
+      "The dscp type represents a Differentiated Services Code-Point
+       that may be used for marking packets in a traffic stream.
+
+       In the value set and its semantics, this type is equivalent
+       to the Dscp textual convention of the SMIv2.";
+     reference
+      "RFC 3289: Management Information Base for the Differentiated
+                 Services Architecture
+       RFC 2474: Definition of the Differentiated Services Field
+                 (DS Field) in the IPv4 and IPv6 Headers
+       RFC 2780: IANA Allocation Guidelines For Values In
+                 the Internet Protocol and Related Headers";
+   }
+
+   typedef ipv6-flow-label {
+     type uint32 {
+       range "0..1048575";
+     }
+     description
+      "The flow-label type represents flow identifier or Flow Label
+       in an IPv6 packet header that may be used to discriminate
+       traffic flows.
+
+       In the value set and its semantics, this type is equivalent
+       to the IPv6FlowLabel textual convention of the SMIv2.";
+     reference
+      "RFC 3595: Textual Conventions for IPv6 Flow Label
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+   }
+
+   typedef port-number {
+     type uint16 {
+       range "0..65535";
+     }
+     description
+      "The port-number type represents a 16-bit port number of an
+       Internet transport layer protocol such as UDP, TCP, DCCP, or
+       SCTP.  Port numbers are assigned by IANA.  A current list of
+       all assignments is available from <http://www.iana.org/>.
+
+       Note that the port number value zero is reserved by IANA.  In
+       situations where the value zero does not make sense, it can
+       be excluded by subtyping the port-number type.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetPortNumber textual convention of the SMIv2.";
+     reference
+      "RFC  768: User Datagram Protocol
+       RFC  793: Transmission Control Protocol
+       RFC 4960: Stream Control Transmission Protocol
+       RFC 4340: Datagram Congestion Control Protocol (DCCP)
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of autonomous system related types ***/
+
+   typedef as-number {
+     type uint32;
+     description
+      "The as-number type represents autonomous system numbers
+       which identify an Autonomous System (AS).  An AS is a set
+       of routers under a single technical administration, using
+       an interior gateway protocol and common metrics to route
+       packets within the AS, and using an exterior gateway
+       protocol to route packets to other ASs'.  IANA maintains
+       the AS number space and has delegated large parts to the
+       regional registries.
+
+       Autonomous system numbers were originally limited to 16
+       bits.  BGP extensions have enlarged the autonomous system
+       number space to 32 bits.  This type therefore uses an uint32
+       base type without a range restriction in order to support
+       a larger autonomous system number space.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetAutonomousSystemNumber textual convention of
+       the SMIv2.";
+     reference
+      "RFC 1930: Guidelines for creation, selection, and registration
+                 of an Autonomous System (AS)
+       RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+       RFC 4893: BGP Support for Four-octet AS Number Space
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of IP address and hostname related types ***/
+
+   typedef ip-address {
+     type union {
+       type inet:ipv4-address;
+       type inet:ipv6-address;
+     }
+     description
+      "The ip-address type represents an IP address and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+     description
+       "The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format";
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+     description
+      "The ipv6-address type represents an IPv6 address in full,
+       mixed, shortened, and shortened-mixed notation.  The IPv6
+       address may include a zone index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format of IPv6 addresses uses the compressed
+       format described in RFC 4291, Section 2.2, item 2 with the
+       following additional rules: the :: substitution must be
+       applied to the longest sequence of all-zero 16-bit chunks
+       in an IPv6 address.  If there is a tie, the first sequence
+       of all-zero 16-bit chunks is replaced by ::.  Single
+       all-zero 16-bit chunks are not compressed.  The canonical
+       format uses lowercase characters and leading zeros are
+       not allowed.  The canonical format for the zone index is
+       the numerical format as described in RFC 4007, Section
+       11.2.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text Representation";
+   }
+
+   typedef ip-prefix {
+     type union {
+       type inet:ipv4-prefix;
+       type inet:ipv6-prefix;
+     }
+     description
+      "The ip-prefix type represents an IP prefix and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-prefix {
+     type string {
+       pattern
+          '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+        +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+        + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+     }
+     description
+      "The ipv4-prefix type represents an IPv4 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal to 32.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The canonical format of an IPv4 prefix has all bits of
+       the IPv4 address set to zero that are not part of the
+       IPv4 prefix.";
+   }
+
+   typedef ipv6-prefix {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(/.+)';
+     }
+     description
+      "The ipv6-prefix type represents an IPv6 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal 128.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The IPv6 address should have all bits that do not belong
+       to the prefix set to zero.
+
+       The canonical format of an IPv6 prefix has all bits of
+       the IPv6 address set to zero that are not part of the
+       IPv6 prefix.  Furthermore, IPv6 address is represented
+       in the compressed format described in RFC 4291, Section
+       2.2, item 2 with the following additional rules: the ::
+       substitution must be applied to the longest sequence of
+       all-zero 16-bit chunks in an IPv6 address.  If there is
+       a tie, the first sequence of all-zero 16-bit chunks is
+       replaced by ::.  Single all-zero 16-bit chunks are not
+       compressed.  The canonical format uses lowercase
+       characters and leading zeros are not allowed.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+   }
+
+   /*** collection of domain name and URI types ***/
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+     description
+      "The domain-name type represents a DNS domain name.  The
+       name SHOULD be fully qualified whenever possible.
+
+       Internet domain names are only loosely specified.  Section
+       3.5 of RFC 1034 recommends a syntax (modified in Section
+       2.1 of RFC 1123).  The pattern above is intended to allow
+       for current practice in domain name use, and some possible
+       future expansion.  It is designed to hold various types of
+       domain names, including names used for A or AAAA records
+       (host names) and other records, such as SRV records.  Note
+       that Internet host names have a stricter syntax (described
+       in RFC 952) than the DNS recommendations in RFCs 1034 and
+       1123, and that systems that want to store host names in
+       schema nodes using the domain-name type are recommended to
+       adhere to this stricter standard to ensure interoperability.
+
+       The encoding of DNS names in the DNS protocol is limited
+       to 255 characters.  Since the encoding consists of labels
+       prefixed by a length bytes and there is a trailing NULL
+       byte, only 253 characters can appear in the textual dotted
+       notation.
+
+       The description clause of schema nodes using the domain-name
+       type MUST describe when and how these names are resolved to
+       IP addresses.  Note that the resolution of a domain-name value
+       may require to query multiple DNS records (e.g., A for IPv4
+       and AAAA for IPv6).  The order of the resolution process and
+       which DNS record takes precedence can either be defined
+       explicitely or it may depend on the configuration of the
+       resolver.
+
+       Domain-name values use the US-ASCII encoding.  Their canonical
+       format uses lowercase US-ASCII characters.  Internationalized
+       domain names MUST be encoded in punycode as described in RFC
+       3492";
+     reference
+      "RFC  952: DoD Internet Host Table Specification
+       RFC 1034: Domain Names - Concepts and Facilities
+       RFC 1123: Requirements for Internet Hosts -- Application
+                 and Support
+       RFC 2782: A DNS RR for specifying the location of services
+                 (DNS SRV)
+       RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                 Internationalized Domain Names in Applications
+                 (IDNA)
+       RFC 5891: Internationalizing Domain Names in Applications
+                 (IDNA): Protocol";
+   }
+
+   typedef host {
+     type union {
+       type inet:ip-address;
+       type inet:domain-name;
+     }
+     description
+      "The host type represents either an IP address or a DNS
+       domain name.";
+   }
+
+   typedef uri {
+     type string;
+     description
+      "The uri type represents a Uniform Resource Identifier
+       (URI) as defined by STD 66.
+
+       Objects using the uri type MUST be in US-ASCII encoding,
+       and MUST be normalized as described by RFC 3986 Sections
+       6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+       percent-encoding is removed, and all case-insensitive
+       characters are set to lowercase except for hexadecimal
+       digits, which are normalized to uppercase as described in
+       Section 6.2.2.1.
+
+       The purpose of this normalization is to help provide
+       unique URIs.  Note that this normalization is not
+       sufficient to provide uniqueness.  Two URIs that are
+       textually distinct after this normalization may still be
+       equivalent.
+
+       Objects using the uri type may restrict the schemes that
+       they permit.  For example, 'data:' and 'urn:' schemes
+       might not be appropriate.
+
+       A zero-length URI is not a valid URI.  This can be used to
+       express 'URI absent' where required.
+
+       In the value set and its semantics, this type is equivalent
+       to the Uri SMIv2 textual convention defined in RFC 5017.";
+     reference
+      "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+       RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                 Group: Uniform Resource Identifiers (URIs), URLs,
+                 and Uniform Resource Names (URNs): Clarifications
+                 and Recommendations
+       RFC 5017: MIB Textual Conventions for Uniform Resource
+                 Identifiers (URIs)";
+   }
+
+ }
diff --git a/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/ietf-netconf.yang b/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/ietf-netconf.yang
new file mode 100644 (file)
index 0000000..44c19c3
--- /dev/null
@@ -0,0 +1,927 @@
+module ietf-netconf {
+
+  // the namespace for NETCONF XML definitions is unchanged
+  // from RFC 4741, which this document replaces
+  namespace "urn:ietf:params:xml:ns:netconf:base:1.0";
+
+  prefix nc;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "WG Web:   <http://tools.ietf.org/wg/netconf/>
+     WG List:  <netconf@ietf.org>
+
+     WG Chair: Bert Wijnen
+               <bertietf@bwijnen.net>
+
+     WG Chair: Mehmet Ersue
+               <mehmet.ersue@nsn.com>
+
+     Editor:   Martin Bjorklund
+               <mbj@tail-f.com>
+
+     Editor:   Juergen Schoenwaelder
+               <j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Andy Bierman
+               <andy.bierman@brocade.com>";
+  description
+    "NETCONF Protocol Data Types and Protocol Operations.
+
+     Copyright (c) 2011 IETF Trust and the persons identified as
+     the document authors.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6241; see
+     the RFC itself for full legal notices.";
+  revision 2011-06-01 {
+    description
+      "Initial revision";
+    reference
+      "RFC 6241: Network Configuration Protocol";
+  }
+
+  extension get-filter-element-attributes {
+    description
+      "If this extension is present within an 'anyxml'
+       statement named 'filter', which must be conceptually
+       defined within the RPC input section for the <get>
+       and <get-config> protocol operations, then the
+       following unqualified XML attribute is supported
+       within the <filter> element, within a <get> or
+       <get-config> protocol operation:
+
+         type : optional attribute with allowed
+                value strings 'subtree' and 'xpath'.
+                If missing, the default value is 'subtree'.
+
+       If the 'xpath' feature is supported, then the
+       following unqualified XML attribute is
+       also supported:
+
+         select: optional attribute containing a
+                 string representing an XPath expression.
+                 The 'type' attribute must be equal to 'xpath'
+                 if this attribute is present.";
+  }
+
+  // NETCONF capabilities defined as features
+  feature writable-running {
+    description
+      "NETCONF :writable-running capability;
+       If the server advertises the :writable-running
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.2";
+  }
+
+  feature candidate {
+    description
+      "NETCONF :candidate capability;
+       If the server advertises the :candidate
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.3";
+  }
+
+  feature confirmed-commit {
+    if-feature candidate;
+    description
+      "NETCONF :confirmed-commit:1.1 capability;
+       If the server advertises the :confirmed-commit:1.1
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+
+    reference "RFC 6241, Section 8.4";
+  }
+
+  feature rollback-on-error {
+    description
+      "NETCONF :rollback-on-error capability;
+       If the server advertises the :rollback-on-error
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.5";
+  }
+
+  feature validate {
+    description
+      "NETCONF :validate:1.1 capability;
+       If the server advertises the :validate:1.1
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.6";
+  }
+
+  feature startup {
+    description
+      "NETCONF :startup capability;
+       If the server advertises the :startup
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.7";
+  }
+
+  feature url {
+    description
+      "NETCONF :url capability;
+       If the server advertises the :url
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.8";
+  }
+
+  feature xpath {
+    description
+      "NETCONF :xpath capability;
+       If the server advertises the :xpath
+       capability for a session, then this feature must
+       also be enabled for that session.  Otherwise,
+       this feature must not be enabled.";
+    reference "RFC 6241, Section 8.9";
+  }
+
+  // NETCONF Simple Types
+
+  typedef session-id-type {
+    type uint32 {
+      range "1..max";
+    }
+    description
+      "NETCONF Session Id";
+  }
+
+  typedef session-id-or-zero-type {
+    type uint32;
+    description
+      "NETCONF Session Id or Zero to indicate none";
+  }
+  typedef error-tag-type {
+    type enumeration {
+       enum in-use {
+         description
+           "The request requires a resource that
+            already is in use.";
+       }
+       enum invalid-value {
+         description
+           "The request specifies an unacceptable value for one
+            or more parameters.";
+       }
+       enum too-big {
+         description
+           "The request or response (that would be generated) is
+            too large for the implementation to handle.";
+       }
+       enum missing-attribute {
+         description
+           "An expected attribute is missing.";
+       }
+       enum bad-attribute {
+         description
+           "An attribute value is not correct; e.g., wrong type,
+            out of range, pattern mismatch.";
+       }
+       enum unknown-attribute {
+         description
+           "An unexpected attribute is present.";
+       }
+       enum missing-element {
+         description
+           "An expected element is missing.";
+       }
+       enum bad-element {
+         description
+           "An element value is not correct; e.g., wrong type,
+            out of range, pattern mismatch.";
+       }
+       enum unknown-element {
+         description
+           "An unexpected element is present.";
+       }
+       enum unknown-namespace {
+         description
+           "An unexpected namespace is present.";
+       }
+       enum access-denied {
+         description
+           "Access to the requested protocol operation or
+            data model is denied because authorization failed.";
+       }
+       enum lock-denied {
+         description
+           "Access to the requested lock is denied because the
+            lock is currently held by another entity.";
+       }
+       enum resource-denied {
+         description
+           "Request could not be completed because of
+            insufficient resources.";
+       }
+       enum rollback-failed {
+         description
+           "Request to roll back some configuration change (via
+            rollback-on-error or <discard-changes> operations)
+            was not completed for some reason.";
+
+       }
+       enum data-exists {
+         description
+           "Request could not be completed because the relevant
+            data model content already exists.  For example,
+            a 'create' operation was attempted on data that
+            already exists.";
+       }
+       enum data-missing {
+         description
+           "Request could not be completed because the relevant
+            data model content does not exist.  For example,
+            a 'delete' operation was attempted on
+            data that does not exist.";
+       }
+       enum operation-not-supported {
+         description
+           "Request could not be completed because the requested
+            operation is not supported by this implementation.";
+       }
+       enum operation-failed {
+         description
+           "Request could not be completed because the requested
+            operation failed for some reason not covered by
+            any other error condition.";
+       }
+       enum partial-operation {
+         description
+           "This error-tag is obsolete, and SHOULD NOT be sent
+            by servers conforming to this document.";
+       }
+       enum malformed-message {
+         description
+           "A message could not be handled because it failed to
+            be parsed correctly.  For example, the message is not
+            well-formed XML or it uses an invalid character set.";
+       }
+     }
+     description "NETCONF Error Tag";
+     reference "RFC 6241, Appendix A";
+  }
+
+  typedef error-severity-type {
+    type enumeration {
+      enum error {
+        description "Error severity";
+      }
+      enum warning {
+        description "Warning severity";
+      }
+    }
+    description "NETCONF Error Severity";
+    reference "RFC 6241, Section 4.3";
+  }
+
+  typedef edit-operation-type {
+    type enumeration {
+      enum merge {
+        description
+          "The configuration data identified by the
+           element containing this attribute is merged
+           with the configuration at the corresponding
+           level in the configuration datastore identified
+           by the target parameter.";
+      }
+      enum replace {
+        description
+          "The configuration data identified by the element
+           containing this attribute replaces any related
+           configuration in the configuration datastore
+           identified by the target parameter.  If no such
+           configuration data exists in the configuration
+           datastore, it is created.  Unlike a
+           <copy-config> operation, which replaces the
+           entire target configuration, only the configuration
+           actually present in the config parameter is affected.";
+      }
+      enum create {
+        description
+          "The configuration data identified by the element
+           containing this attribute is added to the
+           configuration if and only if the configuration
+           data does not already exist in the configuration
+           datastore.  If the configuration data exists, an
+           <rpc-error> element is returned with an
+           <error-tag> value of 'data-exists'.";
+      }
+      enum delete {
+        description
+          "The configuration data identified by the element
+           containing this attribute is deleted from the
+           configuration if and only if the configuration
+           data currently exists in the configuration
+           datastore.  If the configuration data does not
+           exist, an <rpc-error> element is returned with
+           an <error-tag> value of 'data-missing'.";
+      }
+      enum remove {
+        description
+          "The configuration data identified by the element
+           containing this attribute is deleted from the
+           configuration if the configuration
+           data currently exists in the configuration
+           datastore.  If the configuration data does not
+           exist, the 'remove' operation is silently ignored
+           by the server.";
+      }
+    }
+    default "merge";
+    description "NETCONF 'operation' attribute values";
+    reference "RFC 6241, Section 7.2";
+  }
+
+  // NETCONF Standard Protocol Operations
+
+  rpc get-config {
+    description
+      "Retrieve all or part of a specified configuration.";
+
+    reference "RFC 6241, Section 7.1";
+
+    input {
+      container source {
+        description
+          "Particular configuration to retrieve.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration to retrieve.";
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.
+               This is optional-to-implement on the server because
+               not all servers will support filtering for this
+               datastore.";
+          }
+        }
+      }
+
+      anyxml filter {
+        description
+          "Subtree or XPath filter to use.";
+        nc:get-filter-element-attributes;
+      }
+    }
+
+    output {
+      anyxml data {
+        description
+          "Copy of the source datastore subset that matched
+           the filter criteria (if any).  An empty data container
+           indicates that the request did not produce any results.";
+      }
+    }
+  }
+
+  rpc edit-config {
+    description
+      "The <edit-config> operation loads all or part of a specified
+       configuration to the specified target configuration.";
+
+    reference "RFC 6241, Section 7.2";
+
+    input {
+      container target {
+        description
+          "Particular configuration to edit.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            if-feature writable-running;
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+        }
+      }
+
+      leaf default-operation {
+        type enumeration {
+          enum merge {
+            description
+              "The default operation is merge.";
+          }
+          enum replace {
+            description
+              "The default operation is replace.";
+          }
+          enum none {
+            description
+              "There is no default operation.";
+          }
+        }
+        default "merge";
+        description
+          "The default operation to use.";
+      }
+
+      leaf test-option {
+        if-feature validate;
+        type enumeration {
+          enum test-then-set {
+            description
+              "The server will test and then set if no errors.";
+          }
+          enum set {
+            description
+              "The server will set without a test first.";
+          }
+
+          enum test-only {
+            description
+              "The server will only test and not set, even
+               if there are no errors.";
+          }
+        }
+        default "test-then-set";
+        description
+          "The test option to use.";
+      }
+
+      leaf error-option {
+        type enumeration {
+          enum stop-on-error {
+            description
+              "The server will stop on errors.";
+          }
+          enum continue-on-error {
+            description
+              "The server may continue on errors.";
+          }
+          enum rollback-on-error {
+            description
+              "The server will roll back on errors.
+               This value can only be used if the 'rollback-on-error'
+               feature is supported.";
+          }
+        }
+        default "stop-on-error";
+        description
+          "The error option to use.";
+      }
+
+      choice edit-content {
+        mandatory true;
+        description
+          "The content for the edit operation.";
+
+        anyxml config {
+          description
+            "Inline Config content.";
+        }
+        leaf url {
+          if-feature url;
+          type inet:uri;
+          description
+            "URL-based config content.";
+        }
+      }
+    }
+  }
+
+  rpc copy-config {
+    description
+      "Create or replace an entire configuration datastore with the
+       contents of another complete configuration datastore.";
+
+    reference "RFC 6241, Section 7.3";
+
+    input {
+      container target {
+        description
+          "Particular configuration to copy to.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target of the copy operation.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            if-feature writable-running;
+            type empty;
+            description
+              "The running configuration is the config target.
+               This is optional-to-implement on the server.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config target.";
+          }
+        }
+      }
+
+      container source {
+        description
+          "Particular configuration to copy from.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration source for the copy operation.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config source.";
+          }
+          anyxml config {
+            description
+              "Inline Config content: <config> element.  Represents
+               an entire configuration datastore, not
+               a subset of the running datastore.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc delete-config {
+    description
+      "Delete a configuration datastore.";
+
+    reference "RFC 6241, Section 7.4";
+
+    input {
+      container target {
+        description
+          "Particular configuration to delete.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to delete.";
+
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc lock {
+    description
+      "The lock operation allows the client to lock the configuration
+       system of a device.";
+
+    reference "RFC 6241, Section 7.5";
+
+    input {
+      container target {
+        description
+          "Particular configuration to lock.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to lock.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config target.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc unlock {
+    description
+      "The unlock operation is used to release a configuration lock,
+       previously obtained with the 'lock' operation.";
+
+    reference "RFC 6241, Section 7.6";
+
+    input {
+      container target {
+        description
+          "Particular configuration to unlock.";
+
+        choice config-target {
+          mandatory true;
+          description
+            "The configuration target to unlock.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config target.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config target.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config target.";
+          }
+        }
+      }
+    }
+  }
+
+  rpc get {
+    description
+      "Retrieve running configuration and device state information.";
+
+    reference "RFC 6241, Section 7.7";
+
+    input {
+      anyxml filter {
+        description
+          "This parameter specifies the portion of the system
+           configuration and state data to retrieve.";
+        nc:get-filter-element-attributes;
+      }
+    }
+
+    output {
+      anyxml data {
+        description
+          "Copy of the running datastore subset and/or state
+           data that matched the filter criteria (if any).
+           An empty data container indicates that the request did not
+           produce any results.";
+      }
+    }
+  }
+
+  rpc close-session {
+    description
+      "Request graceful termination of a NETCONF session.";
+
+    reference "RFC 6241, Section 7.8";
+  }
+
+  rpc kill-session {
+    description
+      "Force the termination of a NETCONF session.";
+
+    reference "RFC 6241, Section 7.9";
+
+    input {
+      leaf session-id {
+        type session-id-type;
+        mandatory true;
+        description
+          "Particular session to kill.";
+      }
+    }
+  }
+
+  rpc commit {
+    if-feature candidate;
+
+    description
+      "Commit the candidate configuration as the device's new
+       current configuration.";
+
+    reference "RFC 6241, Section 8.3.4.1";
+
+    input {
+      leaf confirmed {
+        if-feature confirmed-commit;
+        type empty;
+        description
+          "Requests a confirmed commit.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf confirm-timeout {
+        if-feature confirmed-commit;
+        type uint32 {
+          range "1..max";
+        }
+        units "seconds";
+        default "600";   // 10 minutes
+        description
+          "The timeout interval for a confirmed commit.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf persist {
+        if-feature confirmed-commit;
+        type string;
+        description
+          "This parameter is used to make a confirmed commit
+           persistent.  A persistent confirmed commit is not aborted
+           if the NETCONF session terminates.  The only way to abort
+           a persistent confirmed commit is to let the timer expire,
+           or to use the <cancel-commit> operation.
+
+           The value of this parameter is a token that must be given
+           in the 'persist-id' parameter of <commit> or
+           <cancel-commit> operations in order to confirm or cancel
+           the persistent confirmed commit.
+
+           The token should be a random string.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+      leaf persist-id {
+        if-feature confirmed-commit;
+        type string;
+        description
+          "This parameter is given in order to commit a persistent
+           confirmed commit.  The value must be equal to the value
+           given in the 'persist' parameter to the <commit> operation.
+           If it does not match, the operation fails with an
+          'invalid-value' error.";
+        reference "RFC 6241, Section 8.3.4.1";
+      }
+
+    }
+  }
+
+  rpc discard-changes {
+    if-feature candidate;
+
+    description
+      "Revert the candidate configuration to the current
+       running configuration.";
+    reference "RFC 6241, Section 8.3.4.2";
+  }
+
+  rpc cancel-commit {
+    if-feature confirmed-commit;
+    description
+      "This operation is used to cancel an ongoing confirmed commit.
+       If the confirmed commit is persistent, the parameter
+       'persist-id' must be given, and it must match the value of the
+       'persist' parameter.";
+    reference "RFC 6241, Section 8.4.4.1";
+
+    input {
+      leaf persist-id {
+        type string;
+        description
+          "This parameter is given in order to cancel a persistent
+           confirmed commit.  The value must be equal to the value
+           given in the 'persist' parameter to the <commit> operation.
+           If it does not match, the operation fails with an
+          'invalid-value' error.";
+      }
+    }
+  }
+
+  rpc validate {
+    if-feature validate;
+
+    description
+      "Validates the contents of the specified configuration.";
+
+    reference "RFC 6241, Section 8.6.4.1";
+
+    input {
+      container source {
+        description
+          "Particular configuration to validate.";
+
+        choice config-source {
+          mandatory true;
+          description
+            "The configuration source to validate.";
+
+          leaf candidate {
+            if-feature candidate;
+            type empty;
+            description
+              "The candidate configuration is the config source.";
+          }
+          leaf running {
+            type empty;
+            description
+              "The running configuration is the config source.";
+          }
+          leaf startup {
+            if-feature startup;
+            type empty;
+            description
+              "The startup configuration is the config source.";
+          }
+          leaf url {
+            if-feature url;
+            type inet:uri;
+            description
+              "The URL-based configuration is the config source.";
+          }
+          anyxml config {
+            description
+              "Inline Config content: <config> element.  Represents
+               an entire configuration datastore, not
+               a subset of the running datastore.";
+          }
+        }
+      }
+    }
+  }
+
+}
diff --git a/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/model1.yang b/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/model1.yang
new file mode 100644 (file)
index 0000000..c84d55f
--- /dev/null
@@ -0,0 +1,74 @@
+module model1 {
+  namespace "ns:model1";
+  prefix "mod1";
+
+  revision "2014-05-14" {
+  }
+
+  container cont1 {
+    container cont11 {
+        list lst111 {
+            key lf1111;
+            leaf lf1111 {
+                type int32;
+            }
+            container cont111 {
+                leaf lf1112 {
+                    type string;
+                }
+                leaf-list lflst1111 {
+                    type int8;
+                }
+            }
+        }
+    }
+
+    container cont12 {
+        list lst121 {
+            key lf1211;
+            leaf lf1211 {
+                type string;
+            }
+            list lst1211 {
+                leaf lf12111 {
+                    type uint8;
+                }
+                leaf lf12112 {
+                    type string;
+                }
+            }
+        }
+        choice chcA {
+            case AA {
+                leaf lf12AA1 {
+                    type string;
+                }
+            }
+            case AB {
+                container cont12AB1 {
+                    leaf lf12AB1 {
+                        type string;
+                    }
+                }
+            }
+            leaf lf121 { //should be standalone case
+                type string;
+            }
+        }
+        list lst122 {
+        }
+    }
+  }
+
+  container cont2 {
+    container cont23 {
+    }
+  }
+
+  container contA {
+  }
+
+  container contB {
+  }
+
+}
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/model2.yang b/opendaylight/netconf/netconf-cli/src/test/resources/schema-context/model2.yang
new file mode 100644 (file)
index 0000000..e92cbd7
--- /dev/null
@@ -0,0 +1,32 @@
+module model2 {
+  namespace "ns:model2";
+  prefix "mod2";
+
+  import model1 {prefix model1; revision-date 2014-05-14;}
+
+  revision "2014-05-14" {
+  }
+
+  container contA {
+  }
+
+  container contB {
+  }
+
+  augment "/model1:cont2" {
+    container cont21 {
+    }
+
+    container cont22 {
+    }
+  }
+
+  augment "/model1:cont1" {
+    list lst11 {
+       leaf lf111 {
+        type string;
+       }
+    }
+  }
+
+}
\ No newline at end of file
index f46d14903323ff8f891da7ff025d5e50cc926c1b..bf27ed6f4dbadab127dc4e3e876676018df2a180 100644 (file)
@@ -72,7 +72,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>
index eaa3589e66d32c6e448c12ee6b04e60ca457dfdd..004a22f6948c570e96fc880ea764b366c8cbfd94 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessage
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public final class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
+public class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
     private final Collection<String> capabilities;
index bb6ea61a25b5fa51e56af04af1b01f533205df18..971ea39ade5b6fb57d07a041f999ec18890528df 100644 (file)
@@ -15,19 +15,22 @@ 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.api.xml.XmlNetconfConstants;
 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.xml.XMLNetconfUtil;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 4c993acf58f3e8640d3aea09468ea0283134a903..3b1de348ff86858884d27a6436ddc0c0d62692fb 100644 (file)
@@ -11,16 +11,18 @@ package org.opendaylight.controller.netconf.client;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
+
 import io.netty.channel.Channel;
 import io.netty.util.Timer;
 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.api.xml.XmlNetconfConstants;
 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.xml.XmlNetconfConstants;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.opendaylight.protocol.framework.SessionNegotiator;
 import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
index c60506ef447d821d5458dbb399c30a1ab0e94325..c6544466d4ea2ae49904ce1787adb4823070d166 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>ietf-netconf-monitoring-extension</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <!-- compile dependencies -->
     <dependency>
@@ -81,7 +80,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-client</artifactId>
-      <version>${project.version}</version>
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.impl.osgi.NetconfImplActivator</Bundle-Activator>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>
index 54ad18a1dec7a61b2159a5b854d70084bbab0018..4f2f65c1a00732137229fba7e1416d9c1db70904 100644 (file)
@@ -11,16 +11,17 @@ package org.opendaylight.controller.netconf.impl;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
+
 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.NetconfTerminationReason;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
 import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil;
 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;
index d5a34d11b244681b1540ff95bae22b26ba607670..487ffd6e5dc2d8f5e7dbd13db1402b3d7e0559a7 100644 (file)
@@ -12,16 +12,17 @@ import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationPr
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
+
 import java.util.Set;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.opendaylight.protocol.framework.SessionNegotiator;
 import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
@@ -31,6 +32,7 @@ import com.google.common.collect.Sets;
 import io.netty.channel.Channel;
 import io.netty.util.Timer;
 import io.netty.util.concurrent.Promise;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
index bfc7df5926de706dd3bd12d5e046dc158dd170c8..6e8158413388d555e9d102354854f684f336d733 100644 (file)
@@ -11,9 +11,9 @@ package org.opendaylight.controller.netconf.impl;
 import com.google.common.base.Optional;
 import java.io.IOException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation.OperationNameAndNamespace;
 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;
index f31233987e97531a563fca3f186fee480e6b6616..b7a98bae83acae9a1ee0f525a015db251c998f3e 100644 (file)
@@ -9,9 +9,9 @@
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;
 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.w3c.dom.Document;
 import org.w3c.dom.Element;
index d4545430b47834ae8604737a50762056fd712526..67b782c7c1d7666a32f78fe08f0ff77d5dd9f17e 100644 (file)
@@ -9,7 +9,9 @@
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
@@ -17,7 +19,6 @@ import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 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;
index beceb8d008cb6e6b61662cf16f6ea32bd31981ed..6db74eaba2ec0aba6efb421b40e12e735709edde 100644 (file)
@@ -10,12 +10,13 @@ package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
 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;
index b9b30a5eaaa2b52b4967e102e373a578cf08b2ea..cccb1a3ac362e35c6f0efcd5836b3c5a51e1a320 100644 (file)
@@ -11,12 +11,12 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;\r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;\r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;\r
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.api.NetconfMessage;\r
 import org.opendaylight.controller.netconf.impl.NetconfServerSession;\r
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;\r
 import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
 import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
index 22caeff071c44939f309d84c8187f2034172bd04..2a24ae32fa0cad9bef292cd53cc8718424692b7c 100644 (file)
@@ -8,10 +8,10 @@
 package org.opendaylight.controller.netconf.impl.mapping.operations;\r
 \r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.impl.NetconfServerSession;\r
 import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
 import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
index ea2bb9c34e4801f5c66b33ef108110602ba5c60b..c5281d01f841263d5f1258975ee85764565a111d 100644 (file)
@@ -18,11 +18,13 @@ 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;
@@ -40,6 +42,7 @@ 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;
@@ -50,6 +53,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
@@ -68,7 +72,6 @@ import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExi
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
 import org.slf4j.Logger;
index c40dfe7fc32208c73251c9a483d7f5feaed48eaf..0e9589d2d21b0bde118440a1a0c683e1bedf3fd5 100644 (file)
@@ -10,9 +10,6 @@
 
   <artifactId>netconf-it</artifactId>
   <name>${project.artifactId}</name>
-  <properties>
-    <tinybundles.version>2.0.0</tinybundles.version>
-  </properties>
 
   <dependencies>
     <dependency>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
-        <version>1.2.4</version>
         <executions>
           <execution>
             <id>generate-config</id>
index 148b0446e309f4470f55ee0205e7be6cd429499d..f7091beba5fcb09f26cb1248dbdfdd52d600db77 100644 (file)
@@ -143,8 +143,8 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
         }
 
         notificationVerifier.assertNotificationCount(2);
-        notificationVerifier.assertNotificationContent(0, 0, 0, 9);
-        notificationVerifier.assertNotificationContent(1, 4, 3, 9);
+        notificationVerifier.assertNotificationContent(0, 0, 0, 8);
+        notificationVerifier.assertNotificationContent(1, 4, 3, 8);
 
         mockedAggregator.assertSnapshotCount(2);
         // Capabilities are stripped for persister
index c277e20553fb3ed469c9f849d624f795f0acf635..fa78fa4bd3983c7eee4cb166e54bc5692f0bad54 100644 (file)
@@ -8,15 +8,16 @@
 package org.opendaylight.controller.netconf.monitoring;
 
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.monitoring.xml.JaxBSerializer;
 import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 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;
index f0e1b3f51fd1abdb445bc33f221f1e90aff1a6dc..c770bde9206c03bba89027bc77b5fcb835e8dd03 100644 (file)
@@ -236,7 +236,7 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
     private final class ExceptionHandlingInboundChannelHandler extends ChannelInboundHandlerAdapter {
         @Override
         public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
-            logger.warn("An exception occurred during negotiation on channel {}", channel.localAddress(), cause);
+            logger.warn("An exception occurred during negotiation with {}", channel.remoteAddress(), cause);
             cancelTimeout();
             negotiationFailed(cause);
             changeState(State.FAILED);
index 9e287f99210389e41ba8d4cbd6f5509b1abfeaef..1b0a34d7e0fa7d0b6ab32c6c3600de52a5f1543f 100644 (file)
@@ -11,7 +11,7 @@ package org.opendaylight.controller.netconf.nettyutil.handler.exi;
 import java.util.List;
 
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.openexi.proc.common.EXIOptions;
 import org.w3c.dom.Document;
index 87056db06c23aef8de11c2fe80d919fffbade208..ad8b25ff2156d8e937d65d054b41b1e3f34c159e 100644 (file)
@@ -12,7 +12,6 @@ import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelPromise;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -20,6 +19,8 @@ import java.util.LinkedList;
 import java.util.Queue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocketException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -27,6 +28,8 @@ import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.V
  * pipeline.
  */
 public class SshClientAdapter implements Runnable {
+    private static final Logger logger = LoggerFactory.getLogger(SshClientAdapter.class);
+
     private static final int BUFFER_SIZE = 1024;
 
     private final SshClient sshClient;
@@ -80,9 +83,11 @@ public class SshClientAdapter implements Runnable {
 
         } catch (VirtualSocketException e) {
             // Netty closed connection prematurely.
+            // Or maybe tried to open ganymed connection without having initialized session
+            // (ctx.channel().remoteAddress() is null)
             // Just pass and move on.
         } catch (Exception e) {
-            throw new IllegalStateException(e);
+            logger.error("Unexpected exception", e);
         } finally {
             sshClient.close();
 
@@ -107,6 +112,7 @@ public class SshClientAdapter implements Runnable {
 
     private void writeImpl(ByteBuf message) throws IOException {
         message.getBytes(0, stdIn, message.readableBytes());
+        message.release();
         stdIn.flush();
     }
 
index 2a3eeb21a8ced14c43565e1c3dd9443b9ef85292..ba65b9ef34cf597aedadf1f5fa5afe6bb5cc646a 100644 (file)
@@ -93,6 +93,7 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
         synchronized(lock) {
             this.bb.discardReadBytes();
             this.bb.writeBytes((ByteBuf) o);
+            ((ByteBuf) o).release();
             lock.notifyAll();
         }
     }
index d97990a5e6f304724b150a40b9e92c8203a3c28a..626ebe937e6942396d695369435cde67f90beda2 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
 /**
  * Exception class which provides notification about exceptional situations at the virtual socket layer.
  */
+// FIXME: Switch to checked exception, create a runtime exception to workaround Socket API
 public class VirtualSocketException extends RuntimeException {
     private static final long serialVersionUID = 1L;
 }
index cbd3efc57f7bc0abfd27e77bec63334087265fab..8a2387d2c1d450df3e0a9bc964c435e84688844a 100644 (file)
@@ -56,7 +56,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.ssh.osgi.NetconfSSHActivator</Bundle-Activator>
@@ -81,7 +80,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>
index d999d378d9af12c56298f292b9b0723b1d9bbe38..8045d32a5038400c650da7ec23fce8e5527ec10e 100644 (file)
@@ -100,14 +100,14 @@ public class Handshaker implements Runnable {
     @Override
     public void run() {
         // let ganymed process handshake
-        logger.trace("{} SocketThread is started", session);
+        logger.trace("{} is started", session);
         try {
             // TODO this should be guarded with a timer to prevent resource exhaustion
             ganymedConnection.connect();
         } catch (IOException e) {
-            logger.warn("{} SocketThread error ", session, e);
+            logger.debug("{} connection error", session, e);
         }
-        logger.trace("{} SocketThread is exiting", session);
+        logger.trace("{} is exiting", session);
     }
 }
 
index 65da6e987e1944aa6cac0d3f38c8de72af68d7f8..3c4ee4728d9f311664f2c04e1b7c1d4f2c278580 100644 (file)
@@ -47,7 +47,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.tcp.osgi.NetconfTCPActivator</Bundle-Activator>
index d9d957c663766ccb847cc57a3cde920b19d6cfd2..df4d389705b29eda03cb3e88a553ba14902720f3 100644 (file)
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <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.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.api.xml,
+              org.opendaylight.controller.netconf.mapping.api,
               org.osgi.framework, org.slf4j, org.w3c.dom, org.xml.sax,io.netty.channel.local</Import-Package>
             <Export-Package>org.opendaylight.controller.netconf.util.*</Export-Package>
           </instructions>
@@ -68,7 +68,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>
index 640596d93078b86b356bc18c19d318bab89a62c6..0269bcccb989492e69b616fc955545ca49509f31 100644 (file)
@@ -8,9 +8,10 @@
 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.xml.XmlNetconfConstants;
 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;
index 8837c74ff5ad80911deb7c804d48383c52d4a51c..25e0f7926574c3168bc013cff865ec2f6a8a33db 100644 (file)
@@ -11,11 +11,11 @@ package org.opendaylight.controller.netconf.util.mapping;
 import java.util.Map;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 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.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;
index 86b2ba1671478a022e30f7dd8c724b07c1d4d703..33934d10ba1c8ec9db8b29fe2135eda9cdcf499b 100644 (file)
@@ -13,9 +13,9 @@ import org.opendaylight.controller.netconf.api.NetconfMessage;
 import java.util.Set;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 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.w3c.dom.Document;
 import org.w3c.dom.Element;
index 49395d53d21225a20b6d47491db0e05fd03626eb..3e8040ad8a1d87e916415795e08e38814963537b 100644 (file)
@@ -10,15 +10,17 @@ package org.opendaylight.controller.netconf.util.messages;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 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 org.w3c.dom.Document;
 
 import javax.annotation.Nullable;
+
 import java.util.Collection;
 import java.util.List;
 
index fdcaa2a5b8c98616385231d5c6c8c0f7e39c0adc..4c4ff2fc583a0a1007ccd4b4706054c097eb2d0c 100644 (file)
@@ -9,14 +9,15 @@
 package org.opendaylight.controller.netconf.util.messages;
 
 import com.google.common.base.Preconditions;
+
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
+
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -24,12 +25,6 @@ import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import java.io.InputStream;
-import java.util.Map.Entry;
 
 public final class SendErrorExceptionUtil {
     private static final Logger logger = LoggerFactory.getLogger(SendErrorExceptionUtil.class);
@@ -86,56 +81,8 @@ public final class SendErrorExceptionUtil {
         }
     }
 
-    private static XPathExpression rpcErrorExpression = XMLNetconfUtil
-            .compileXPath("/netconf:rpc-reply/netconf:rpc-error");
-    private static XPathExpression errorTypeExpression = XMLNetconfUtil.compileXPath("netconf:error-type");
-    private static XPathExpression errorTagExpression = XMLNetconfUtil.compileXPath("netconf:error-tag");
-    private static XPathExpression errorSeverityExpression = XMLNetconfUtil.compileXPath("netconf:error-severity");
-
     private static Document createDocument(final NetconfDocumentedException sendErrorException) {
-
-        final InputStream errIS = SendErrorExceptionUtil.class.getResourceAsStream("server_error.xml");
-        Document originalErrorDocument;
-        try {
-            originalErrorDocument = XmlUtil.readXmlToDocument(errIS);
-        } catch (final Exception e) {
-            throw new IllegalStateException(e);
-        }
-
-        final Document errorDocument = XmlUtil.createDocumentCopy(originalErrorDocument);
-        final Node rootNode = errorDocument.getFirstChild();
-
-        final Node rpcErrorNode = (Node) XmlUtil.evaluateXPath(rpcErrorExpression, rootNode, XPathConstants.NODE);
-
-        final Node errorTypeNode = (Node) XmlUtil.evaluateXPath(errorTypeExpression, rpcErrorNode, XPathConstants.NODE);
-        errorTypeNode.setTextContent(sendErrorException.getErrorType().getTagValue());
-
-        final Node errorTagNode = (Node) XmlUtil.evaluateXPath(errorTagExpression, rpcErrorNode, XPathConstants.NODE);
-        errorTagNode.setTextContent(sendErrorException.getErrorTag().getTagValue());
-
-        final Node errorSeverityNode = (Node) XmlUtil.evaluateXPath(errorSeverityExpression, rpcErrorNode,
-                XPathConstants.NODE);
-        errorSeverityNode.setTextContent(sendErrorException.getErrorSeverity().getTagValue());
-
-        if (sendErrorException.getErrorInfo() != null && !sendErrorException.getErrorInfo().isEmpty()) {
-            /*
-             * <error-info> <bad-attribute>message-id</bad-attribute>
-             * <bad-element>rpc</bad-element> </error-info>
-             */
-            final Node errorInfoNode = errorDocument.createElementNS(
-                    XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, "error-info");
-
-            errorInfoNode.setPrefix(rootNode.getPrefix());
-            rpcErrorNode.appendChild(errorInfoNode);
-            for (final Entry<String, String> errorInfoEntry : sendErrorException.getErrorInfo().entrySet()) {
-                final Node node = errorDocument.createElementNS(
-                        XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, errorInfoEntry.getKey());
-                node.setTextContent(errorInfoEntry.getValue());
-                errorInfoNode.appendChild(node);
-            }
-
-        }
-        return errorDocument;
+        return sendErrorException.toXMLDocument();
     }
 
     /**
index 02ced96bf30d6cc6f6ae619f3b32053dbe17f4d8..e7ce4541559943e86983e2e83285ff0d0b9c18e6 100644 (file)
@@ -13,6 +13,8 @@ import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
 
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+
 public final class XMLNetconfUtil {
 
     private XMLNetconfUtil() {}
index b2b202b69ef024569d032771ecd35e116812769e..01b1c8d5642368cfcfb76249ffd163037616134a 100644 (file)
@@ -10,12 +10,14 @@ package org.opendaylight.controller.netconf.util.xml;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
+
 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;
@@ -33,6 +35,8 @@ import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
+
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
index d26fcf987e5469388b5c01bac3a391b805a46536..937949a17e5827bbe74d22eb5071904b3a71906d 100644 (file)
@@ -19,6 +19,7 @@
 
   <modules>
     <module>netconf-api</module>
+    <module>netconf-cli</module>
     <module>netconf-impl</module>
     <module>config-netconf-connector</module>
     <module>netconf-util</module>
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronObject.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronObject.java
new file mode 100644 (file)
index 0000000..bebac37
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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
+ *
+ *  Authors : Dave Tucker
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+/**
+ * This class contains behaviour common to Neutron configuration objects
+ */
+public interface INeutronObject {
+    public String getID();
+    public void setID(String id);
+}
index 5b35dc2b34ff73519e4350fa7070ec06cf60801d..a3c38a9265dc50c814a83c776a0c0c7e599f1dba 100644 (file)
@@ -23,7 +23,7 @@ import org.opendaylight.controller.configuration.ConfigurationObject;
 @XmlRootElement(name = "network")
 @XmlAccessorType(XmlAccessType.NONE)
 
-public class NeutronNetwork extends ConfigurationObject implements Serializable {
+public class NeutronNetwork extends ConfigurationObject implements Serializable, INeutronObject {
     // See OpenStack Network API v2.0 Reference for description of
     // annotated attributes
 
@@ -93,6 +93,8 @@ public class NeutronNetwork extends ConfigurationObject implements Serializable
 
     public String getID() { return networkUUID; }
 
+    public void setID(String id) { this.networkUUID = id; }
+
     public String getNetworkUUID() {
         return networkUUID;
     }
index 680a07453b94b3f56072804b2981006574837f5a..b32b01cb3f3015930510d22fd1a39836a25a0cbb 100644 (file)
@@ -25,7 +25,7 @@ import org.opendaylight.controller.configuration.ConfigurationObject;
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
 
-public class NeutronPort extends ConfigurationObject implements Serializable {
+public class NeutronPort extends ConfigurationObject implements Serializable, INeutronObject {
     private static final long serialVersionUID = 1L;
 
     // See OpenStack Network API v2.0 Reference for description of
@@ -76,6 +76,8 @@ public class NeutronPort extends ConfigurationObject implements Serializable {
 
     public String getID() { return portUUID; }
 
+    public void setID(String id) { this.portUUID = id; }
+
     public String getPortUUID() {
         return portUUID;
     }
index fa35f71fd6ae425aac90f7d31524198413ade2f2..2c10cca0c0e4d0819f91d2f7d5543897d216cd65 100644 (file)
@@ -23,7 +23,7 @@ import org.opendaylight.controller.configuration.ConfigurationObject;
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
 
-public class NeutronRouter extends ConfigurationObject implements Serializable {
+public class NeutronRouter extends ConfigurationObject implements Serializable, INeutronObject {
     private static final long serialVersionUID = 1L;
 
     // See OpenStack Network API v2.0 Reference for description of
@@ -57,6 +57,8 @@ public class NeutronRouter extends ConfigurationObject implements Serializable {
 
     public String getID() { return routerUUID; }
 
+    public void setID(String id) { this.routerUUID = id; }
+
     public String getRouterUUID() {
         return routerUUID;
     }
index ae84a72bbac84ddda56c102972c894e21873a603..840029006be5b16a4d394bae0d6daa0b5efd65a5 100644 (file)
@@ -25,7 +25,7 @@ import org.opendaylight.controller.configuration.ConfigurationObject;
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
 
-public class NeutronSubnet extends ConfigurationObject implements Serializable {
+public class NeutronSubnet extends ConfigurationObject implements Serializable, INeutronObject {
     private static final long serialVersionUID = 1L;
 
     // See OpenStack Network API v2.0 Reference for description of
@@ -83,6 +83,8 @@ public class NeutronSubnet extends ConfigurationObject implements Serializable {
 
     public String getID() { return subnetUUID; }
 
+    public void setID(String id) { this.subnetUUID = id; }
+
     public String getSubnetUUID() {
         return subnetUUID;
     }
index 09c075735a6c3b7090de71554c6fdefc73ef34ec..a2d2dac112e932d7578698bd1eccf54f54942f50 100644 (file)
@@ -12,7 +12,6 @@
   <version>0.4.2-SNAPSHOT</version>
   <packaging>bundle</packaging>
   <dependencies>
-
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>usermanager</artifactId>
     </dependency>
+
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
   <build>
@@ -78,6 +84,7 @@
             <Export-Package>org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.types,
               org.opendaylight.controller.northbound.commons.utils,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.northbound.commons</Export-Package>
             <Import-Package>javax.ws.rs,
               javax.ws.rs.ext,
           <manifestLocation>${project.basedir}/META-INF</manifestLocation>
         </configuration>
       </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-source</id>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <sources>
+                <source>${project.build.directory}/generated-sources/javacc</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>javacc-maven-plugin</artifactId>
+        <version>2.6</version>
+        <executions>
+          <execution>
+            <id>javacc</id>
+            <goals>
+              <goal>javacc</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
     </plugins>
   </build>
   <scm>
index 4393b79f6446463074b869918651c273ff6cfa2a..87f51364ba1c5b59f3b9326a518a07c99c72129c 100644 (file)
@@ -20,6 +20,7 @@ import javax.xml.bind.JAXBException;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
+import org.opendaylight.controller.northbound.commons.query.QueryContextProvider;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleReference;
@@ -58,6 +59,7 @@ public class NorthboundApplication extends Application {
         } );
         _singletons.add(getJsonProvider());
         _singletons.add(new JacksonJsonProcessingExceptionMapper());
+        _singletons.add(new QueryContextProvider());
     }
 
     ////////////////////////////////////////////////////////////////
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Accessor.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Accessor.java
new file mode 100644 (file)
index 0000000..2d910ed
--- /dev/null
@@ -0,0 +1,55 @@
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/*package*/ class Accessor {
+    protected final AccessibleObject _accessorObj;
+
+    public Accessor(AccessibleObject accessor) {
+        _accessorObj = accessor;
+        _accessorObj.setAccessible(true);
+    }
+
+    public AccessibleObject getAccessibleObject() {
+        return _accessorObj;
+    }
+
+    public Annotation[] getAnnotations() {
+        return _accessorObj.getAnnotations();
+    }
+
+    public Object getValue(Object parent) throws QueryException {
+        try {
+            if (_accessorObj instanceof Field) {
+                return ((Field)_accessorObj).get(parent);
+            } else {
+                // assume method
+                return ((Method)_accessorObj).invoke(parent);
+            }
+        } catch (Exception e) {
+            throw new QueryException("Failure in retrieving value", e);
+        }
+    }
+    public Type getGenericType() {
+        if (_accessorObj instanceof Field) {
+            return ((Field)_accessorObj).getGenericType();
+        } else {
+            // assume method
+            return ((Method)_accessorObj).getGenericReturnType();
+        }
+    }
+    public Class<?> getType() {
+
+        if (_accessorObj instanceof Field) {
+            return ((Field)_accessorObj).getType();
+        } else {
+            // assume method
+            return ((Method)_accessorObj).getReturnType();
+        }
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/CompareExpression.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/CompareExpression.java
new file mode 100644 (file)
index 0000000..6b972e6
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * 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.northbound.commons.query;
+
+/*package*/ class CompareExpression implements Expression {
+
+    public static enum OP { RE, EQ, NE, GT, GE, LT, LE };
+
+    private final OP _operation;
+    private final String _selector;
+    private final String _arg;
+
+    public CompareExpression(OP op, String selector, String arg) {
+        _operation = op;
+        _selector = selector;
+        _arg = unQuote(arg);
+    }
+
+
+    public OP getOperator() {
+        return _operation;
+    }
+
+    public String getSelector() {
+        return _selector;
+    }
+
+    public String getArgument() {
+        return _arg;
+    }
+
+    @Override
+    public boolean accept(Visitor visitor) throws QueryException {
+        return visitor.visit(this);
+    }
+
+    @Override
+    public String toString() {
+        return "[" + _selector + " " + _operation + " " + _arg + "]";
+    }
+
+    private static String unQuote(String s) {
+        if (s.startsWith("\"") && s.endsWith("\"")) {
+            s = s.substring(1, s.length()-1);
+        } else if (s.startsWith("\'") && s.endsWith("\'")) {
+            s = s.substring(1, s.length()-1);
+        }
+        return s;
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Expression.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Expression.java
new file mode 100644 (file)
index 0000000..fbc22a0
--- /dev/null
@@ -0,0 +1,12 @@
+/**
+ * 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.northbound.commons.query;
+
+/*package*/ interface Expression {
+    boolean accept(Visitor visitor) throws QueryException;
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/ExpressionBuilder.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/ExpressionBuilder.java
new file mode 100644 (file)
index 0000000..f1b2999
--- /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.northbound.commons.query;
+
+import java.util.Stack;
+
+/*package*/ class ExpressionBuilder {
+    private final Stack<Expression> _stack = new Stack<Expression>();
+    private LogicalExpression.OP _lastOp = null;
+
+    public ExpressionBuilder() {}
+
+    public ExpressionBuilder withAnd() {
+        _lastOp = LogicalExpression.OP.AND;
+        return this;
+    }
+
+    public ExpressionBuilder withOr() {
+        _lastOp = LogicalExpression.OP.OR;
+        return this;
+    }
+
+    public ExpressionBuilder withTerm(Expression exp) {
+        if (_lastOp != null) {
+            exp = new LogicalExpression(_lastOp, _stack.pop(), exp);
+            _lastOp = null;
+        }
+        _stack.push(exp);
+        return this;
+    }
+
+    public Expression build() {
+        return _stack.pop();
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/IteratableTypeInfo.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/IteratableTypeInfo.java
new file mode 100644 (file)
index 0000000..3977837
--- /dev/null
@@ -0,0 +1,67 @@
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ */
+/*package*/ class IteratableTypeInfo extends TypeInfo {
+
+    public IteratableTypeInfo(String name, Accessor accessor) {
+        super(name, accessor.getType(), accessor);
+    }
+
+    @Override
+    public Object retrieve(Object target, String[] query, int index) throws QueryException {
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("retrieve collection: {}/{} type:{}", index, query.length,
+                    target.getClass());
+        }
+        explore();
+        Collection<?> c = (Collection<?>) target;
+        Iterator<?> it = c.iterator();
+        List<Object> objects = new ArrayList<Object>();
+        while (it.hasNext()) {
+            Object item = it.next();
+            for (TypeInfo child : _types.values()) {
+                Object val = child.retrieve(item, query, index);
+                if (val != null) objects.add(val);
+            }
+        }
+        return objects;
+
+    }
+
+    @Override
+    public synchronized void explore() {
+        if (_explored) return;
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("exploring iteratable type: {} gtype: {}", _class,
+                    _accessor.getGenericType());
+        }
+        Type t = _accessor.getGenericType();
+        if (t instanceof ParameterizedType) {
+            Type[] pt = ((ParameterizedType) t).getActualTypeArguments();
+            // First type is a child, ignore rest
+            if (pt.length > 0) {
+                _types.put(_name, new TypeInfo(_name, (Class)pt[0], null));
+            }
+        }
+        _explored = true;
+    }
+
+    @Override
+    public TypeInfo getCollectionChild(Class<?> childType) {
+        explore();
+        for (TypeInfo ti : _types.values()) {
+            if (ti.getType().equals(childType)) {
+                return ti;
+            }
+        }
+        return null;
+    }
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/LogicalExpression.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/LogicalExpression.java
new file mode 100644 (file)
index 0000000..4e99820
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.northbound.commons.query;
+
+/*package*/ class LogicalExpression implements Expression {
+
+    public static enum OP { AND, OR }
+
+    private final OP _op;
+    private final Expression _arg1;
+    private final Expression _arg2;
+
+    public LogicalExpression(OP op, Expression first, Expression second) {
+        _op = op;
+        _arg1 = first;
+        _arg2 = second;
+    }
+
+    public OP getOperator() {
+        return _op;
+    }
+
+    public Expression getFirst() {
+        return _arg1;
+    }
+
+    public Expression getSecond() {
+        return _arg2;
+    }
+
+    @Override
+    public boolean accept(Visitor visitor) throws QueryException {
+        return visitor.visit(this);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(_arg1.toString())
+        .append(_op.toString())
+        .append(_arg2.toString());
+        return sb.toString();
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Query.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Query.java
new file mode 100644 (file)
index 0000000..15dcaeb
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * 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.northbound.commons.query;
+
+import java.util.Collection;
+import java.util.List;
+
+
+/**
+ * Represents a parsed query used in filtering of collections.
+ */
+public interface Query<T> {
+
+    /**
+     * Find items in the given collection and return them as a new list. The
+     * original collection is not changed.
+     *
+     * @param collection to search in.
+     * @return list of items which match the query.
+     * @throws QueryException
+     */
+    public List<T> find(Collection<T> collection) throws QueryException;
+
+    /**
+     * Apply the query on the given collection. Note that this method will modify
+     * the given object by removing any items which don't match the query criteria.
+     * If the collection is 'singleton' or unmodifiable, invocation will result in
+     * an exception.
+     *
+     * @param collection
+     * @return the number matched items
+     * @throws QueryException
+     */
+    public int filter(Collection<T> collection) throws QueryException;
+
+    /**
+     * Search the given root for a child collection and them apply the query on.
+     * Note that this method will modify the given object by removing any items
+     * which don't match the query criteria.
+     *
+     * @param root - top level object to search in
+     * @param childType - the child type which represents the collection.
+     * @return the number of matched items
+     * @throws QueryException
+     */
+    public int filter(T root, Class<?> childType) throws QueryException;
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContext.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContext.java
new file mode 100644 (file)
index 0000000..59a78ac
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ * 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.northbound.commons.query;
+
+/**
+ * Query context
+ */
+public interface QueryContext {
+
+    /**
+     * Create a Query
+     * @param queryString - query string to parse
+     * @param clazz - The class which represents the top level jaxb object
+     * @return a query object
+     * @throws QueryException if the query cannot be parsed.
+     */
+    <T> Query<T> createQuery(String queryString, Class<T> clazz)
+            throws QueryException;
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContextImpl.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContextImpl.java
new file mode 100644 (file)
index 0000000..13d70b1
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * 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.northbound.commons.query;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*package*/ class QueryContextImpl implements QueryContext {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(QueryContext.class);
+
+    @Override
+    public <T> Query<T> createQuery(String queryString, Class<T> type) throws QueryException {
+        if (queryString == null || queryString.trim().length() == 0) return null;
+        try {
+            if (LOGGER.isDebugEnabled()) LOGGER.debug("Processing query: {}", queryString);
+            // FiqlParser is a parser generated by javacc
+            Expression expression = FiqlParser.parse(queryString);
+            if (LOGGER.isDebugEnabled()) LOGGER.debug("Query expression: {}", expression);
+            // create Query and return;
+            return new QueryImpl<T>(type, expression);
+        } catch (Exception ex) {
+            if (LOGGER.isDebugEnabled()) LOGGER.error("Query processing failed = {}",
+                    queryString, ex);
+            throw new QueryException("Unable to parse query.", ex);
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContextProvider.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryContextProvider.java
new file mode 100644 (file)
index 0000000..65a232c
--- /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.northbound.commons.query;
+
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * A provider for getting hold of the QueryContext.
+ */
+@Provider
+public class QueryContextProvider implements ContextResolver<QueryContext> {
+
+    // Singleton Query Context instance
+    private static final QueryContext queryContext = new QueryContextImpl();
+
+    @Override
+    public QueryContext getContext(Class<?> type) {
+        return queryContext;
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryException.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryException.java
new file mode 100644 (file)
index 0000000..9ff78ed
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.northbound.commons.query;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Signals that an error happened during the parsing or processing of a query.
+ */
+public class QueryException extends WebApplicationException {
+
+    private static final long serialVersionUID = 1L;
+
+    public QueryException(String msg) {
+        super(Response.status(Response.Status.BAD_REQUEST)
+                .entity(msg).type(MediaType.TEXT_PLAIN).build());
+    }
+
+    public QueryException(String msg, Throwable cause) {
+        super(cause, Response.status(Response.Status.BAD_REQUEST)
+                .entity(msg).type(MediaType.TEXT_PLAIN).build());
+    }
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryImpl.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/QueryImpl.java
new file mode 100644 (file)
index 0000000..a520f98
--- /dev/null
@@ -0,0 +1,237 @@
+/**
+ * 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.northbound.commons.query;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.opendaylight.controller.northbound.commons.query.CompareExpression.OP;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+/*package*/ class QueryImpl<T> implements Query<T> {
+    public static final Logger LOGGER = LoggerFactory.getLogger(QueryImpl.class);
+    private static final boolean ALLOW_OBJECT_STRING_COMPARE = true;
+
+    private final Expression expression;
+    private final TypeInfo rootType ;
+    /**
+     * Set the expression and cache
+     * @param type
+     * @param expression
+     */
+    public QueryImpl(Class<T> type, Expression expression) {
+        this.expression = expression;
+        this.rootType = TypeInfo.createRoot(null, type);
+    }
+
+    @Override
+    public List<T> find(Collection<T> collection) throws QueryException {
+        // new arraylist for result
+        List<T> result = new ArrayList<T>();
+        for (T item : collection) {
+            if (match(item, rootType)) {
+                result.add(item);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public int filter(Collection<T> collection) throws QueryException {
+        // find items
+        List<T> matched = new ArrayList<T>();
+        for (T item : collection) {
+            if (match(item, rootType)) {
+                matched.add(item);
+            }
+        }
+        collection.clear();
+        collection.addAll(matched);
+        return matched.size();
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public int filter(T rootObject, Class<?> childClass) throws QueryException {
+        // retrieve underlying collection
+        TypeInfo childType = rootType.getCollectionChild(childClass);
+        if (childType == null || !(childType instanceof IteratableTypeInfo)) {
+            return 0;
+        }
+        Collection collection = (Collection)
+                childType.getAccessor().getValue(rootObject);
+        // get the child type of the collection type
+        TypeInfo ti = childType.getCollectionChild(childClass);
+        List matched = new ArrayList();
+        for (Object item : collection) {
+            if (match(item, ti)) {
+                matched.add(item);
+            }
+        }
+        collection.clear();
+        collection.addAll(matched);
+        return matched.size();
+    }
+
+    private boolean match(final Object object, final TypeInfo rootType)
+            throws QueryException {
+        return expression.accept(new Visitor () {
+            @Override
+            public boolean visit(LogicalExpression le) throws QueryException {
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Logical exp {}|{}|{}", le.getOperator(), le.getFirst(),
+                            le.getSecond());
+                }
+                return (le.getOperator() == LogicalExpression.OP.AND) ?
+                        le.getFirst().accept(this) && le.getSecond().accept(this) :
+                            le.getFirst().accept(this) || le.getSecond().accept(this);
+            }
+
+            @Override
+            public boolean visit(CompareExpression ce) throws QueryException {
+                boolean result = visitInternal(ce);
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("=== Compare exp {}|{}|{} == {}", ce.getOperator(),
+                            ce.getSelector(), ce.getArgument(), result);
+                }
+                return result;
+            }
+
+            public boolean visitInternal(CompareExpression ce) throws QueryException {
+                String[] selector = ce.getSelector().split("\\.");
+                if (!rootType.getName().equals(selector[0])) {
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("Root name mismatch: {} != {}",
+                                rootType.getName(), selector[0]);
+                    }
+                    return false;
+                }
+                Object value = rootType.retrieve(object, selector, 1);
+                if(value == null){ // nothing to compare against
+                    return false;
+                }
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Comparing [{}] {} [{}]", ce.getArgument(),
+                            ce.getOperator(), value.toString());
+                }
+                if (value instanceof Collection) {
+                    Collection<?> collection = (Collection<?>) value;
+                    if(collection.size() == 0 && ce.getOperator() == OP.NE) {
+                        // collection doesn't contain query string
+                        return true;
+                    }
+                    // If there are elements iterate
+                    Iterator<?> it = collection.iterator();
+                    OP operator = ce.getOperator();
+                    if (operator == OP.NE) {
+                        // negate the operator
+                        operator = OP.EQ;
+                    }
+                    while (it.hasNext()) {
+                        Object item = it.next();
+                        if (compare(parse(ce.getArgument(), item), item, operator)) {
+                            // if match found check the operator and return false for NE
+                            return (ce.getOperator() != OP.NE);
+                        }
+                    }
+                    // return true for NE and false for rest
+                    return (ce.getOperator() == OP.NE);
+                } else {
+                    return compare(parse(ce.getArgument(), value), value,
+                            ce.getOperator());
+                }
+            }
+
+        });
+    }
+
+    private boolean compare(Object valueToMatch, Object actualValue, OP operator) {
+        if (valueToMatch == null || actualValue == null) return false;
+        if (ALLOW_OBJECT_STRING_COMPARE && (valueToMatch instanceof String)
+                && !(actualValue instanceof String)) {
+            actualValue = actualValue.toString();
+        }
+
+        int compareResult = -1;
+        if (valueToMatch instanceof Comparable) {
+            compareResult = ((Comparable)actualValue).compareTo(valueToMatch);
+        } else {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Not a comparable type: {} {}",
+                        valueToMatch.getClass().getName(),
+                        actualValue.getClass().getName());
+            }
+            return false;
+        }
+        switch(operator) {
+            case EQ :
+                return compareResult == 0;
+            case RE :
+                // Regex match,
+                if (valueToMatch instanceof String) {
+                    return Pattern.matches((String)valueToMatch, actualValue.toString());
+                } else {
+                    return compareResult == 0;
+                }
+            case NE:
+                return compareResult != 0;
+            case GT :
+                return compareResult > 0;
+            case GE :
+                return compareResult >= 0;
+            case LT :
+                return compareResult < 0;
+            case LE :
+                return compareResult <= 0;
+            default:
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Unrecognized comparator - {}", operator);
+                }
+            return false;
+        }
+    }
+    private Object parse(String arg, Object value) {
+        if (value == null) return null;
+
+        try {
+            if (value instanceof String) {
+                return arg;
+            } else if (value instanceof Byte) {
+                return Byte.decode(arg);
+            } else if (value instanceof Double) {
+                return Double.parseDouble(arg);
+            } else if (value instanceof Float) {
+                return Float.parseFloat(arg);
+            } else if (value instanceof Integer) {
+                return Integer.parseInt(arg);
+            } else if (value instanceof Long) {
+                return Long.parseLong(arg);
+            } else if (value instanceof Short) {
+                return Short.parseShort(arg);
+            }
+        } catch (NumberFormatException ignore) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Exception parsing {}", arg, value);
+            }
+        }
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Using string comparision for type - {}",
+                    value.getClass().getName());
+        }
+        // Not a number or string. Convert to a string and compare as last resort
+        return ALLOW_OBJECT_STRING_COMPARE ? arg.toString() : null;
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/TypeInfo.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/TypeInfo.java
new file mode 100644 (file)
index 0000000..91f01d8
--- /dev/null
@@ -0,0 +1,294 @@
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A wrapper over a JAXB type to allow traversal of the object graph and
+ * search for specific values in the object tree.
+ */
+/*package*/ class TypeInfo {
+
+    public static final Logger LOGGER = LoggerFactory.getLogger(TypeInfo.class);
+    public static final String DEFAULT_NAME = "##default";
+
+    protected final String _name; // the jaxb name
+    protected Class<?> _class; // jaxb type class
+    protected final XmlAccessType _accessType; // jaxb access type
+    protected final Accessor _accessor; // accessor to access object value
+    protected Map<String,TypeInfo> _types = new HashMap<String,TypeInfo>();
+    protected volatile boolean _explored = false;
+    /**
+     * Create a TypeInfo with a name and a class type. The accessor will be null
+     * for a root node.
+     */
+    protected TypeInfo(String name, Class<?> clz, Accessor accessor) {
+        _name = name;
+        _class = clz;
+        _accessor = accessor;
+        XmlAccessorType accessorType = null;
+        if(clz == null) {
+            throw new NullPointerException("Type class can not be null");
+        }
+        accessorType = clz.getAnnotation(XmlAccessorType.class);
+        _accessType = (accessorType == null ?
+                XmlAccessType.PUBLIC_MEMBER : accessorType.value());
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Created type info name:{} type:{}", _name, _class);
+        }
+    }
+
+    /**
+     * @return the Accessor to access the value
+     */
+    public final Accessor getAccessor() {
+        return _accessor;
+    }
+
+    /**
+     * @return get the child by name
+     */
+    public final TypeInfo getChild(String name) {
+        return _types.get(name);
+    }
+
+    public TypeInfo getCollectionChild(Class<?> childType) {
+        explore();
+        for (TypeInfo ti : _types.values()) {
+            if (Collection.class.isAssignableFrom(ti.getType())) {
+                ParameterizedType p = (ParameterizedType)
+                        ti.getAccessor().getGenericType();
+                Type[] pts = p.getActualTypeArguments();
+                if (pts.length == 1 && pts[0].equals(childType)) {
+                    return ti;
+                }
+            }
+        }
+        return null;
+    }
+
+    public Class getType() {
+        return _class;
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    /**
+     * @return the object value by a selector query
+     */
+    public Object retrieve(Object target, String[] query, int index)
+            throws QueryException {
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("retrieve: {}/{} type:{}", index, query.length, target.getClass());
+        }
+        if (index >= query.length) return null;
+        explore();
+        if (!target.getClass().equals(_class)) {
+            if (_class.isAssignableFrom(target.getClass())) {
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Handling subtype {} of {} ", target.getClass(), _class);
+                }
+                // explore the subtype
+                TypeInfo subTypeInfo = new TypeInfo(getRootName(target.getClass()),
+                        target.getClass(), _accessor);
+                return subTypeInfo.retrieve(target, query, index);
+            } else {
+                // non compatible object; bail out
+                return null;
+            }
+        }
+        TypeInfo child = getChild(query[index]);
+        if (child == null) return null;
+        target = child.getAccessor().getValue(target);
+        if (index+1 == query.length) {
+            // match found
+            return target;
+        }
+        return child.retrieve(target, query, index+1);
+    }
+
+    /**
+     * Explore the type info for children.
+     */
+    public synchronized void explore() {
+        if (_explored) return;
+        for (Class<?> c = _class; c != null; c = c.getSuperclass()) {
+            if (c.equals(Object.class)) break;
+            // Currently only fields and methods annotated with JAXB annotations are
+            // considered as valid for search purposes.
+            //check methods first
+            for (Method m : c.getDeclaredMethods()) {
+                String tn = getTypeName(m, _accessType);
+                if (tn != null) {
+                    if (LOGGER.isDebugEnabled()) LOGGER.debug(
+                            "exploring type: {} name: {} method: {}",
+                            _class.getSimpleName(), tn, m);
+                    _types.put(tn, createTypeInfo(tn, new Accessor(m)));
+                }
+            }
+            for (Field f : c.getDeclaredFields()) {
+                String tn = getTypeName(f, _accessType);
+                if (tn != null) {
+                    if (LOGGER.isDebugEnabled()) LOGGER.debug(
+                            "exploring type: {} name: {} field: {}",
+                            _class.getSimpleName(), tn, f);
+                    _types.put(tn, createTypeInfo(tn, new Accessor(f)));
+                }
+            }
+        }
+        _explored = true;
+    }
+
+    public static final String getTypeName(Field f, XmlAccessType access) {
+        // ignore static, transient and xmltransient fields
+        if (Modifier.isTransient(f.getModifiers()) ||
+                Modifier.isStatic(f.getModifiers()) ||
+                f.getAnnotation(XmlTransient.class) != null ) {
+            return null;
+        }
+        // try to read annotation
+        String name = getTypeName(f.getAnnotations(), f.getName());
+        if (name != null) return name;
+        // no annotation present check accesstype
+        else if (access == XmlAccessType.NONE) { // none return name
+            return name;
+        } else if (access == XmlAccessType.FIELD) {
+            // return field name if no annotation present
+            return f.getName();
+        } else if (access == XmlAccessType.PUBLIC_MEMBER
+                && Modifier.isPublic(f.getModifiers())) { // look for public access
+            return f.getName();
+        }
+        // return annotated name ( if any )
+        return null;
+    }
+
+    public static final String getTypeName(Method m, XmlAccessType access) {
+        // ignore static, transient and xmltransient fields
+        if (Modifier.isStatic(m.getModifiers()) ||
+                m.getAnnotation(XmlTransient.class) != null ) {
+            return null;
+        }
+        // try to read annotation
+        String name = getTypeName(m.getAnnotations(), m.getName());
+        if (name != null) return name;
+        //check acces type
+        else if (access == XmlAccessType.NONE) { // none return name
+            return name;
+        } else if (access == XmlAccessType.PROPERTY) {
+            // return bean property name if no annotation present
+            return getBeanPropertyName(m);
+        } else if (access == XmlAccessType.PUBLIC_MEMBER
+                && Modifier.isPublic(m.getModifiers())) { // look for public access
+            return getBeanPropertyName(m);
+        }
+        return null;
+    }
+
+    private static String getBeanPropertyName(Method m){
+        try
+        {
+            Class<?> clazz=m.getDeclaringClass();
+            BeanInfo info = Introspector.getBeanInfo(clazz);
+            PropertyDescriptor[] props = info.getPropertyDescriptors();
+            for (PropertyDescriptor pd : props)
+            {
+                if (m.equals(pd.getReadMethod())) return pd.getName();
+            }
+        }
+        catch (IntrospectionException e)
+        {
+            LOGGER.error("Could not read bean property name for method = {}",
+                    m.getName(), e);
+        }
+        return null;
+    }
+
+    public static TypeInfo createRoot(String name, Class<?> clz) {
+        // root is always a composite type
+        // FIXME assert its a JAXB type
+        XmlRootElement root = clz.getAnnotation(XmlRootElement.class);
+        if (root == null) throw new IllegalArgumentException("Not a JAXB type: " + clz);
+        if (name == null) name = getRootName(clz);
+        return new TypeInfo(name, clz, null);
+    }
+
+    public static TypeInfo createTypeInfo(String name, Accessor accessor) {
+        if (accessor.getAccessibleObject().getAnnotation(XmlElementWrapper.class) != null) {
+            //XmlElementWrapperType
+            return new WrapperTypeInfo(name, accessor);
+        } else if (Collection.class.isAssignableFrom(accessor.getType())) {
+            // collection type
+            return new IteratableTypeInfo(name, accessor);
+        }
+        return new TypeInfo(name, accessor.getType(), accessor);
+    }
+
+    public static String getRootName(Class<?> cls) {
+        XmlRootElement root = cls.getAnnotation(XmlRootElement.class);
+        if (root == null) return null;
+        String rootName = root.name();
+        if (DEFAULT_NAME.equals(rootName)) {
+            String clsName = cls.getSimpleName();
+            rootName = Character.toLowerCase(clsName.charAt(0)) + clsName.substring(1);
+        }
+        return rootName;
+    }
+
+    protected static String getTypeName(Annotation[] annotations, String dflt) {
+        String name = null;
+        for (Annotation a : annotations) {
+            if (a.annotationType() == XmlAttribute.class) {
+                name = ((XmlAttribute)a).name();
+            } else if (a.annotationType() == XmlElement.class) {
+                name = ((XmlElement)a).name();
+            } else if (a.annotationType() == XmlElementRef.class) {
+                name = ((XmlElementRef)a).name();
+            } else if (a.annotationType() == XmlElementWrapper.class) {
+                name = ((XmlElementWrapper)a).name();
+                // break the loop as we don't want name to be overwritten by XmlElement
+                break;
+            } else if (a.annotationType() == XmlType.class) {
+                name = ((XmlType)a).name();
+            } else if (a.annotationType() == XmlTransient.class) {
+                // transient type
+                return null;
+            }
+        }
+        if (DEFAULT_NAME.equals(name)) return dflt;
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return " TypeInfo [_name=" + _name + ", _class=" + _class
+                + ", _accessType=" + _accessType + ", _accessor=" + _accessor
+                + ", _types=" + _types + ", _explored=" + _explored + " ] ";
+    }
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Visitor.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/Visitor.java
new file mode 100644 (file)
index 0000000..0c1d2be
--- /dev/null
@@ -0,0 +1,16 @@
+/**
+ * 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.northbound.commons.query;
+
+/*package*/ interface Visitor {
+
+    boolean visit(LogicalExpression exp) throws QueryException;
+
+    boolean visit(CompareExpression exp) throws QueryException;
+
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/WrapperTypeInfo.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/query/WrapperTypeInfo.java
new file mode 100644 (file)
index 0000000..a8172f2
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ * 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.northbound.commons.query;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import javax.xml.bind.annotation.XmlElement;
+
+public class WrapperTypeInfo extends TypeInfo {
+
+    protected WrapperTypeInfo(String name, Accessor accessor) {
+        super(name, accessor.getType(), accessor);
+    }
+
+    @Override
+    public Object retrieve(Object target, String[] query, int index) throws QueryException {
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("retrieve collection: {}/{}", index, query.length);
+        }
+        if (index >= query.length) return null;
+        explore();
+        TypeInfo child = getChild(query[index]);
+        if (child == null) return null;
+        if (query.length == index+1) { // skipping this node
+            return target;
+        }else { // if list of list go to next node to get value
+            return child.retrieve(target, query, index+1);
+        }
+    }
+
+    @Override
+    public synchronized void explore() {
+        if (_explored) return;
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("exploring wrapper type: {} gtype: {}", _class,
+                    _accessor.getGenericType());
+        }
+        String tn = null;
+        AccessibleObject accessibleObject = _accessor.getAccessibleObject();
+        XmlElement xmlElement = accessibleObject.getAnnotation(XmlElement.class);
+        if (accessibleObject instanceof Field) {
+            Field f = (Field) accessibleObject;
+            tn = DEFAULT_NAME.equals(xmlElement.name())?f.getName() : xmlElement.name();
+        }else if (accessibleObject instanceof Method) {
+            Method m = (Method) accessibleObject;
+            tn = DEFAULT_NAME.equals(xmlElement.name())?m.getName() : xmlElement.name();
+        }
+        this._types.put(tn, new IteratableTypeInfo(tn, this._accessor));
+        _explored = true;
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/main/javacc/fiql.jj b/opendaylight/northbound/commons/src/main/javacc/fiql.jj
new file mode 100644 (file)
index 0000000..b447a32
--- /dev/null
@@ -0,0 +1,124 @@
+
+options {
+  STATIC = false;
+}
+
+PARSER_BEGIN(FiqlParser)
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.util.regex.*;
+
+/*package*/ class FiqlParser {
+  public static Expression parse(String query) throws ParseException {
+    FiqlParser parser = new FiqlParser(new java.io.StringReader(query));
+    return parser.START();
+  }
+}
+
+PARSER_END(FiqlParser)
+
+/* whitespace */
+SKIP :
+{
+  " " | "\t"
+}
+
+TOKEN : {
+  <#ALPHA  : ( ["a"-"z", "A"-"Z", "0"-"9"] )+ >
+}
+
+TOKEN : {
+  <NUM     : ("+"|"-")?(["0"-"9"])+"."(["0"-"9"])* >
+  |
+  <LPAREN  : "(" >
+  |
+  <RPAREN  : ")" >
+}
+
+/* comparision ops */
+TOKEN : {
+  <RE      : ("=") >
+  |
+  <EQ      : ("==" | "=eq=") >
+  |
+  <NE      : ("!=" | "=ne=") >
+  |
+  <LT      : ("=lt=" | "<") >
+  |
+  <LE      : ("=le=" | "<=") >
+  |
+  <GT      : ("=gt=" | ">") >
+  |
+  <GE      : ("=ge=" | ">=") >
+}
+
+/* ops */
+TOKEN : {
+  <AND     : (";" | "and") >
+  |
+  <OR      : ("," | "or") >
+}
+
+/* strings */
+TOKEN : {
+  <STRING : ( ~["\"", "'", "(", ")", ";", ",", "=", "<", ">", "!", "~", " "] )+ >
+  |
+  <DQ_STRING : ( "\"" ( ~["\""] )* "\"" ) >
+  |
+  <SQ_STRING : ( "'" ( ~["'"] )* "'" ) >
+}
+
+/* Root production */
+Expression START() :
+{
+  Expression e;
+}
+{
+  e = EXPR()
+  <EOF>
+  {
+    return e;
+  }
+}
+
+Expression EXPR():
+{
+  ExpressionBuilder builder = new ExpressionBuilder();
+  Expression t;
+}
+{
+  t = TERM() { builder.withTerm(t); }
+  (
+    (<AND> t = TERM()) { builder.withAnd().withTerm(t); }
+    |
+    (<OR> t = TERM() ) { builder.withOr().withTerm(t); }
+  )*
+  {
+    return builder.build();
+  }
+}
+
+Expression TERM() :
+{
+  Token selector, arg;
+  Expression exp;
+  CompareExpression.OP op;
+}
+{
+  selector = <STRING>
+  (
+    ( <EQ>  {op=CompareExpression.OP.EQ;} |
+      <RE>  {op=CompareExpression.OP.RE;} |
+      <NE>  {op=CompareExpression.OP.NE;} |
+      <LT>  {op=CompareExpression.OP.LT;} |
+      <LE>  {op=CompareExpression.OP.LE;} |
+      <GT>  {op=CompareExpression.OP.GT;} |
+      <GE>  {op=CompareExpression.OP.GE;}
+    )
+    ( arg = <STRING> | arg = <DQ_STRING> | arg = <SQ_STRING> | arg = <NUM>)
+  ) { return new CompareExpression(op, selector.image, arg.image); }
+  |
+  (
+    <LPAREN> exp = EXPR() <RPAREN>
+  ) { return exp; }
+}
diff --git a/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/BookBean.java b/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/BookBean.java
new file mode 100644 (file)
index 0000000..5d518f6
--- /dev/null
@@ -0,0 +1,92 @@
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.northbound.commons.types.StringList;
+
+/**
+ */
+
+@XmlRootElement(name="book")
+public class BookBean {
+
+    @XmlElement(name="name")
+    private String _name; // simple type
+
+    private String _isbn; // method annotation
+
+    @XmlElement(name="author")
+    private PersonBean _author; // composite type
+
+    @XmlElementWrapper//for XMLWrapper iterative composite types
+    @XmlElement(name="review")
+    private final List<ReviewBean> reviews = new ArrayList<ReviewBean>();
+
+    @XmlElement
+    private List<String> soldBy; //Iterative Type
+
+    @XmlElementWrapper(name="test")
+    @XmlElement
+    private final List<StringList> testList = new ArrayList<StringList>(); //XMLWrapper list of list
+
+    @XmlElementWrapper(name="parent")
+    @XmlElement(name="child")
+    private final List<WrapperList> wrapperList = new ArrayList<WrapperList>(); // XMLWrapper of XMLWrapper
+
+    public BookBean(){}
+
+    public BookBean(String name, String id, PersonBean person) {
+        _name = name;
+        _isbn = id;
+        _author = person;
+        soldBy = new ArrayList<String>();
+    }
+
+    public BookBean addReview(ReviewBean review) {
+        reviews.add(review);
+        return this;
+    }
+
+    public void setSellerInfo(List<String> sellers) {
+        soldBy = new ArrayList<String>(sellers);
+    }
+
+    public void addWrapperList(WrapperList list){
+        wrapperList.add(list);
+    }
+
+    public void addToTestList(StringList testList){
+        this.testList.add(testList);
+    }
+    public String getName() {
+        return "1"+_name;
+    }
+
+    @XmlElement(name="isbn")
+    public String get_isbn() {
+        return "pre"+_isbn;
+    }
+
+    public PersonBean getauthor() {
+        return _author;
+    }
+
+    @Override
+    public String toString() {
+        return "BookBean [_name=" + _name + ", _isbn=" + _isbn + ", _author="
+                + _author + ", reviews=" + reviews + ", soldBy=" + soldBy
+                + ", testList=" + testList + ", wrapperList=" + wrapperList + "]";
+    }
+
+}
+
+class WrapperList {
+  @XmlElementWrapper(name="items")
+  @XmlElement
+  public List<String> item = new ArrayList<String>();
+}
diff --git a/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/ExpresssionTest.java b/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/ExpresssionTest.java
new file mode 100644 (file)
index 0000000..3e2e153
--- /dev/null
@@ -0,0 +1,207 @@
+/**
+ * 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.northbound.commons.query;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.northbound.commons.query.CompareExpression.OP;
+
+public class ExpresssionTest {
+
+    private static final List<PersonBean> people = new ArrayList<PersonBean>();
+    private static final ArrayList<BookBean> books = new ArrayList<BookBean>();
+
+    public static void p(String msg) {
+        //System.out.println("======= " + msg);
+    }
+
+    public static boolean matches(Expression exp, final PersonBean person) throws Exception {
+
+        boolean result = exp.accept(new Visitor() {
+            @Override
+            public boolean visit(LogicalExpression le) throws QueryException {
+                p("=== LE " + le.getOperator() + "|" + le.getFirst() + "|" + le.getSecond());
+                return (le.getOperator() == LogicalExpression.OP.AND) ?
+                        le.getFirst().accept(this) && le.getSecond().accept(this) :
+                            le.getFirst().accept(this) || le.getSecond().accept(this);
+            }
+
+            @Override
+            public boolean visit(CompareExpression ce) {
+                p("=== CE " + ce.getOperator() + "|" + ce.getSelector() + "|" + ce.getArgument());
+                if (person == null) {
+                    return false;
+                }
+                try {
+                    // check if the selector matches any of the fields
+                    Field field = PersonBean.class.getDeclaredField(ce.getSelector());
+                    if (field == null) {
+                        p("No field found by name : " + ce.getSelector());
+                        return false;
+                    }
+                    Object value = field.get(person);
+                    if (value instanceof String) {
+                        p("Comparing [" + ce.getArgument() + "] "+ ce.getOperator() + " [" + value.toString() + "]");
+                        if (ce.getOperator() == OP.EQ) {
+                            return ce.getArgument().equals(value.toString());
+                        } else if (ce.getOperator() == OP.RE) {
+                            return Pattern.matches(ce.getArgument(), value.toString());
+                        } else if (ce.getOperator() == OP.NE) {
+                            return !ce.getArgument().equals(value.toString());
+                        } else {
+                            p("Comparator : " + ce.getOperator() + " cannot apply to Strings");
+                            return false;
+                        }
+                    } else {
+                        // assume its a #
+                        int valToMatch = Integer.parseInt(ce.getArgument());
+                        int actualValue = (Integer)value;
+                        p("Comparing: " + valToMatch + " " + ce.getOperator() + " " + actualValue);
+                        switch(ce.getOperator()) {
+                        case EQ :
+                        case RE :
+                            return actualValue == valToMatch;
+                        case NE :
+                            return actualValue != valToMatch;
+                        case GT :
+                            return actualValue > valToMatch;
+                        case GE :
+                            return actualValue >= valToMatch;
+                        case LT :
+                            return actualValue < valToMatch;
+                        case LE :
+                            return actualValue <= valToMatch;
+                        default:
+                            p("Unrecognized compare operator: " + ce.getOperator());
+                            return false;
+                        }
+                    }
+                } catch (Exception e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        });
+        p("RESULT: " + result);
+        return result;
+    }
+
+    @BeforeClass
+    public static void load() {
+        System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug");
+
+        people.add(new PersonBean(100, "John", "Doe", "San Jose"));
+        people.add(new PersonBean(200, "Foo", "Bar", "San Francisco"));
+        people.add(new PersonBean(300, "A", "B", "San Francisco"));
+        people.add(new PersonBean(400, "X", "Y", "New York"));
+
+        books.add(new BookBean("Book1", "A001", people.get(0)));
+        books.add(new BookBean("Book2", "A002", people.get(1)));
+        books.add(new BookBean("Book3", "A003", people.get(2)));
+
+        ReviewBean review1 = new ReviewBean("cool", people.get(2));
+        ReviewBean review2 = new ReviewBean("kewl", people.get(3));
+        ReviewBean review3 = new ReviewBean("+++", people.get(0));
+        ReviewBean review4 = new ReviewBean("---", people.get(1));
+
+        books.get(0).addReview(review1).addReview(review2).addReview(review3).addReview(review4);
+        books.get(1).addReview(review1).addReview(review2).addReview(review3).addReview(review4);
+        books.get(2).addReview(review1).addReview(review2).addReview(review3).addReview(review4);
+    }
+
+    @Test
+    public void testCXFQueries() throws Exception {
+        // following queries copied from apache cxf
+        Assert.assertFalse(matches(parseQuery("id=gt=100;name=Fred"), null));
+        Assert.assertFalse(matches(parseQuery("id=gt=100;name==Fred"), null));
+        Assert.assertFalse(matches(parseQuery("id=lt=123"), null));
+        Assert.assertFalse(matches(parseQuery("date=le=2010-03-11"), null));
+        Assert.assertFalse(matches(parseQuery("time=le=2010-03-11T18:00:00"), null));
+        Assert.assertFalse(matches(parseQuery("name==CXF;version=ge=2.2"), null));
+        Assert.assertFalse(matches(parseQuery("(age=lt=25,age=gt=35);city==London"), null));
+        Assert.assertFalse(matches(parseQuery("date=lt=2000-01-01;date=gt=1999-01-01;(sub==math,sub==physics)"), null));
+    }
+
+    public Expression parseQuery(String query) throws Exception {
+        p("PARSING query: " + query);
+        // FiqlParser is a parser generated by javacc
+        Expression exp = FiqlParser.parse(query);
+        p(exp.toString());
+        return exp;
+    }
+
+    public int find(String query) throws Exception {
+        int found = 0;
+        Expression exp = parseQuery(query);
+        TypeInfo.createRoot("person", PersonBean.class);
+        for (PersonBean person : people) {
+            if (matches(exp, person)) found++;
+        }
+        return found;
+    }
+
+    @Test
+    public void testPeopleQueries() throws Exception {
+        Assert.assertTrue(find("id==200") == 1);
+        Assert.assertTrue(find("id!=100;(city='San.*')") == 2);
+        Assert.assertTrue(find("id>200;(city='San.*')") == 1);
+        Assert.assertTrue(find("city='San.*'") == 3);
+    }
+
+    @Test
+    public void testTypeTree() throws Exception {
+        TypeInfo bookType = TypeInfo.createRoot("book", BookBean.class);
+        Assert.assertEquals("John", bookType.retrieve(books.get(0),
+                "book.author.firstName".split("\\."), 1));
+        Object result = bookType.retrieve(books.get(0),
+                "book.reviews.review.comment".split("\\."), 1);
+        Assert.assertTrue( result instanceof List);
+        List<Object> commentList = (List<Object>) result;
+        Assert.assertTrue(commentList.contains("cool"));
+    }
+
+    @Test
+    public void testQueryAPI() throws Exception {
+        QueryContext qc = new QueryContextImpl();
+
+        // find all books written by author with firstName "John"
+        Query q1 = qc.createQuery("book.author.firstName==John", BookBean.class);
+        Collection<BookBean> r1 = q1.find(books);
+        p("Filtered books: " + r1.size());
+        Assert.assertEquals(1, r1.size());
+
+        // find all books reviewed by people in a city "San*"
+        Query q2 = qc.createQuery("book.reviews.review.reviewer.city=San.*", BookBean.class);
+        Collection<BookBean> r2 = q2.find(books);
+
+        p("Filtered books: " + r2.size());
+        Assert.assertEquals(3, r2.size());
+
+        // find all books reviewed by people in a city "San*"
+        Query q3 = qc.createQuery("book==foo", BookBean.class);
+        Collection<BookBean> r3 = q3.find(books);
+        Assert.assertEquals(0, r3.size());
+    }
+
+    @Test
+    public void testFilter() throws Exception {
+        Library library = new Library((List)books.clone());
+        QueryContext qc = new QueryContextImpl();
+        // find all books written by author with firstName "John"
+        Query q1 = qc.createQuery("book.author.firstName==John", Library.class);
+        int sizeBefore = library.getList().size();
+        System.out.println(q1.filter(library, BookBean.class));
+        Assert.assertEquals(1, library.getList().size());
+    }
+}
diff --git a/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/Library.java b/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/Library.java
new file mode 100644 (file)
index 0000000..c54b0e7
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * 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.northbound.commons.query;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name="library")
+public class Library {
+
+    @XmlElement(name="book")
+    private final List<BookBean> _list;
+
+    public Library(List<BookBean> list) {
+        _list = list;
+    }
+
+    public List<BookBean> getList() {
+        return _list;
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/PersonBean.java b/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/PersonBean.java
new file mode 100644 (file)
index 0000000..b4b9ed5
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name="person")
+
+public class PersonBean {
+
+    @XmlElement
+    public String firstName;
+    @XmlElement
+    public String lastName;
+    @XmlElement
+    public String city;
+    @XmlElement
+    public int id;
+
+    @XmlElementWrapper(name="emails") // ElementWrapper iteratable type
+    @XmlElement
+    public List<String> email;
+
+    public PersonBean(){}
+    public PersonBean(int n, String f, String l, String c) {
+        firstName = f;
+        lastName = l;
+        city = c;
+        id = n;
+    }
+
+    public void setEmail(List<String> emails){
+        email = emails;
+    }
+    @Override
+    public String toString() {
+        return "PersonBean [firstName=" + firstName + ", lastName=" + lastName
+                + ", city=" + city + ", id=" + id + "]";
+    }
+
+}
diff --git a/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/QueryContextTest.java b/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/QueryContextTest.java
new file mode 100644 (file)
index 0000000..b6e582b
--- /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.northbound.commons.query;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.northbound.commons.types.StringList;
+
+public class QueryContextTest {
+
+    protected static final List<PersonBean> people = new ArrayList<PersonBean>();
+    protected static final List<BookBean> books = new ArrayList<BookBean>();
+
+    public static void p(String msg) {
+        System.out.println("=== " + msg);
+    }
+
+    @BeforeClass
+    public static void load() {
+        people.add(new PersonBean(100, "John", "Doe", "San Jose"));
+        people.add(new PersonBean(200, "Foo", "Bar", "San Francisco"));
+        people.add(new PersonBean(300, "A", "B", "San Francisco"));
+        people.add(new PersonBean(400, "X", "Y", "New York"));
+
+        books.add(new BookBean("Book1", "A001", people.get(0)));
+        books.add(new BookBean("Book2", "A002", people.get(1)));
+        books.add(new BookBean("Book3", "A003", people.get(2)));
+
+        ReviewBean review1 = new ReviewBean("cool", people.get(2));
+        ReviewBean review2 = new ReviewBean("kewl", people.get(3));
+
+        books.get(0).addReview(review1).addReview(review2);
+        books.get(1).addReview(review1);
+        books.get(2).addReview(review2).addReview(review1);
+
+    }
+
+    @Test
+    public void testQueryContext() {
+        QueryContext queryContext = new QueryContextImpl();
+        Assert.assertNotNull(queryContext);
+    }
+
+    @Test
+    public void testSimpleQuery() throws QueryException {
+        QueryContext queryContext = new QueryContextImpl();
+        Query<PersonBean> query = queryContext.createQuery(
+                "person.id==200", PersonBean.class);
+        Assert.assertNotNull(query);
+
+        List<PersonBean> found = query.find(people);
+        Assert.assertNotNull(found);
+        Assert.assertTrue(found.size() == 1);
+        Assert.assertEquals("Foo", found.get(0).firstName);
+    }
+
+    @Test
+    public void testAndQuery() throws QueryException {
+        QueryContext queryContext = new QueryContextImpl();
+        Query<PersonBean> query = queryContext.createQuery(
+                "person.id!=200;(person.city='San.*')", PersonBean.class);
+        Assert.assertNotNull(query);
+
+        List<PersonBean> found = query.find(people);
+        Assert.assertNotNull(found);
+        Assert.assertTrue(found.size() == 2);
+        Assert.assertEquals("John", found.get(0).firstName);
+        Assert.assertEquals("A", found.get(1).firstName);
+    }
+
+    @Test
+    public void testOrQuery() throws QueryException {
+        QueryContext queryContext = new QueryContextImpl();
+        Query<PersonBean> query = queryContext.createQuery(
+                "person.id==200,(person.city='San.*')", PersonBean.class);
+        Assert.assertNotNull(query);
+
+        List<PersonBean> found = query.find(people);
+        Assert.assertNotNull(found);
+        Assert.assertTrue(found.size() == 3);
+        Assert.assertEquals("John", found.get(0).firstName);
+        Assert.assertEquals("Foo", found.get(1).firstName);
+        Assert.assertEquals("A", found.get(2).firstName);
+    }
+
+    @Test
+    public void testXmlElementWrapper() throws QueryException {
+        List<String> emails = new ArrayList<String>();
+        emails.add("john@cisco.com");
+        emails.add("john@gmail.com");
+        people.get(0).setEmail(emails);
+
+        p(toXml(people.get(0)));
+        QueryContext queryContext = new QueryContextImpl();
+        Query<PersonBean> query = queryContext.createQuery(
+                "person.emails.email==john@cisco.com", PersonBean.class);
+        Assert.assertNotNull(query);
+
+        List<PersonBean> found = query.find(people);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1,found.size());
+        Assert.assertEquals("John", found.get(0).firstName);
+    }
+
+    @Test
+    public void testXmlWrapperOfWrapper() throws QueryException{
+        WrapperList wrapper = new WrapperList();
+        wrapper.item.add("Test1");
+        wrapper.item.add("Test2");
+
+        books.get(0).addWrapperList(wrapper);
+        books.get(1).addWrapperList(wrapper);
+
+        System.out.println(toXml(books.get(0)));
+        QueryContext queryContext = new QueryContextImpl();
+        Query<BookBean> query = queryContext.createQuery(
+                "book.parent.child.items.item==Test1", BookBean.class);
+        Assert.assertNotNull(query);
+    }
+
+    @Test
+    public void testXmlElementWrapperListofList() throws QueryException {
+        // create Stringlist
+        List<String> testList = new ArrayList<String>();
+        testList.add("A");
+        testList.add("B");
+        StringList itemList = new StringList(testList);
+        books.get(0).addToTestList(itemList);
+
+        System.out.println(toXml(books.get(0)));
+        QueryContext queryContext = new QueryContextImpl();
+        Query<BookBean> query = queryContext.createQuery(
+                "book.test.testList.item==A", BookBean.class);
+        Assert.assertNotNull(query);
+    }
+
+    @Test
+    public void testPrimitiveIteratableTypes() throws QueryException {
+        // Load data for this test
+        List<String> sellers = new ArrayList<String>();
+        sellers.add("Amazon");
+
+        books.get(0).setSellerInfo(sellers);
+        sellers.add("Barners & Nobles");
+        books.get(1).setSellerInfo(sellers);
+        sellers.add("Borders");
+        sellers.remove("Amazon");
+        sellers.add("BookShop");
+        books.get(2).setSellerInfo(sellers);
+
+        System.out.println(toXml(books.get(0)));
+
+        QueryContext queryContext = new QueryContextImpl();
+        Query<BookBean> query = queryContext.createQuery(
+                "book.soldBy==Amazon", BookBean.class);
+        Assert.assertNotNull(query);
+
+        List<BookBean> found = query.find(books);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(2,found.size());
+        Assert.assertEquals("John", found.get(0).getauthor().firstName);
+
+        query = queryContext.createQuery(
+                "book.soldBy!=Amazon", BookBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(books);
+        System.out.println("books" +found);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1,found.size());
+        Assert.assertEquals("A", found.get(0).getauthor().firstName);
+    }
+
+    @Test
+    public void testCompositeIteratableTypes() throws QueryException {
+        QueryContext queryContext = new QueryContextImpl();
+        Query<BookBean> query = queryContext.createQuery("book.reviews.review.reviewer.firstName==X",
+                BookBean.class);
+        Assert.assertNotNull(query);
+
+        List<BookBean> found = query.find(books);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(2, found.size());
+        Assert.assertEquals("John", found.get(0).getauthor().firstName);
+
+        query = queryContext.createQuery("book.reviews.review.comment==kewl",
+                BookBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(books);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(2, found.size());
+        p("Book 0" + found.get(0));
+        Assert.assertEquals("John", found.get(0).getauthor().firstName);
+
+        query = queryContext.createQuery("book.reviews.review.reviewer.id>300",
+                BookBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(books);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(2, found.size());
+        p("Book 0" + found.get(0));
+        Assert.assertEquals("John", found.get(0).getauthor().firstName);
+
+        query = queryContext.createQuery("book.reviews.review.reviewer.firstName!=X",
+                BookBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(books);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        p("Book 0" + found.get(0));
+        Assert.assertEquals("Foo", found.get(0).getauthor().firstName);
+    }
+
+    @Test
+    public void testXMLAccessorType() {
+        //Assert.fail("implement");
+    }
+
+    @Test
+    public void testMethodAnnotation() throws QueryException {
+        System.out.println(toXml(books.get(0)));
+        QueryContext queryContext = new QueryContextImpl();
+        Query<BookBean> query = queryContext.createQuery(
+                "book.isbn==preA003", BookBean.class);
+        Assert.assertNotNull(query);
+
+        List<BookBean> found = query.find(books);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1,found.size());
+        Assert.assertEquals("A", found.get(0).getauthor().firstName);
+    }
+
+    public static String toXml(Object element) {
+        try {
+            JAXBContext jc = JAXBContext.newInstance(element.getClass());
+            Marshaller marshaller = jc.createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            marshaller.marshal(element, baos);
+            return baos.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    @Test
+    public void testXMLElementWrapperForCompositeTypes(){
+        //Assert.fail("implement");
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/ReviewBean.java b/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/ReviewBean.java
new file mode 100644 (file)
index 0000000..ea2f873
--- /dev/null
@@ -0,0 +1,41 @@
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ */
+@XmlRootElement(name="review")
+public class ReviewBean {
+    @XmlElement(name="date")
+    private  Date _publishedDate;
+    @XmlElement(name="comment")
+    private  String _comment;
+    @XmlElement(name="reviewer")
+    private  PersonBean _reviewer;
+    @XmlElement
+    private int _upVotes;
+    @XmlElement
+    private int _downVotes;
+    public ReviewBean(){}
+
+    public ReviewBean(String comment, PersonBean user) {
+        _comment = comment;
+        _reviewer = user;
+        _publishedDate = new Date();
+    }
+
+    public void vote(int up, int down) {
+        _upVotes += up;
+        _downVotes += down;
+    }
+
+    @Override
+    public String toString() {
+        return "ReviewBean <publishedDate>" + _publishedDate + "</publishedDate> <comment>"
+                + _comment + "</comment> <reviewer>" + _reviewer + "</reviewer> <upVotes>" + _upVotes
+                + "</upVotes> <downVotes>" + _downVotes + "</downVotes>";
+    }
+}
diff --git a/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/XMLAccessorTypeTest.java b/opendaylight/northbound/commons/src/test/java/org/opendaylight/controller/northbound/commons/query/XMLAccessorTypeTest.java
new file mode 100644 (file)
index 0000000..25cb692
--- /dev/null
@@ -0,0 +1,374 @@
+package org.opendaylight.controller.northbound.commons.query;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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 javax.xml.bind.annotation.XmlTransient;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class XMLAccessorTypeTest {
+
+    @Test
+    public void testPublicAccessType() throws Exception {
+        // create bean
+        List<PublicAccessBean> testList = new ArrayList<PublicAccessBean>();
+        testList.add(new PublicAccessBean("John", "Scott", "private", 1,
+                "transient", "elem1"));
+        testList.add(new PublicAccessBean("Foo", "Bar", "private1", 2,
+                "transient1", "elem2"));
+        QueryContextTest.p(QueryContextTest.toXml(testList.get(0)));
+
+        QueryContext queryContext = new QueryContextImpl();
+        Assert.assertNotNull(queryContext);
+        // search for public field
+        Query<PublicAccessBean> query = queryContext.createQuery(
+                "publicbean.firstName==Foo", PublicAccessBean.class);
+        Assert.assertNotNull(query);
+
+        List<PublicAccessBean> found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("Foo", found.get(0).firstName);
+
+        // search for public getter
+        query = queryContext.createQuery("publicbean.privateGetterField<2",
+                PublicAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).firstName);
+
+        // test for transient field
+        query = queryContext.createQuery("publicbean.transientField='trans*'",
+                PublicAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(0, found.size());
+
+        // test for private field
+        query = queryContext.createQuery("publicbean.privateField==private",
+                PublicAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(0, found.size());
+
+        // test for XML Element
+        query = queryContext.createQuery("publicbean.element==elem1",
+                PublicAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).firstName);
+    }
+
+    @Test
+    public void testFieldAccessType() throws QueryException {
+        // create bean
+        List<FieldAccessBean> testList = new ArrayList<FieldAccessBean>();
+        testList.add(new FieldAccessBean("John", "Scott", "private", 1, "elem1"));
+        testList.add(new FieldAccessBean("Foo", "Bar", "private1", 2, "elem2"));
+
+        QueryContextTest.p(QueryContextTest.toXml(testList.get(0)));
+        QueryContext queryContext = new QueryContextImpl();
+        Assert.assertNotNull(queryContext);
+        // test private field
+        Query<FieldAccessBean> query = queryContext.createQuery(
+                "field.privateField==private", FieldAccessBean.class);
+        Assert.assertNotNull(query);
+
+        List<FieldAccessBean> found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).firstName);
+
+        // test public field
+        query = queryContext.createQuery("field.firstName==Foo",
+                FieldAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("Foo", found.get(0).firstName);
+
+        // test annotated field
+        query = queryContext.createQuery("field.element==elem2",
+                FieldAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("Foo", found.get(0).firstName);
+
+        // test annotated method
+        query = queryContext.createQuery("field.privateGetterField==11",
+                FieldAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).firstName);
+    }
+
+    @Test
+    public void testPropertyAccessType() throws QueryException {
+        // create bean
+        List<PropertyAccessBean> testList = new ArrayList<PropertyAccessBean>();
+        testList.add(new PropertyAccessBean("John", "Scott", "private", 1, "elem1",
+                "transient1"));
+        testList.add(new PropertyAccessBean("Foo", "Bar", "private1", 2, "elem2",
+                "transient2"));
+
+        QueryContextTest.p(QueryContextTest.toXml(testList.get(0)));
+        QueryContext queryContext = new QueryContextImpl();
+        Assert.assertNotNull(queryContext);
+        // test public getter public field
+        Query<PropertyAccessBean> query = queryContext.createQuery(
+                "property.firstName==John", PropertyAccessBean.class);
+        Assert.assertNotNull(query);
+
+        List<PropertyAccessBean> found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).firstName);
+
+        // test public field no getter
+        query = queryContext.createQuery("property.lastName==Bar",
+                PropertyAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(0, found.size());
+
+        // test annotated field
+        query = queryContext.createQuery("property.element==elem2",
+                PropertyAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("Foo", found.get(0).firstName);
+
+        // test annotated method
+        query = queryContext.createQuery("property.field==private",
+                PropertyAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).firstName);
+
+        // test transient method
+        query = queryContext.createQuery("property.transientField==transient1",
+                PropertyAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(0, found.size());
+    }
+
+    @Test
+    public void testNoneAccessType() throws QueryException {
+        // create bean
+        List<NoneAccessBean> testList = new ArrayList<NoneAccessBean>();
+        testList.add(new NoneAccessBean("John", "Scott", "private"));
+        testList.add(new NoneAccessBean("Foo", "Bar", "private1"));
+
+        QueryContextTest.p(QueryContextTest.toXml(testList.get(0)));
+        QueryContext queryContext = new QueryContextImpl();
+        Assert.assertNotNull(queryContext);
+        // test annotated field
+        Query<NoneAccessBean> query = queryContext.createQuery(
+                "test.firstName==John", NoneAccessBean.class);
+        Assert.assertNotNull(query);
+
+        List<NoneAccessBean> found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).getFirstName());
+        // test unannotated field
+        query = queryContext
+                .createQuery("test.lastName==Bar", NoneAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(0, found.size());
+        // test annotated method
+        query = queryContext.createQuery("test.testField==private",
+                NoneAccessBean.class);
+        Assert.assertNotNull(query);
+
+        found = query.find(testList);
+        Assert.assertNotNull(found);
+        Assert.assertEquals(1, found.size());
+        Assert.assertEquals("John", found.get(0).getFirstName());
+
+    }
+
+}
+
+// default ( public memeber )
+@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
+@XmlRootElement(name = "publicbean")
+class PublicAccessBean {
+
+  public String firstName;
+  public String lastName;
+  private String privateField;
+  private int privateGetterField;
+  @XmlTransient
+  public String transientField;
+  @XmlElement(name = "element")
+  private String xmlElem;
+
+  public PublicAccessBean() {
+  }
+
+  public PublicAccessBean(String firstName, String lastName,
+      String privateField, int privateGetterField, String transientField,
+      String xmlElem) {
+    this.firstName = firstName;
+    this.lastName = lastName;
+    this.privateField = privateField;
+    this.privateGetterField = privateGetterField;
+    this.transientField = transientField;
+    this.xmlElem = xmlElem;
+  }
+
+  public int getPrivateGetterField() {
+    return privateGetterField;
+  }
+
+  public void setPrivateGetterField(int field) {
+    this.privateGetterField = field;
+  }
+}
+
+// default ( public memeber )
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlRootElement(name = "field")
+class FieldAccessBean {
+
+  public String firstName;
+  public String lastName;
+  private String privateField;
+  private int test;
+  @XmlElement(name = "element")
+  private String xmlElem;
+
+  public FieldAccessBean() {
+  }
+
+  public FieldAccessBean(String firstName, String lastName,
+      String privateField, int privateGetterField, String xmlElem) {
+    this.firstName = firstName;
+    this.lastName = lastName;
+    this.privateField = privateField;
+    this.xmlElem = xmlElem;
+    this.test = privateGetterField;
+  }
+
+  public String getPrivateField() {
+    return privateField;
+  }
+
+  @XmlElement(name = "privateGetterField")
+  public int getPrivateGetterField() {
+    return test + 10;
+  }
+}
+
+// default ( public memeber )
+@XmlAccessorType(XmlAccessType.PROPERTY)
+@XmlRootElement(name = "property")
+class PropertyAccessBean {
+
+  public String firstName;
+  public String lastName;
+  private String privateField;
+  private int privateGetterField;
+  @XmlElement(name = "element")
+  private String xmlElem;
+  private String transientField;
+
+  public PropertyAccessBean() {
+  }
+
+  public PropertyAccessBean(String firstName, String lastName,
+      String privateField, int privateGetterField, String xmlElem,
+      String transientField) {
+    this.firstName = firstName;
+    this.lastName = lastName;
+    this.privateField = privateField;
+    this.privateGetterField = privateGetterField;
+    this.xmlElem = xmlElem;
+    this.transientField = transientField;
+  }
+
+  public int getPrivateGetterField() {
+    return privateGetterField;
+  }
+
+  @XmlElement(name = "field")
+  public String getPrivateField() {
+    return privateField;
+  }
+
+  public String getFirstName() {
+    return firstName;
+  }
+
+  @XmlTransient
+  public String getTransientField() {
+    return transientField;
+  }
+}
+
+// default ( public memeber )
+@XmlAccessorType(XmlAccessType.NONE)
+@XmlRootElement(name = "test")
+class NoneAccessBean {
+  @XmlElement
+  private String firstName;
+  public String lastName;
+  private String testField;
+
+  public NoneAccessBean() {
+  }
+
+  public NoneAccessBean(String firstName, String lastName, String testField) {
+    this.firstName = firstName;
+    this.lastName = lastName;
+    this.testField = testField;
+  }
+
+  @XmlElement(name = "testField")
+  public String getTestField() {
+    return testField;
+  }
+
+  public String getFirstName() {
+    return firstName;
+  }
+}
similarity index 61%
rename from opendaylight/md-sal/remoterpc-routingtable/integrationtest/src/test/resources/logback.xml
rename to opendaylight/northbound/commons/src/test/resources/logback.xml
index 6d9dfda9a365f9a08f9d4ba5b7733f2cb6340ba6..97e15deb944b4093fbb3a52e225b4a8e34fa0cae 100644 (file)
@@ -1,11 +1,15 @@
 <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>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n
       </pattern>
     </encoder>
   </appender>
 
+
+  <logger name="org.opendaylight.controller.northbound.commons.query" level="INFO"/>
+
   <root level="error">
     <appender-ref ref="STDOUT" />
   </root>
index a0940e34284833673913654600ef50a81908b9b8..ad315ac008e78e78712fc6bbc7a6f74e8b12b7b3 100644 (file)
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.utils,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.sal.authorization,
               org.opendaylight.controller.connectionmanager,
               org.opendaylight.controller.sal.connection,
               org.slf4j,
               javax.ws.rs,
+              javax.ws.rs.ext,
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
index e2c1b32c4bf3ab129604d3e66763b3913f0f03d2..dde3210928689278af7d7f2e3103b0e78c114b47 100644 (file)
@@ -27,6 +27,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -36,6 +37,7 @@ import org.opendaylight.controller.northbound.commons.exception.NotAcceptableExc
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.connection.ConnectionConstants;
@@ -50,7 +52,14 @@ import org.opendaylight.controller.sal.utils.Status;
 @Path("/")
 public class ConnectionManagerNorthbound {
     private String username;
+    private QueryContext queryContext;
 
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
     @Context
     public void setSecurityContext(SecurityContext context) {
         if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
@@ -115,7 +124,8 @@ public class ConnectionManagerNorthbound {
         @ResponseCode(code = 406, condition = "Invalid Controller IP Address passed."),
         @ResponseCode(code = 503, condition = "Connection Manager Service not available")})
 
-    public Nodes getNodes(@DefaultValue("") @QueryParam("controller") String controllerAddress) {
+    public Nodes getNodes(@DefaultValue("") @QueryParam("controller") String controllerAddress,
+        @QueryParam("_q") String queryString) {
         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container");
         }
@@ -140,7 +150,12 @@ public class ConnectionManagerNorthbound {
         } else {
             nodeSet = connectionManager.getLocalNodes();
         }
-        return new Nodes(nodeSet);
+        Nodes nodes = new Nodes(nodeSet);
+        if (queryString != null) {
+            queryContext.createQuery(queryString, Nodes.class)
+                .filter(nodes, Node.class);
+        }
+        return nodes;
     }
 
     /**
index 457b1bd6a40c714e8b7dbd7f94d837f07c51d8d4..2e6bb7d40ca0d5245200699822198b8d9ba1c697 100644 (file)
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.utils,
+              org.opendaylight.controller.northbound.commons.query,
               com.sun.jersey.spi.container.servlet,
               javax.ws.rs,
+              javax.ws.rs.ext,
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
index fe38361cca246465bf514686b0beb872e72dd9f5..754167814d763555ede965c5de8c6ee867f5c9f5 100644 (file)
@@ -21,11 +21,13 @@ 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.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -41,6 +43,7 @@ import org.opendaylight.controller.northbound.commons.exception.ResourceConflict
 import org.opendaylight.controller.northbound.commons.exception.ResourceForbiddenException;
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.authorization.UserLevel;
@@ -68,6 +71,14 @@ import org.opendaylight.controller.usermanager.IUserManager;
 @Path("/")
 public class ContainerManagerNorthbound {
     private String username;
+    private QueryContext queryContext;
+
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
 
     @Context
     public void setSecurityContext(SecurityContext context) {
@@ -172,13 +183,18 @@ public class ContainerManagerNorthbound {
     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
             @ResponseCode(code = 401, condition = "User is not authorized to perform this operation"),
             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
-    public ContainerConfigs viewAllContainers() {
+    public ContainerConfigs viewAllContainers(@QueryParam("_q") String queryString) {
 
         handleNetworkAuthorization(getUserName());
 
         IContainerManager containerManager = getContainerManager();
-
-        return new ContainerConfigs(containerManager.getContainerConfigList());
+        ContainerConfigs result = new ContainerConfigs(
+                containerManager.getContainerConfigList());
+        if (queryString != null) {
+            queryContext.createQuery(queryString, ContainerConfigs.class)
+                .filter(result, ContainerConfig.class);
+        }
+        return result;
     }
 
     /**
@@ -481,7 +497,8 @@ public class ContainerManagerNorthbound {
     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
             @ResponseCode(code = 404, condition = "The container is not found"),
             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
-    public FlowSpecConfigs viewContainerFlowSpecs(@PathParam(value = "container") String container) {
+    public FlowSpecConfigs viewContainerFlowSpecs(@PathParam(value = "container") String container,
+        @QueryParam("_q") String queryString) {
 
         handleContainerAuthorization(container, getUserName());
         handleForbiddenOnDefault(container);
@@ -489,8 +506,13 @@ public class ContainerManagerNorthbound {
         handleContainerNotExists(container);
 
         IContainerManager containerManager = getContainerManager();
-
-        return new FlowSpecConfigs(containerManager.getContainerFlows(container));
+        FlowSpecConfigs result = new FlowSpecConfigs(
+                containerManager.getContainerFlows(container));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, FlowSpecConfigs.class)
+                .filter(result, ContainerFlowConfig.class);
+        }
+        return result;
     }
 
     /**
index b9d2200180dbd858c17624dbaa7b2bd8e0c97038..db3d543a69d9d948e77f67fe8bd68a76fb797fd7 100644 (file)
@@ -11,8 +11,11 @@ package org.opendaylight.controller.containermanager.northbound;
 
 import java.util.HashSet;
 import java.util.Set;
+
 import javax.ws.rs.core.Application;
 
+import org.opendaylight.controller.northbound.commons.query.QueryContextProvider;
+
 import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
 
 /**
@@ -28,6 +31,7 @@ public class ContainerManagerNorthboundRSApplication extends Application {
         Set<Class<?>> classes = new HashSet<Class<?>>();
         classes.add(ContainerManagerNorthbound.class);
         classes.add(JacksonJaxbJsonProvider.class);
+        classes.add(QueryContextProvider.class);
         return classes;
     }
 }
index 07d34cb6d4ee7e20ff48c387d8275687837c445e..89d2b99cadb7b89409a11fb600638edd8897ed2d 100644 (file)
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.utils,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.sal.authorization,
               javax.ws.rs,
+              javax.ws.rs.ext,
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
index 003f8b3b95df37b465ad04caf487181614511ddc..aaf93d1f4bacb0c73ace34595121f6641ce33323 100644 (file)
@@ -25,6 +25,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -36,6 +37,7 @@ import org.opendaylight.controller.northbound.commons.exception.BadRequestExcept
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.Property;
@@ -55,6 +57,14 @@ import org.opendaylight.controller.switchmanager.ISwitchManager;
 public class ControllerManagerNorthbound {
 
     private String username;
+    private QueryContext queryContext;
+
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
 
     @Context
     public void setSecurityContext(SecurityContext context) {
@@ -122,7 +132,8 @@ public class ControllerManagerNorthbound {
             @ResponseCode(code = 404, condition = "The containerName or property is not found"),
             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public ControllerProperties getControllerProperties(@PathParam("containerName") String containerName,
-            @QueryParam("propertyName") String propertyName) {
+            @QueryParam("propertyName") String propertyName,
+            @QueryParam("_q") String queryString) {
 
         if (!isValidContainer(containerName)) {
             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
@@ -147,8 +158,12 @@ public class ControllerManagerNorthbound {
             throw new ResourceNotFoundException("Unable to find property with name: " + propertyName);
         }
         properties.add(property);
-
-        return new ControllerProperties(properties);
+        ControllerProperties result = new ControllerProperties(properties);
+        if (queryString != null) {
+            queryContext.createQuery(queryString, ControllerProperties.class)
+                .filter(result, Property.class);
+        }
+        return result;
 
     }
 
index 205b68a91c9859055d51aa0d043b6ce42abd6dd9..43797f5c6558d84cca3f256d6f2bbdcf4f380407 100644 (file)
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.utils,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.sal.authorization,
               org.opendaylight.controller.usermanager,
               com.sun.jersey.spi.container.servlet,
               org.apache.catalina.filters,
               javax.ws.rs,
+              javax.ws.rs.ext,
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
index 4928ddef3b0296b8525531791dfe4272064dfaa1..42bd59ea4577ff5c6d40b3ad4e8efaa976c900f5 100644 (file)
@@ -19,10 +19,12 @@ 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.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -37,6 +39,7 @@ import org.opendaylight.controller.northbound.commons.exception.NotAcceptableExc
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.Node;
@@ -62,6 +65,14 @@ public class FlowProgrammerNorthbound {
 
     private String username;
 
+    private QueryContext queryContext;
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
+
     @Context
     public void setSecurityContext(SecurityContext context) {
         if (context != null && context.getUserPrincipal() != null) {
@@ -194,15 +205,21 @@ public class FlowProgrammerNorthbound {
     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
         @ResponseCode(code = 404, condition = "The containerName is not found"),
-        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
-    public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName) {
+        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable"),
+        @ResponseCode(code = 400, condition = "Incorrect query syntex")})
+    public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName,
+                   @QueryParam("_q") String queryString) {
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
                     + containerName);
         }
 
-        List<FlowConfig> flowConfigs = getStaticFlowsInternal(containerName, null);
-        return new FlowConfigs(flowConfigs);
+        FlowConfigs result = new FlowConfigs(getStaticFlowsInternal(containerName, null));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, FlowConfigs.class)
+                .filter(result, FlowConfig.class);
+        }
+        return result;
     }
 
     /**
@@ -272,7 +289,8 @@ public class FlowProgrammerNorthbound {
         @ResponseCode(code = 404, condition = "The containerName or nodeId is not found"),
         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName,
-            @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId) {
+            @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
+            @QueryParam("_q") String queryString) {
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
                     + containerName);
@@ -281,8 +299,12 @@ public class FlowProgrammerNorthbound {
         if (node == null) {
             throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString());
         }
-        List<FlowConfig> flows = getStaticFlowsInternal(containerName, node);
-        return new FlowConfigs(flows);
+        FlowConfigs flows = new FlowConfigs(getStaticFlowsInternal(containerName, node));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, FlowConfigs.class)
+                .filter(flows, FlowConfig.class);
+        }
+        return flows;
     }
 
     /**
index bf1b082cfef7eecb48f4c8861eebbd0b97b74e39..c8415f8b4f77cc63496d3a8abaa5abe0810da9b4 100644 (file)
               com.sun.jersey.spi.container.servlet,
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.northbound.commons.utils,
               org.opendaylight.controller.sal.authorization,
               org.opendaylight.controller.sal.packet.address,
               javax.ws.rs,
               javax.ws.rs.core,
+              javax.ws.rs.ext,
               javax.xml.bind.annotation,
               javax.xml.bind,
               org.slf4j,
index 74c13d11f129943ba45e449411adfbc9f09d41e3..d7579c82e10bdd378dd603bfee9c4fde1d0ad414 100644 (file)
@@ -21,11 +21,13 @@ 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.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -39,6 +41,7 @@ import org.opendaylight.controller.northbound.commons.exception.ResourceConflict
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.Node;
@@ -69,6 +72,14 @@ import org.opendaylight.controller.switchmanager.ISwitchManager;
 public class HostTrackerNorthbound {
 
     private String username;
+    private QueryContext queryContext;
+
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
 
     @Context
     public void setSecurityContext(SecurityContext context) {
@@ -107,7 +118,7 @@ public class HostTrackerNorthbound {
         return hostTracker;
     }
 
-    private Hosts convertHosts(Set<HostNodeConnector> hostNodeConnectors) {
+    private Set<HostConfig> convertHosts(Set<HostNodeConnector> hostNodeConnectors) {
         if(hostNodeConnectors == null) {
             return null;
         }
@@ -115,7 +126,7 @@ public class HostTrackerNorthbound {
         for(HostNodeConnector hnc : hostNodeConnectors) {
             hosts.add(HostConfig.convert(hnc));
         }
-        return new Hosts(hosts);
+        return hosts;
     }
 
     /**
@@ -194,14 +205,20 @@ public class HostTrackerNorthbound {
             @ResponseCode(code = 200, condition = "Operation successful"),
             @ResponseCode(code = 404, condition = "The containerName is not found"),
             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
-    public Hosts getActiveHosts(@PathParam("containerName") String containerName) {
+    public Hosts getActiveHosts(@PathParam("containerName") String containerName,
+        @QueryParam("_q") String queryString) {
 
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
                     + containerName);
         }
         IfIptoHost hostTracker = getIfIpToHostService(containerName);
-        return convertHosts(hostTracker.getAllHosts());
+        Hosts hosts = new Hosts(convertHosts(hostTracker.getAllHosts()));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, Hosts.class)
+                .filter(hosts, HostConfig.class);
+        }
+        return hosts;
     }
 
     /**
@@ -281,13 +298,19 @@ public class HostTrackerNorthbound {
             @ResponseCode(code = 404, condition = "The containerName is not found"),
             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public Hosts getInactiveHosts(
-            @PathParam("containerName") String containerName) {
+            @PathParam("containerName") String containerName,
+            @QueryParam("_q") String queryString) {
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
                     + containerName);
         }
         IfIptoHost hostTracker = getIfIpToHostService(containerName);
-        return convertHosts(hostTracker.getInactiveStaticHosts());
+        Hosts hosts = new Hosts(convertHosts(hostTracker.getInactiveStaticHosts()));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, Hosts.class)
+                .filter(hosts, HostConfig.class);
+        }
+        return hosts;
     }
 
     /**
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/INeutronRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/INeutronRequest.java
new file mode 100644 (file)
index 0000000..8e0ff5c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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
+ *
+ *  Authors : Dave Tucker
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.INeutronObject;
+
+import java.util.List;
+
+public interface INeutronRequest<T extends INeutronObject> {
+    public T getSingleton();
+    public boolean isSingleton();
+    public List<T> getBulk();
+}
index cebd3c267dd1a1ad2d3b345f2f97d498046631b0..a4c113c2c1803081409e61c4132770482d51f3c0 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
 
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
-public class NeutronNetworkRequest {
+public class NeutronNetworkRequest implements INeutronRequest {
     // See OpenStack Network API v2.0 Reference for description of
     // annotated attributes
 
@@ -29,9 +29,18 @@ public class NeutronNetworkRequest {
     @XmlElement(name="networks")
     List<NeutronNetwork> bulkRequest;
 
+    @XmlElement(name="networks_links")
+    List<NeutronPageLink> links;
+
     NeutronNetworkRequest() {
     }
 
+    NeutronNetworkRequest(List<NeutronNetwork> bulkRequest, List<NeutronPageLink> links) {
+        this.bulkRequest = bulkRequest;
+        this.links = links;
+        this.singletonNetwork = null;
+    }
+
     NeutronNetworkRequest(List<NeutronNetwork> bulk) {
         bulkRequest = bulk;
         singletonNetwork = null;
index 52c3337e40047fb844352fd9dcc0b6c596fcb8d0..9de5aef5f421eb2436ac73a6dff63e24efcf4c64 100644 (file)
@@ -9,8 +9,6 @@
 package org.opendaylight.controller.networkconfig.neutron.northbound;
 
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -33,6 +31,7 @@ import javax.ws.rs.core.Response;
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
 import org.codehaus.enunciate.jaxrs.TypeHint;
+
 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
 import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
@@ -95,13 +94,13 @@ public class NeutronNetworksNorthbound {
             @QueryParam("provider_network_type") String queryProviderNetworkType,
             @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,
             @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,
-            // pagination
+            // linkTitle
             @QueryParam("limit") Integer limit,
             @QueryParam("marker") String marker,
             @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse
             // sorting not supported
             ) {
-        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+        INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
         if (networkInterface == null) {
             throw new ServiceUnavailableException("Network CRUD Interface "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
@@ -139,89 +138,11 @@ public class NeutronNetworksNorthbound {
             }
         }
 
-        Comparator<NeutronNetwork> neutronNetworkComparator = new Comparator<NeutronNetwork>() {
-            @Override
-            public int compare(NeutronNetwork o1, NeutronNetwork o2) {
-                return o1.getID().compareTo(o2.getID());
-            }
-        };
-
-        Collections.sort(ans, neutronNetworkComparator);
-
         if (limit != null && ans.size() > 1) {
-            List<NeutronPageLink> links = new ArrayList<>();
-            Integer startPos = null;
-            String startMarker;
-            String endMarker;
-            Boolean firstPage = false;
-            Boolean lastPage = false;
-
-            if (marker == null) {
-                startPos = 0;
-            }
-
-            else {
-
-                NeutronNetwork markerNetwork = new NeutronNetwork();
-                markerNetwork.setNetworkUUID(marker);
-
-                startPos = Collections.binarySearch(ans, markerNetwork, neutronNetworkComparator);
-
-                if (!pageReverse){
-                    startPos = startPos + 1;
-                }
-                else {
-                    startPos = startPos - limit;
-                }
-
-            }
-
-            if (startPos == null) {
-                throw new ResourceNotFoundException("UUID for marker:" + marker + " could not be found");
-            }
-
-            if (startPos == 0){
-                firstPage = true;
-            }
-
-            if (startPos + limit >= ans.size()) {
-                ans = ans.subList(startPos, ans.size());
-                startMarker = ans.get(0).getID();
-                endMarker = ans.get(ans.size() - 1).getID();
-                lastPage = true;
-            }
-            else if (startPos < 0) {
-                if (startPos + limit > 0) {
-                    ans = ans.subList(0, startPos + limit);
-                    startMarker = ans.get(0).getID();
-                    endMarker = ans.get(ans.size() - 1).getID();
-                    firstPage = true;
-                }
-                else {
-                    throw new BadRequestException("Requested page is out of bounds. Please check the supplied limit and marker");
-                }
-            }
-            else {
-                ans = ans.subList(startPos, startPos + limit);
-                startMarker = ans.get(0).getID();
-                endMarker = ans.get(limit-1).getID();
-            }
-
-            if (!lastPage) {
-                NeutronPageLink next = new NeutronPageLink();
-                next.setRef("next");
-                next.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + endMarker);
-                links.add(next);
-            }
-
-            if (!firstPage) {
-                NeutronPageLink previous = new NeutronPageLink();
-                previous.setRef("previous");
-                previous.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + startMarker + "&page_reverse=True");
-                links.add(previous);
-            }
-
-            return Response.status(200).entity(new PaginatedNeutronNetworkRequest(ans, links)).build();
+            // Return a paginated request
+            NeutronNetworkRequest request = (NeutronNetworkRequest) PaginatedRequestFactory.createRequest(limit,
+                    marker, pageReverse, uriInfo, ans, NeutronNetwork.class);
+            return Response.status(200).entity(request).build();
         }
 
     return Response.status(200).entity(new NeutronNetworkRequest(ans)).build();
index 9b3399d9a8bfe72266843b0d4d8c34d6b163ef52..12b58aa2abc54e30799fd0458a4e126b9185124a 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
 
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
-public class NeutronPortRequest {
+public class NeutronPortRequest implements INeutronRequest {
     // See OpenStack Network API v2.0 Reference for description of
     // annotated attributes
 
@@ -29,9 +29,18 @@ public class NeutronPortRequest {
     @XmlElement(name="ports")
     List<NeutronPort> bulkRequest;
 
+    @XmlElement(name="ports_links")
+    List<NeutronPageLink> links;
+
     NeutronPortRequest() {
     }
 
+    public NeutronPortRequest(List<NeutronPort> bulkRequest, List<NeutronPageLink> links) {
+        this.bulkRequest = bulkRequest;
+        this.links = links;
+        this.singletonPort = null;
+    }
+
     NeutronPortRequest(List<NeutronPort> bulk) {
         bulkRequest = bulk;
         singletonPort = null;
index 1a2512fde3c3fd6c689a872f9ee148bba4a67521..5451fbf3e129e4be88addabcc7816e308c2cb2b7 100644 (file)
@@ -15,6 +15,7 @@ import java.util.List;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -22,8 +23,10 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -69,6 +72,9 @@ public class NeutronPortsNorthbound {
         return o.extractFields(fields);
     }
 
+    @Context
+    UriInfo uriInfo;
+
     /**
      * Returns a list of all Ports */
 
@@ -92,10 +98,10 @@ public class NeutronPortsNorthbound {
             @QueryParam("device_id") String queryDeviceID,
             @QueryParam("device_owner") String queryDeviceOwner,
             @QueryParam("tenant_id") String queryTenantID,
-            // pagination
-            @QueryParam("limit") String limit,
+            // linkTitle
+            @QueryParam("limit") Integer limit,
             @QueryParam("marker") String marker,
-            @QueryParam("page_reverse") String pageReverse
+            @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse
             // sorting not supported
             ) {
         INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
@@ -124,7 +130,14 @@ public class NeutronPortsNorthbound {
                 }
             }
         }
-        //TODO: apply pagination to results
+
+        if (limit != null && ans.size() > 1) {
+            // Return a paginated request
+            NeutronPortRequest request = (NeutronPortRequest) PaginatedRequestFactory.createRequest(limit,
+                    marker, pageReverse, uriInfo, ans, NeutronPort.class);
+            return Response.status(200).entity(request).build();
+        }
+
         return Response.status(200).entity(
                 new NeutronPortRequest(ans)).build();
     }
index aed9db58bd34c3255c54830c8b76957da6d4de5c..57a724c1cc60936b3a15ed80ba0c1b9bc6d53288 100644 (file)
@@ -20,7 +20,7 @@ import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
 
-public class NeutronSubnetRequest {
+public class NeutronSubnetRequest implements INeutronRequest {
     // See OpenStack Network API v2.0 Reference for description of
     // annotated attributes
 
@@ -30,16 +30,28 @@ public class NeutronSubnetRequest {
     @XmlElement(name="subnets")
     List<NeutronSubnet> bulkRequest;
 
+    @XmlElement(name="subnets_links")
+    List<NeutronPageLink> links;
+
     NeutronSubnetRequest() {
     }
 
+    public NeutronSubnetRequest(List<NeutronSubnet> bulkRequest, List<NeutronPageLink> links) {
+        this.bulkRequest = bulkRequest;
+        this.links = links;
+        this.singletonSubnet = null;
+    }
+
     NeutronSubnetRequest(List<NeutronSubnet> bulk) {
         bulkRequest = bulk;
         singletonSubnet = null;
+        links = null;
     }
 
     NeutronSubnetRequest(NeutronSubnet subnet) {
         singletonSubnet = subnet;
+        bulkRequest = null;
+        links = null;
     }
 
     public NeutronSubnet getSingleton() {
index f397eb3a97b0630002b3fc1b70901a1a25cf0609..8f20269603b1ed1802fc04812974125016c1811b 100644 (file)
@@ -13,8 +13,10 @@ 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.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -22,8 +24,10 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -65,6 +69,8 @@ public class NeutronSubnetsNorthbound {
         return o.extractFields(fields);
     }
 
+    @Context
+    UriInfo uriInfo;
 
     /**
      * Returns a list of all Subnets */
@@ -89,13 +95,13 @@ public class NeutronSubnetsNorthbound {
             @QueryParam("tenant_id") String queryTenantID,
             @QueryParam("ipv6_address_mode") String queryIpV6AddressMode,
             @QueryParam("ipv6_ra_mode") String queryIpV6RaMode,
-            // pagination
-            @QueryParam("limit") String limit,
+            // linkTitle
+            @QueryParam("limit") Integer limit,
             @QueryParam("marker") String marker,
-            @QueryParam("page_reverse") String pageReverse
+            @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse
             // sorting not supported
             ) {
-        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+        INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
         if (subnetInterface == null) {
             throw new ServiceUnavailableException("Subnet CRUD Interface "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
@@ -122,7 +128,14 @@ public class NeutronSubnetsNorthbound {
                 }
             }
         }
-        //TODO: apply pagination to results
+
+        if (limit != null && ans.size() > 1) {
+            // Return a paginated request
+            NeutronSubnetRequest request = (NeutronSubnetRequest) PaginatedRequestFactory.createRequest(limit,
+                    marker, pageReverse, uriInfo, ans, NeutronSubnet.class);
+            return Response.status(200).entity(request).build();
+        }
+
         return Response.status(200).entity(
                 new NeutronSubnetRequest(ans)).build();
     }
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java
deleted file mode 100644 (file)
index c050661..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2014 Hewlett-Packard Development Company L.P
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Authors : Dave Tucker
- */
-
-package org.opendaylight.controller.networkconfig.neutron.northbound;
-
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import java.util.List;
-
-@XmlRootElement
-@XmlAccessorType(XmlAccessType.NONE)
-
-public class PaginatedNeutronNetworkRequest {
-
-    @XmlElement (name="networks")
-    List<NeutronNetwork> networks;
-
-    @XmlElement (name="network_links")
-    List<NeutronPageLink> networkLinks;
-
-    public PaginatedNeutronNetworkRequest() {
-    }
-
-    public PaginatedNeutronNetworkRequest(List<NeutronNetwork> networks, List<NeutronPageLink> networkLinks) {
-        this.networks = networks;
-        this.networkLinks = networkLinks;
-    }
-
-    public List<NeutronNetwork> getNetworks() {
-        return networks;
-    }
-
-    public void setNetworks(List<NeutronNetwork> networks) {
-        this.networks = networks;
-    }
-
-    public List<NeutronPageLink> getNetworkLinks() {
-        return networkLinks;
-    }
-
-    public void setNetworkLinks(List<NeutronPageLink> networkLinks) {
-        this.networkLinks = networkLinks;
-    }
-}
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedRequestFactory.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedRequestFactory.java
new file mode 100644 (file)
index 0000000..8f05e76
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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
+ *
+ *  Authors : Dave Tucker
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.INeutronObject;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+
+import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class PaginatedRequestFactory {
+
+    public static class PaginationResults<T extends INeutronObject> {
+        List<T> collection;
+        List<NeutronPageLink> links;
+
+        public PaginationResults(List<T> collection, List<NeutronPageLink> links) {
+            this.collection = collection;
+            this.links = links;
+        }
+    }
+
+    public static <T extends INeutronObject> INeutronRequest createRequest(Integer limit, String marker,
+                                                                           Boolean pageReverse,
+                                                                           UriInfo uriInfo,
+                                                                           List<T> collection,
+                                                                           Class<T> clazz) {
+        PaginationResults results = _paginate(limit, marker, pageReverse, uriInfo, collection);
+
+        if (clazz.equals(NeutronNetwork.class)){
+            return new NeutronNetworkRequest(results.collection, results.links);
+        }
+        if (clazz.equals(NeutronSubnet.class)){
+            return new NeutronSubnetRequest(results.collection, results.links);
+        }
+        if (clazz.equals(NeutronPort.class)){
+            return new NeutronPortRequest(results.collection, results.links);
+        }
+        return null;
+    }
+
+    private static <T extends INeutronObject> PaginationResults _paginate(Integer limit, String marker, Boolean pageReverse, UriInfo uriInfo, List<T> collection) {
+        List<NeutronPageLink> links = new ArrayList<>();
+        Integer startPos = null;
+        String startMarker;
+        String endMarker;
+        Boolean firstPage = false;
+        Boolean lastPage = false;
+
+        Comparator<INeutronObject> neutronObjectComparator = new Comparator<INeutronObject>() {
+            @Override
+            public int compare(INeutronObject o1, INeutronObject o2) {
+                return o1.getID().compareTo(o2.getID());
+            }
+        };
+
+        Collections.sort(collection, neutronObjectComparator);
+
+        if (marker == null) {
+            startPos = 0;
+        }
+
+        else {
+
+            class MarkerObject implements INeutronObject {
+                private String id;
+
+                public String getID() {
+                    return id;
+                }
+
+                public void setID(String id) {
+                    this.id = id;
+                }
+            }
+
+            INeutronObject markerObject = new MarkerObject();
+
+            markerObject.setID(marker);
+
+            startPos = Collections.binarySearch(collection, markerObject, neutronObjectComparator);
+
+            if (!pageReverse){
+                startPos = startPos + 1;
+            }
+            else {
+                startPos = startPos - limit;
+            }
+
+        }
+
+        if (startPos == null) {
+            throw new ResourceNotFoundException("UUID for marker:" + marker + " could not be found");
+        }
+
+        if (startPos == 0){
+            firstPage = true;
+        }
+
+        if (startPos + limit >= collection.size()) {
+            collection = collection.subList(startPos, collection.size());
+            startMarker = collection.get(0).getID();
+            endMarker = collection.get(collection.size() - 1).getID();
+            lastPage = true;
+        }
+        else if (startPos < 0) {
+            if (startPos + limit > 0) {
+                collection = collection.subList(0, startPos + limit);
+                startMarker = collection.get(0).getID();
+                endMarker = collection.get(collection.size() - 1).getID();
+                firstPage = true;
+            }
+            else {
+                throw new BadRequestException("Requested page is out of bounds. Please check the supplied limit and marker");
+            }
+        }
+        else {
+            collection = collection.subList(startPos, startPos + limit);
+            startMarker = collection.get(0).getID();
+            endMarker = collection.get(limit-1).getID();
+        }
+
+        if (!lastPage) {
+            NeutronPageLink next = new NeutronPageLink();
+            next.setRef("next");
+            next.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + endMarker);
+            links.add(next);
+        }
+
+        if (!firstPage) {
+            NeutronPageLink previous = new NeutronPageLink();
+            previous.setRef("previous");
+            previous.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + startMarker + "&page_reverse=True");
+            links.add(previous);
+        }
+
+        return new PaginationResults(collection, links);
+    }
+}
index dd2a2e6223bb5ab19d776fa71093ad70e89d2bc3..83f8191e025e1c4d23d3bd8673f2ed0046ff9408 100644 (file)
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.utils,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.sal.authorization,
               org.slf4j,
               javax.ws.rs,
+              javax.ws.rs.ext,
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
index e765af524d5a6e215531bc7682a644b3d277339c..20f6cb40a56cb812fa5370a5dd01cc6bf2ef85e8 100644 (file)
@@ -19,11 +19,13 @@ 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.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -37,6 +39,7 @@ import org.opendaylight.controller.northbound.commons.exception.NotAcceptableExc
 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
@@ -74,6 +77,14 @@ import org.opendaylight.controller.sal.utils.Status;
 public class StaticRoutingNorthbound {
 
     private String username;
+    private QueryContext queryContext;
+
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
 
     @Context
     public void setSecurityContext(SecurityContext context) {
@@ -148,7 +159,8 @@ public class StaticRoutingNorthbound {
             @ResponseCode(code = 200, condition = "Operation successful"),
             @ResponseCode(code = 404, condition = "The containerName passed was not found") })
     public StaticRoutes getStaticRoutes(
-            @PathParam("containerName") String containerName) {
+            @PathParam("containerName") String containerName,
+            @QueryParam("_q") String queryString) {
 
         if(!NorthboundUtils.isAuthorized(getUserName(), containerName,
                 Privilege.WRITE, this)){
@@ -156,7 +168,12 @@ public class StaticRoutingNorthbound {
                 UnauthorizedException("User is not authorized to perform this operation on container "
                             + containerName);
         }
-        return new StaticRoutes(getStaticRoutesInternal(containerName));
+        StaticRoutes result = new StaticRoutes(getStaticRoutesInternal(containerName));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, StaticRoutes.class)
+                .filter(result, StaticRoute.class);
+        }
+        return result;
     }
 
     /**
index 76ce062424b32568f9838e8ab05476ace1201439..7e2919bc44c1a7f698f2afe77c31d3347de3fc4a 100644 (file)
@@ -64,7 +64,9 @@
                 org.opendaylight.controller.northbound.commons,
                 org.opendaylight.controller.northbound.commons.exception,
                 org.opendaylight.controller.northbound.commons.utils,
+                org.opendaylight.controller.northbound.commons.query,
                 javax.ws.rs,
+                javax.ws.rs.ext,
                 javax.ws.rs.core,
                 javax.xml.bind.annotation,
                 javax.xml.bind,
index 5338849a62626ed740c6d930d72064efa1dca4d2..4175f1e3c49984c7d90ac03b2207df946c9f7e3a 100644 (file)
@@ -15,9 +15,11 @@ import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -29,6 +31,7 @@ import org.opendaylight.controller.northbound.commons.exception.ResourceConflict
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.Node;
@@ -57,7 +60,14 @@ import org.opendaylight.controller.switchmanager.ISwitchManager;
 public class StatisticsNorthbound {
 
     private String username;
+    private QueryContext queryContext;
 
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
     @Context
     public void setSecurityContext(SecurityContext context) {
         if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
@@ -234,7 +244,8 @@ public class StatisticsNorthbound {
         @ResponseCode(code = 404, condition = "The containerName is not found"),
         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public AllFlowStatistics getFlowStatistics(
-            @PathParam("containerName") String containerName) {
+            @PathParam("containerName") String containerName,
+            @QueryParam("_q") String queryString) {
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException(
@@ -265,7 +276,12 @@ public class StatisticsNorthbound {
             FlowStatistics stat = new FlowStatistics(node, flowStats);
             statistics.add(stat);
         }
-        return new AllFlowStatistics(statistics);
+        AllFlowStatistics result = new AllFlowStatistics(statistics);
+        if (queryString != null) {
+            queryContext.createQuery(queryString, AllFlowStatistics.class)
+                .filter(result, FlowStatistics.class);
+        }
+        return result;
     }
 
     /**
@@ -610,7 +626,8 @@ public class StatisticsNorthbound {
         @ResponseCode(code = 404, condition = "The containerName is not found"),
         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public AllPortStatistics getPortStatistics(
-            @PathParam("containerName") String containerName) {
+            @PathParam("containerName") String containerName,
+            @QueryParam("_q") String queryString) {
 
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.READ, this)) {
@@ -638,7 +655,13 @@ public class StatisticsNorthbound {
             PortStatistics portStat = new PortStatistics(node, stat);
             statistics.add(portStat);
         }
-        return new AllPortStatistics(statistics);
+
+        AllPortStatistics result = new AllPortStatistics(statistics);
+        if (queryString != null) {
+            queryContext.createQuery(queryString, AllPortStatistics.class)
+                .filter(result, PortStatistics.class);
+        }
+        return result;
     }
 
     /**
@@ -924,7 +947,8 @@ public class StatisticsNorthbound {
         @ResponseCode(code = 404, condition = "The containerName is not found"),
         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public AllTableStatistics getTableStatistics(
-            @PathParam("containerName") String containerName) {
+            @PathParam("containerName") String containerName,
+            @QueryParam("_q") String queryString) {
 
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
@@ -952,7 +976,12 @@ public class StatisticsNorthbound {
             TableStatistics tableStat = new TableStatistics(node, stat);
             statistics.add(tableStat);
         }
-        return new AllTableStatistics(statistics);
+        AllTableStatistics allstats = new AllTableStatistics(statistics);
+        if (queryString != null) {
+            queryContext.createQuery(queryString, AllTableStatistics.class)
+                .filter(allstats, TableStatistics.class);
+        }
+        return allstats;
     }
 
     /**
index 5aa2f7f202a00c30eff3937d0f7bb34efb76cf0c..630221fcc2dac2b0c53a945cbeaf41ef63c9a1cd 100644 (file)
               org.opendaylight.controller.switchmanager,
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.northbound.commons.utils,
               com.sun.jersey.spi.container.servlet,
               org.opendaylight.controller.sal.authorization,
               org.opendaylight.controller.usermanager,
               javax.ws.rs,
               javax.ws.rs.core,
+              javax.ws.rs.ext,
               javax.xml.bind,
               javax.xml.bind.annotation,
               org.slf4j,
index 3465dc95addd727ade9243e3410208cc7735ec40..b6274795df9279275e1b1d7e145aa2fa3055914b 100644 (file)
@@ -19,11 +19,13 @@ 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.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -35,6 +37,7 @@ import org.opendaylight.controller.northbound.commons.exception.ResourceConflict
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.NodeConnector;
@@ -63,6 +66,14 @@ public class SubnetsNorthbound {
     protected static final Logger logger = LoggerFactory.getLogger(SubnetsNorthbound.class);
 
     private String username;
+    private QueryContext queryContext;
+
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
 
     @Context
     public void setSecurityContext(SecurityContext context) {
@@ -160,9 +171,11 @@ public class SubnetsNorthbound {
     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @StatusCodes({ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
         @ResponseCode(code = 404, condition = "The containerName passed was not found"),
-        @ResponseCode(code = 503, condition = "Service unavailable") })
+        @ResponseCode(code = 503, condition = "Service unavailable"),
+        @ResponseCode(code = 400, condition = "Incorrect query syntex") })
     @TypeHint(SubnetConfigs.class)
-    public SubnetConfigs listSubnets(@PathParam("containerName") String containerName) {
+    public SubnetConfigs listSubnets(@PathParam("containerName") String containerName,
+        @QueryParam("_q") String queryString) {
 
         handleContainerDoesNotExist(containerName);
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
@@ -174,7 +187,13 @@ public class SubnetsNorthbound {
         if (switchManager == null) {
             throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
         }
-        return new SubnetConfigs(switchManager.getSubnetsConfigList());
+        List<SubnetConfig> subnets = switchManager.getSubnetsConfigList();
+        if (queryString != null) {
+            subnets = queryContext.createQuery(queryString, SubnetConfig.class)
+                    .find(subnets);
+
+        }
+        return new SubnetConfigs(subnets);
     }
 
     /**
diff --git a/opendaylight/northbound/swagger-ui/pom.xml b/opendaylight/northbound/swagger-ui/pom.xml
new file mode 100644 (file)
index 0000000..18eaed9
--- /dev/null
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <artifactId>swagger-ui</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <api.dir>${resource.dir}/apis</api.dir>
+    <resource.dir>${project.build.directory}/classes</resource.dir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>javax.servlet</artifactId>
+    </dependency>
+    <!-- add dependency on all northbound bundles -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>connectionmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>controllermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flowprogrammer.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwarding.staticrouting.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statistics.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>subnets.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topology.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>usermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package></Export-Package>
+            <Import-Package>org.slf4j,
+              javax.annotation,
+              javax.naming,
+              javax.servlet,
+              javax.servlet.annotation,
+              javax.servlet.http,
+              com.google.gson,</Import-Package>
+            <Export-Package></Export-Package>
+            <Include-Resource>apis=target/classes/apis,
+                index.html=target/classes/index.html,
+                apilist.json=target/classes/apilist.json,
+                css=target/classes/css,
+                lib=target/classes/lib,
+                swagger-ui.min.js=target/classes/swagger-ui.min.js,
+                swagger-ui.js=target/classes/swagger-ui.js,
+                images=target/classes/images,
+                WEB-INF/web.xml=target/classes/WEB-INF/web.xml</Include-Resource>
+            <Web-ContextPath>/swagger</Web-ContextPath>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.7</version>
+        <dependencies>
+          <dependency>
+            <groupId>ant-contrib</groupId>
+            <artifactId>ant-contrib</artifactId>
+            <version>1.0b3</version>
+            <exclusions>
+              <exclusion>
+                <groupId>ant</groupId>
+                <artifactId>ant</artifactId>
+              </exclusion>
+            </exclusions>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <target>
+                <taskdef classpathref="maven.plugin.classpath" resource="net/sf/antcontrib/antlib.xml"></taskdef>
+                <patternset id="rest.paths">
+                  <include name="**/enunciate/generate/swagger/ui/*.json"></include>
+                  <exclude name="**/java-client/**"></exclude>
+                  <exclude name="**/swagger-ui/**"></exclude>
+                </patternset>
+
+                <echo message="======== Assembling swagger docs ========"></echo>
+                <!-- make api directory -->
+                <mkdir dir="${api.dir}"></mkdir>
+                <!--  copy swagger libs -->
+                <copy todir="${resource.dir}">
+                  <fileset dir="../subnets/target/enunciate/generate/swagger/ui">
+                    <exclude name="**/*.json"></exclude>
+                    <exclude name="**/*.png"></exclude>
+                    <exclude name="**/index.html"></exclude>
+                  </fileset>
+                </copy>
+                <!--  Copy NorthBound json files into ui directory-->
+                <copy todir="${api.dir}">
+                  <fileset dir="${basedir}/../../..">
+                    <patternset refid="rest.paths"></patternset>
+                  </fileset>
+                  <mapper>
+                    <regexpmapper from="^(.*)/([^/]+)/*/target/enunciate/generate/swagger/ui/(.*Northbound).*$$" to="\3"></regexpmapper>
+                    <regexpmapper from="^(.*)/([^/]+)/*/target/enunciate/generate/swagger/ui/(.*resource-list.json)$$" to="\2-\3"></regexpmapper>
+                  </mapper>
+                </copy>
+
+                <!--  Correct base path -->
+                <replaceregexp match="/full" replace="">
+                  <fileset dir="${api.dir}">
+                    <include name="**/*Northbound"></include>
+                  </fileset>
+                </replaceregexp>
+                <!--  Merge Resource list -->
+                <echo append="false" file="${resource.dir}/apilist.json">{
+  "swaggerVersion": "1.1",
+  "basePath": "http://localhost:8080/swagger/apis",
+  "apis": [</echo>
+                <for param="file">
+                  <path>
+                    <fileset dir="${api.dir}">
+                      <include name="**/*resource-list.json"></include>
+                      <exclude name="**/neutron*"></exclude>
+                    </fileset>
+                  </path>
+                  <sequential>
+                    <echo message="Processing json resource @{file}"></echo>
+                    <loadfile property="jsoncontent" srcfile="@{file}">
+                      <filterchain>
+                        <headfilter lines="10"></headfilter>
+                        <tailfilter lines="6"></tailfilter>
+                      </filterchain>
+                    </loadfile>
+                    <echo append="true" file="${resource.dir}/apilist.json" message="${jsoncontent},"></echo>
+                    <var name="jsoncontent" unset="true"></var>
+                  </sequential>
+                </for>
+                <sequential>
+                  <loadfile property="jsoncontent" srcfile="${api.dir}/neutron-resource-list.json">
+                    <filterchain>
+                      <headfilter lines="46"></headfilter>
+                      <tailfilter lines="42"></tailfilter>
+                    </filterchain>
+                  </loadfile>
+                  <echo append="true" file="${resource.dir}/apilist.json" message="${jsoncontent},"></echo>
+                  <var name="jsoncontent" unset="true"></var>
+                </sequential>
+                <echo append="true" file="${resource.dir}/apilist.json">{ }
+  ]
+}</echo>
+
+                <!-- Remove .json from api paths -->
+                <replaceregexp file="${resource.dir}/apilist.json" flags="g" match=".json" replace=""></replaceregexp>
+                <replaceregexp file="${resource.dir}/apilist.json" flags="g" match="JAXRS" replace=""></replaceregexp>
+
+                <!-- cleanup resource files as we don't need them -->
+                <delete>
+                  <fileset dir="${api.dir}" includes="**/*resource-list.json"></fileset>
+                </delete>
+                <echo message="======== Build successful ========"></echo>
+              </target>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+  </scm>
+</project>
diff --git a/opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java b/opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java
new file mode 100644 (file)
index 0000000..083a50c
--- /dev/null
@@ -0,0 +1,101 @@
+package org.opendaylight.controller.swaggerui;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * Servlet implementation class BasePathModifierServlet
+ */
+public class BasePathModifierServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+    private static final Logger logger = LoggerFactory
+            .getLogger(BasePathModifierServlet.class);
+
+    private static final String API_BASE_PATH_SUFFIX = "/swagger/apis";
+    private static final String BASE_PATH_KEY = "basePath";
+
+    /**
+     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
+     *      response)
+     */
+    @Override
+    protected void doGet(HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException {
+        String resourcePath = request.getRequestURI().substring(
+                request.getContextPath().length());
+        logger.debug("Locating resource : {}.", resourcePath);
+        JsonObject jsonObject = null;
+        try {
+
+            InputStream stream = this.getServletContext().getResourceAsStream(
+                    resourcePath);
+            if (stream == null) {
+                response.sendError(HttpServletResponse.SC_NOT_FOUND,
+                        "API / API Listing not found");
+                return;
+            }
+            BufferedReader streamReader = new BufferedReader(
+                    new InputStreamReader(stream, "UTF-8"));
+            StringBuilder responseStrBuilder = new StringBuilder();
+
+            String inputStr;
+            while ((inputStr = streamReader.readLine()) != null)
+                responseStrBuilder.append(inputStr);
+
+            JsonElement jelement = new JsonParser().parse(responseStrBuilder
+                    .toString());
+            jsonObject = jelement.getAsJsonObject();
+
+            String basePath = jsonObject.get(BASE_PATH_KEY).getAsString();
+
+            // construct base path
+            StringBuilder requestURL = new StringBuilder();
+
+            requestURL.append(request.isSecure() ? "https://" : "http://")
+                    .append(request.getServerName()).append(":")
+                    .append(request.getServerPort());
+            if (!basePath.contains(requestURL)) {
+                String endPath = "";
+                if (basePath.contains(API_BASE_PATH_SUFFIX)) {
+                    endPath = basePath.substring(basePath
+                            .indexOf(API_BASE_PATH_SUFFIX));
+                }
+                basePath = requestURL + endPath;
+                logger.debug("Modified Base Path is {}", basePath);
+                jsonObject.addProperty(BASE_PATH_KEY, basePath);
+            }
+        } catch (Exception ex) {
+            logger.error("Error processing JSON data", ex);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Could not read API Listing or APIs");
+            return;
+        }
+
+        try {
+            response.setContentType("application/json");
+            PrintWriter out = response.getWriter();
+            out.print(jsonObject);
+            out.flush();
+        } catch (Exception ex) {
+            logger.error("Error while writing response", ex);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Internal Error while writing resposne");
+        }
+    }
+
+}
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml b/opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..6d02390
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+  <servlet>
+     <servlet-name>BasePathModifierServlet</servlet-name>
+     <servlet-class>org.opendaylight.controller.swaggerui.BasePathModifierServlet</servlet-class>
+  </servlet>
+  <!-- Mapping for all northbound json files aka apis-->
+  <servlet-mapping>
+    <servlet-name>BasePathModifierServlet</servlet-name>
+    <url-pattern>/apis/*</url-pattern>
+  </servlet-mapping>
+  <!-- Mapping to get list of available NB apis -->
+  <servlet-mapping>
+    <servlet-name>BasePathModifierServlet</servlet-name>
+    <url-pattern>/apilist.json</url-pattern>
+  </servlet-mapping>
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+</web-app>
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css b/opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css
new file mode 100644 (file)
index 0000000..e393943
--- /dev/null
@@ -0,0 +1,12 @@
+body #header a#logo {
+    font-size: 1.5em;
+    font-weight: bold;
+    text-decoration: none;
+    background: transparent url(../images/logo.png) no-repeat left center;
+    padding: 20px 0 20px 70px;
+    color: white;
+}
+
+div.footer {
+    display: none;
+}
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png b/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png
new file mode 100644 (file)
index 0000000..d49fb86
Binary files /dev/null and b/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png differ
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/index.html b/opendaylight/northbound/swagger-ui/src/main/resources/index.html
new file mode 100644 (file)
index 0000000..bb5126c
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Swagger UI</title>
+    <link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
+    <link href='css/highlight.default.css' media='screen' rel='stylesheet' type='text/css'/>
+    <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
+    <link href='css/custom.css' media='screen' rel='stylesheet' type='text/css'/>
+    <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
+    <script src='lib/handlebars-1.0.rc.1.js' type='text/javascript'></script>
+    <script src='lib/underscore-min.js' type='text/javascript'></script>
+    <script src='lib/backbone-min.js' type='text/javascript'></script>
+    <script src='lib/swagger.js' type='text/javascript'></script>
+    <script src='swagger-ui.js' type='text/javascript'></script>
+    <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
+
+    <script type="text/javascript">
+    $(function () {
+        window.swaggerUi = new SwaggerUi({
+                discoveryUrl:"./apilist.json",
+                apiKey:"",
+                dom_id:"swagger-ui-container",
+                supportHeaderParams: false,
+                supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
+                onComplete: function(swaggerApi, swaggerUi){
+                    if(console) {
+                        console.log("Loaded SwaggerUI")
+                        console.log(swaggerApi);
+                        console.log(swaggerUi);
+                    }
+                  $('pre code').each(function(i, e) {hljs.highlightBlock(e)});
+                },
+                onFailure: function(data) {
+                    if(console) {
+                        console.log("Unable to Load SwaggerUI");
+                        console.log(data);
+                    }
+                },
+                docExpansion: "none"
+            });
+
+            window.swaggerUi.load();
+        });
+
+    </script>
+</head>
+
+<body>
+  <div id='header'>
+    <div class="swagger-ui-wrap">
+      <a id="logo" href="http://www.opendaylight.org/">ODL NB API</a>
+      <form id='api_selector'>
+        <div class='input'>
+          <input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/>
+        </div>
+        <div class='input'>
+          <input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/>
+        </div>
+        <div class='input'><a id="explore" href="#">Explore</a></div>
+      </form>
+    </div>
+  </div>
+
+  <div id="message-bar" class="swagger-ui-wrap">
+      &nbsp;
+  </div>
+
+  <div id="swagger-ui-container" class="swagger-ui-wrap">
+
+  </div>
+
+</body>
+
+</html>
index 590f0bb533dbf610990fb4082a10f8b220a86023..614ec8847658d87800de3f6319c076357020d269 100644 (file)
@@ -58,7 +58,9 @@
               org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.utils,
               org.opendaylight.controller.sal.authorization,
+              org.opendaylight.controller.northbound.commons.query,
               javax.ws.rs,
+              javax.ws.rs.ext,
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
index e30dad24ab18866b1c455a8facf7bf347a0d22b2..dab5d7d1b26785b6f2564d1d0ebb3fbecda861e5 100644 (file)
@@ -23,11 +23,13 @@ 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.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -38,6 +40,7 @@ import org.opendaylight.controller.northbound.commons.exception.InternalServerEr
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.Node;
@@ -60,6 +63,14 @@ import org.opendaylight.controller.switchmanager.SwitchConfig;
 public class SwitchNorthbound {
 
     private String username;
+    private QueryContext queryContext;
+
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
 
     @Context
     public void setSecurityContext(SecurityContext context) {
@@ -200,8 +211,9 @@ public class SwitchNorthbound {
     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
         @ResponseCode(code = 404, condition = "The containerName is not found"),
-        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
-    public Nodes getNodes(@PathParam("containerName") String containerName) {
+        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable"),
+        @ResponseCode(code = 400, condition = "Incorrect query syntex") })
+    public Nodes getNodes(@PathParam("containerName") String containerName, @QueryParam("_q") String queryString) {
 
         if (!isValidContainer(containerName)) {
             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
@@ -233,8 +245,12 @@ public class SwitchNorthbound {
             NodeProperties nodeProps = new NodeProperties(node, props);
             res.add(nodeProps);
         }
-
-        return new Nodes(res);
+        Nodes result = new Nodes(res);
+        if (queryString != null) {
+            queryContext.createQuery(queryString, Nodes.class)
+                .filter(result, NodeProperties.class);
+        }
+        return result;
     }
 
     /**
@@ -564,9 +580,11 @@ public class SwitchNorthbound {
     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
         @ResponseCode(code = 404, condition = "The containerName is not found"),
-        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
+        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable"),
+        @ResponseCode(code = 400, condition = "Incorrect query syntex") })
     public NodeConnectors getNodeConnectors(@PathParam("containerName") String containerName,
-            @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId) {
+            @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
+            @QueryParam("_q") String queryString) {
 
         if (!isValidContainer(containerName)) {
             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
@@ -598,8 +616,12 @@ public class SwitchNorthbound {
             NodeConnectorProperties ncProps = new NodeConnectorProperties(nc, props);
             res.add(ncProps);
         }
-
-        return new NodeConnectors(res);
+        NodeConnectors result = new NodeConnectors(res);
+        if (queryString != null) {
+            queryContext.createQuery(queryString, NodeConnectors.class)
+                .filter(result, NodeConnectorProperties.class);
+        }
+        return result;
     }
 
     /**
index 4a1142bb1813784fd7b5108a807ac9fde26bc6c5..3f1a7701102467edf00dd974c254407728049176 100644 (file)
@@ -51,6 +51,7 @@
               org.opendaylight.controller.northbound.commons,
               org.opendaylight.controller.northbound.commons.exception,
               org.opendaylight.controller.northbound.commons.utils,
+              org.opendaylight.controller.northbound.commons.query,
               org.opendaylight.controller.sal.core,
               org.opendaylight.controller.sal.packet,
               org.opendaylight.controller.sal.authorization,
@@ -62,6 +63,7 @@
               com.sun.jersey.spi.container.servlet,
               com.fasterxml.jackson.annotation,
               javax.ws.rs,
+              javax.ws.rs.ext,
               javax.ws.rs.core,
               javax.xml.bind,
               javax.xml.bind.annotation,
index 427aa1c1deaaf98c86fa3ecd072757bc6331892c..3773070504a0fa4be1e107e422793b52085217d2 100644 (file)
@@ -21,10 +21,12 @@ 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.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -33,6 +35,7 @@ import org.opendaylight.controller.northbound.commons.RestMessages;
 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.Edge;
@@ -59,7 +62,14 @@ import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
 public class TopologyNorthboundJAXRS {
 
     private String username;
+    private QueryContext queryContext;
 
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
     @Context
     public void setSecurityContext(SecurityContext context) {
         if (context != null && context.getUserPrincipal() != null) {
@@ -240,7 +250,8 @@ public class TopologyNorthboundJAXRS {
     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @TypeHint(Topology.class)
     @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
-    public Topology getTopology(@PathParam("containerName") String containerName) {
+    public Topology getTopology(@PathParam("containerName") String containerName,
+        @QueryParam("_q") String queryString) {
 
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
@@ -253,16 +264,21 @@ public class TopologyNorthboundJAXRS {
         }
 
         Map<Edge, Set<Property>> topo = topologyManager.getEdges();
-        if (topo != null) {
-            List<EdgeProperties> res = new ArrayList<EdgeProperties>();
-            for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
-                EdgeProperties el = new EdgeProperties(entry.getKey(), entry.getValue());
-                res.add(el);
-            }
-            return new Topology(res);
+        if (topo == null) {
+            return null;
+        }
+        List<EdgeProperties> res = new ArrayList<EdgeProperties>();
+        for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
+            EdgeProperties el = new EdgeProperties(entry.getKey(), entry.getValue());
+            res.add(el);
         }
+        Topology result = new Topology(res);
 
-        return null;
+        if (queryString != null) {
+            queryContext.createQuery(queryString, Topology.class)
+                .filter(result, EdgeProperties.class);
+        }
+        return result;
     }
 
     /**
@@ -311,7 +327,8 @@ public class TopologyNorthboundJAXRS {
     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @TypeHint(TopologyUserLinks.class)
     @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
-    public TopologyUserLinks getUserLinks(@PathParam("containerName") String containerName) {
+    public TopologyUserLinks getUserLinks(@PathParam("containerName") String containerName,
+        @QueryParam("_q") String queryString) {
 
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
@@ -324,12 +341,16 @@ public class TopologyNorthboundJAXRS {
         }
 
         ConcurrentMap<String, TopologyUserLinkConfig> userLinks = topologyManager.getUserLinks();
-        if ((userLinks != null) && (userLinks.values() != null)) {
-            List<TopologyUserLinkConfig> res = new ArrayList<TopologyUserLinkConfig>(userLinks.values());
-            return new TopologyUserLinks(res);
+        if ((userLinks == null) || (userLinks.values() == null)) {
+            return null;
         }
-
-        return null;
+        TopologyUserLinks result = new TopologyUserLinks(
+                new ArrayList<TopologyUserLinkConfig>(userLinks.values()));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, TopologyUserLinks.class)
+                .filter(result, TopologyUserLinkConfig.class);
+        }
+        return result;
     }
 
     /**
index 5c2af6d8b430471d25f68a68c25e8915c9d02e97..932ac4e20be37f8d5ea1234265054209ceda120f 100644 (file)
@@ -32,11 +32,15 @@ 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.match.Match;
+import org.opendaylight.controller.sal.packet.Ethernet;
 import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService;
+import org.opendaylight.controller.sal.packet.PacketException;
 import org.opendaylight.controller.sal.packet.PacketResult;
 import org.opendaylight.controller.sal.packet.RawPacket;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.HexEncode;
+import org.opendaylight.controller.sal.utils.NetUtils;
 import org.openflow.protocol.OFMessage;
 import org.openflow.protocol.OFPacketIn;
 import org.openflow.protocol.OFPacketOut;
@@ -169,12 +173,10 @@ public class DataPacketMuxDemux implements IContainerListener,
 
     @Override
     public void receive(ISwitch sw, OFMessage msg) {
-        if (sw == null || msg == null
-                || this.pluginOutDataPacketServices == null) {
+        if (sw == null || msg == null || this.pluginOutDataPacketServices == null) {
             // Something fishy, we cannot do anything
-            logger.debug(
-                    "sw: {} and/or msg: {} and/or pluginOutDataPacketServices: {} is null!",
-                    new Object[] { sw, msg, this.pluginOutDataPacketServices });
+            logger.debug("sw: {} and/or msg: {} and/or pluginOutDataPacketServices: {} is null!", new Object[] { sw,
+                    msg, this.pluginOutDataPacketServices });
             return;
         }
 
@@ -185,8 +187,7 @@ public class DataPacketMuxDemux implements IContainerListener,
                 logger.debug("Connection service refused DataPacketMuxDemux receive {} {}", sw, msg);
                 return;
             }
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             return;
         }
 
@@ -204,63 +205,72 @@ public class DataPacketMuxDemux implements IContainerListener,
                 // pass the parsed packet simply because once the
                 // packet infra is settled all the packets will passed
                 // around as parsed and read-only
-                for (int i = 0; i < this.iDataPacketListen.size(); i++) {
-                    IDataPacketListen s = this.iDataPacketListen.get(i);
-                    if (s.receiveDataPacket(dataPacket).equals(
-                            PacketResult.CONSUME)) {
+                for (IDataPacketListen s : this.iDataPacketListen) {
+                      if (s.receiveDataPacket(dataPacket).equals(PacketResult.CONSUME)) {
                         logger.trace("Consumed locally data packet");
                         return;
                     }
                 }
 
-                // Now dispatch the packet toward SAL at least for
-                // default container, we need to revisit this in a general
-                // slicing architecture refresh
-                IPluginOutDataPacketService defaultOutService = this.pluginOutDataPacketServices
-                        .get(GlobalConstants.DEFAULT.toString());
-                if (defaultOutService != null) {
-                    defaultOutService.receiveDataPacket(dataPacket);
-                    if (logger.isTraceEnabled()) {
-                      logger.trace(
-                              "Dispatched to apps a frame of size: {} on " +
-                              "container: {}: {}", new Object[] {
-                                    ofPacket.getPacketData().length,
-                                    GlobalConstants.DEFAULT.toString(),
-                                    HexEncode.bytesToHexString(dataPacket
-                                            .getPacketData()) });
-                    }
-                }
+                boolean dispatched_to_container = false;
+
                 // Now check the mapping between nodeConnector and
                 // Container and later on optimally filter based on
                 // flowSpec
                 List<String> containersRX = this.nc2Container.get(p);
                 if (containersRX != null) {
-                    for (int i = 0; i < containersRX.size(); i++) {
-                        String container = containersRX.get(i);
-                        IPluginOutDataPacketService s = this.pluginOutDataPacketServices
-                                .get(container);
-                        if (s != null) {
-                            // TODO add filtering on a per-flowSpec base
-                            s.receiveDataPacket(dataPacket);
-                            if (logger.isTraceEnabled()) {
-                              logger.trace(
-                                      "Dispatched to apps a frame of size: {}" +
-                                      " on container: {}: {}", new Object[] {
-                                            ofPacket.getPacketData().length,
-                                            container,
-                                            HexEncode.bytesToHexString(dataPacket
-                                                    .getPacketData()) });
+                    Ethernet frame = new Ethernet();
+                    byte data[] = dataPacket.getPacketData();
+                    frame.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
+                    Match packetMatch = frame.getMatch();
+                    for (String container : containersRX) {
+                        boolean notify = true;
+                        List<ContainerFlow> containerFlows = this.container2FlowSpecs.get(container);
+                        if (containerFlows != null) {
+                            notify = false;
+                            for (ContainerFlow cFlow : containerFlows) {
+                                if (cFlow.allowsMatch(packetMatch)) {
+                                    notify = true;
+                                    break;
+                                }
+                            }
+                            if (notify) {
+                                IPluginOutDataPacketService s = this.pluginOutDataPacketServices.get(container);
+                                if (s != null) {
+                                    s.receiveDataPacket(dataPacket);
+                                    if (logger.isTraceEnabled()) {
+                                        logger.trace(
+                                                "Dispatched to apps a frame of size: {}" + " on container: {}: {}",
+                                                new Object[] { ofPacket.getPacketData().length, container,
+                                                        HexEncode.bytesToHexString(dataPacket.getPacketData()) });
+                                    }
+                                }
+                                dispatched_to_container = true;
                             }
                         }
                     }
                 }
-
+                if (!dispatched_to_container) {
+                    // Now dispatch the packet toward SAL for default container
+                    IPluginOutDataPacketService defaultOutService = this.pluginOutDataPacketServices
+                        .get(GlobalConstants.DEFAULT.toString());
+                    if (defaultOutService != null) {
+                        defaultOutService.receiveDataPacket(dataPacket);
+                        if (logger.isTraceEnabled()) {
+                            logger.trace("Dispatched to apps a frame of size: {} on " + "container: {}: {}",
+                                         new Object[] { ofPacket.getPacketData().length,
+                                                        GlobalConstants.DEFAULT.toString(),
+                                                        HexEncode.bytesToHexString(dataPacket.getPacketData()) });
+                        }
+                    }
+                }
                 // This is supposed to be the catch all for all the
                 // DataPacket hence we will assume it has been handled
                 return;
             } catch (ConstructionException cex) {
+            } catch (PacketException e) {
+                logger.debug("Failed to deserialize raw packet: ", e.getMessage());
             }
-
             // If we reach this point something went wrong.
             return;
         } else {
index cfe20a1fa2a6f13e35804f2eb389787314a6a9b8..4b8966c54698b048490480aa5f758cf1d1df1e2b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -69,6 +69,16 @@ public class V6Match extends OFMatch implements Cloneable {
 
     private static int IPV6_EXT_MIN_HDR_LEN = 36;
 
+    /**
+     * CFI bit in VLAN TCI field.
+     */
+    private static final int  VLAN_TCI_CFI = 1 << 12;
+
+    /**
+     * Value of OFP_VLAN_NONE defined by OpenFlow 1.0.
+     */
+    private static final short  OFP_VLAN_NONE = (short) 0xffff;
+
     private enum MatchFieldState {
         MATCH_ABSENT, MATCH_FIELD_ONLY, MATCH_FIELD_WITH_MASK
     }
@@ -334,11 +344,15 @@ public class V6Match extends OFMatch implements Cloneable {
     private byte[] getVlanTCI(short dataLayerVirtualLanID,
             byte dataLayerVirtualLanPriorityCodePoint) {
         ByteBuffer vlan_tci = ByteBuffer.allocate(2);
-        int cfi = 1 << 12; // the cfi bit is in position 12
-        int pcp = dataLayerVirtualLanPriorityCodePoint << 13; // the pcp fields
-                                                              // have to move by
-                                                              // 13
-        int vlan_tci_int = pcp + cfi + dataLayerVirtualLanID;
+        int vlan_tci_int;
+        if (dataLayerVirtualLanID == OFP_VLAN_NONE) {
+            // Match only packets without VLAN tag.
+            vlan_tci_int = 0;
+        } else {
+             // the pcp fields have to move by 13
+            int pcp = dataLayerVirtualLanPriorityCodePoint << 13;
+            vlan_tci_int = pcp + VLAN_TCI_CFI + dataLayerVirtualLanID;
+        }
         vlan_tci.put((byte) (vlan_tci_int >> 8)); // bits 8 to 15
         vlan_tci.put((byte) vlan_tci_int); // bits 0 to 7
         return vlan_tci.array();
@@ -542,7 +556,12 @@ public class V6Match extends OFMatch implements Cloneable {
                 ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
                 match_len += 6;
             } else if (values[0].equals(STR_DL_VLAN)) {
-                this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1]));
+                short vlan = U16.t(Integer.valueOf(values[1]));
+                if (this.dlVlanPCPState != MatchFieldState.MATCH_ABSENT &&
+                    vlan == OFP_VLAN_NONE) {
+                    throw new IllegalArgumentException("DL_VLAN_PCP is set.");
+                }
+                this.dataLayerVirtualLan = vlan;
                 this.dlVlanIDState = MatchFieldState.MATCH_FIELD_ONLY;
                 // the variable dlVlanIDState is not really used as a flag
                 // for serializing and deserializing. Rather it is used as a
@@ -552,6 +571,9 @@ public class V6Match extends OFMatch implements Cloneable {
                 if (this.dlVlanPCPState != MatchFieldState.MATCH_ABSENT) {
                     this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
                     match_len -= 2;
+                } else if (this.dataLayerVirtualLan == OFP_VLAN_NONE) {
+                    this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
+                    match_len += 6;
                 } else {
                     this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
                     this.dataLayerVirtualLanTCIMask = 0x1fff;
@@ -559,6 +581,11 @@ public class V6Match extends OFMatch implements Cloneable {
                 }
                 this.wildcards &= ~OFPFW_DL_VLAN;
             } else if (values[0].equals(STR_DL_VLAN_PCP)) {
+                if (this.dlVlanIDState != MatchFieldState.MATCH_ABSENT &&
+                    this.dataLayerVirtualLan == OFP_VLAN_NONE) {
+                    throw new IllegalArgumentException
+                        ("OFP_VLAN_NONE is specified to DL_VLAN.");
+                }
                 this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short
                         .valueOf(values[1]));
                 this.dlVlanPCPState = MatchFieldState.MATCH_FIELD_ONLY;
@@ -858,12 +885,20 @@ public class V6Match extends OFMatch implements Cloneable {
                 // get the vlan pcp
                 byte firstByte = data.get();
                 byte secondByte = data.get();
-                super.setDataLayerVirtualLanPriorityCodePoint(getVlanPCP(firstByte));
-                super.setDataLayerVirtualLan(getVlanID(firstByte, secondByte));
+                if (firstByte == 0 && secondByte == 0) {
+                    // Match only packets without VLAN tag.
+                    setDataLayerVirtualLan(OFP_VLAN_NONE);
+                } else if (((firstByte << 8) & VLAN_TCI_CFI) == 0) {
+                    // Ignore invalid TCI field.
+                    return;
+                } else {
+                    super.setDataLayerVirtualLanPriorityCodePoint(getVlanPCP(firstByte));
+                    super.setDataLayerVirtualLan(getVlanID(firstByte, secondByte));
+                    this.wildcards ^= (1 << 20);
+                }
                 this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
                 this.match_len += 6;
                 this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
-                this.wildcards ^= (1 << 20);
             }
         }
     }
@@ -1241,7 +1276,6 @@ public class V6Match extends OFMatch implements Cloneable {
      *
      * @return
      */
-
     public Inet6Address getNetworkDest() {
         return this.nwDst;
     }
@@ -1251,7 +1285,6 @@ public class V6Match extends OFMatch implements Cloneable {
      *
      * @return
      */
-
     public Inet6Address getNetworkSrc() {
         return this.nwSrc;
     }
@@ -1316,7 +1349,19 @@ public class V6Match extends OFMatch implements Cloneable {
         }
     }
 
+    /**
+     * Set a value to VLAN ID match field.
+     *
+     * @param vlan  A value to match for VLAN ID.
+     * @param mask  A bitmask for VLAN ID.
+     */
     public void setDataLayerVirtualLan(short vlan, short mask) {
+        if (vlan == OFP_VLAN_NONE
+                && this.dlVlanIDState != MatchFieldState.MATCH_ABSENT) {
+            throw new IllegalStateException
+                ("DL_VLAN_PCP is set.");
+        }
+
         // mask is ignored as the code sets the appropriate mask
         super.dataLayerVirtualLan = vlan;
         this.dlVlanIDState = MatchFieldState.MATCH_FIELD_ONLY;
@@ -1327,6 +1372,9 @@ public class V6Match extends OFMatch implements Cloneable {
         if (this.dlVlanPCPState != MatchFieldState.MATCH_ABSENT) {
             this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
             match_len -= 2;
+        } else if (this.dataLayerVirtualLan == OFP_VLAN_NONE) {
+            this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
+            match_len += 6;
         } else {
             this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
             this.dataLayerVirtualLanTCIMask = 0x1fff;
@@ -1334,7 +1382,19 @@ public class V6Match extends OFMatch implements Cloneable {
         }
     }
 
+    /**
+     * Set a value to VLAN PCP match field.
+     *
+     * @param pcp  A value to match for VLAN PCP.
+     * @param mask  A bitmask for VLAN PCP.
+     */
     public void setDataLayerVirtualLanPriorityCodePoint(byte pcp, byte mask) {
+        if (this.dlVlanIDState != MatchFieldState.MATCH_ABSENT
+                && this.dataLayerVirtualLan == OFP_VLAN_NONE) {
+            throw new IllegalStateException
+                ("OFP_VLAN_NONE is specified to DL_VLAN.");
+        }
+
         // mask is ignored as the code sets the appropriate mask
         super.dataLayerVirtualLanPriorityCodePoint = pcp;
         this.dlVlanPCPState = MatchFieldState.MATCH_FIELD_ONLY;
diff --git a/opendaylight/protocol_plugins/openflow/src/test/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6MatchTest.java b/opendaylight/protocol_plugins/openflow/src/test/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6MatchTest.java
new file mode 100644 (file)
index 0000000..fceaaf4
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2014 NEC Corporation
+ * 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.protocol_plugin.openflow.vendorextension.v6extension;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.openflow.protocol.OFMatch.OFPFW_ALL;
+import static org.openflow.protocol.OFMatch.OFPFW_DL_VLAN;
+import static org.openflow.protocol.OFMatch.OFPFW_DL_VLAN_PCP;
+import static org.openflow.protocol.OFMatch.OFPFW_IN_PORT;
+
+import java.nio.ByteBuffer;
+import org.junit.Test;
+
+/**
+ * JUnit test for {@link V6Match}.
+ */
+public class V6MatchTest {
+    /**
+     * Header of a match entry for input port field without a mask.
+     * The vendor-specific value is 0, and the length of value is 2.
+     */
+    private static int  HEADER_INPUT_PORT = (0 << 9) | 2;
+
+    /**
+     * Header of a match entry for VLAN TCI field without a mask.
+     * The vendor-specific value is 4, and the length of value is 2.
+     */
+    private static int  HEADER_VLAN_TCI= (4 << 9) | 2;
+
+    /**
+     * Header of a match entry for VLAN TCI field with a mask.
+     * The vendor-specific value is 4, and the length of value is 4.
+     */
+    private static int  HEADER_VLAN_TCI_W = (4 << 9) | (1 << 8) | 4;
+
+    /**
+     * Length of a match entry for input port field.
+     * Header (4 bytes) + value (2 bytes) = 6 bytes.
+     */
+    private static short  MATCH_LEN_INPUT_PORT = 6;
+
+    /**
+     * Length of a match entry for VLAN TCI field without a mask.
+     * Header (4 bytes) + value (2 bytes) = 6 bytes.
+     */
+    private static short  MATCH_LEN_VLAN_TCI = 6;
+
+    /**
+     * Length of a match entry for VLAN TCI field with a mask.
+     * Header (4 bytes) + value (2 bytes) + bitmask (2 bytes) = 8 bytes.
+     */
+    private static short  MATCH_LEN_VLAN_TCI_WITH_MASK = 8;
+
+    /**
+     * Value of OFP_VLAN_NONE defined by OpenFlow 1.0.
+     */
+    private static final short  OFP_VLAN_NONE = (short)0xffff;
+
+    /**
+     * CFI bit in VLAN TCI field.
+     */
+    private static final int  VLAN_TCI_CFI = 1 << 12;
+
+    /**
+     * Test case for {@link V6Match#fromString(String)} about VLAN TCI field.
+     * This test passes values to "dl_vlan" and "dl_vpcp".
+     */
+    @Test
+    public void testFromStringVlanTci() {
+        // Test for "dl_vlan" using non OFP_VLAN_NONE values.
+        short vlans[] = {1, 10, 1000, 4095};
+        short mask = 0;
+        for (short vlan: vlans) {
+            V6Match match = new V6Match();
+            match.fromString("dl_vlan=" + vlan);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen());
+            assertEquals(vlan, match.getDataLayerVirtualLan());
+            int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN;
+            assertEquals(wildcards, match.getWildcards());
+        }
+
+        // Test for "dl_vpcp".
+        byte pcps[] = {1, 3, 7};
+        for (byte pcp: pcps) {
+            V6Match match = new V6Match();
+            match.fromString("dl_vpcp=" + pcp);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen());
+            assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint());
+            int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN_PCP;
+            assertEquals(wildcards, match.getWildcards());
+        }
+
+        // Set "dl_vlan" field firstly, "dl_vpcp" field secondly.
+        for (short vlan: vlans) {
+            for (byte pcp: pcps) {
+                V6Match match = new V6Match();
+                match.fromString("dl_vlan=" + vlan);
+                match.fromString("dl_vpcp=" + pcp);
+                assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+                assertEquals(vlan, match.getDataLayerVirtualLan());
+                assertEquals(pcp,
+                        match.getDataLayerVirtualLanPriorityCodePoint());
+            }
+        }
+
+        // Set "dl_vpcp" field firstly, "dl_vlan" field secondly.
+        for (short vlan: vlans) {
+            for (byte pcp: pcps) {
+                V6Match match = new V6Match();
+                match.fromString("dl_vpcp=" + pcp);
+                match.fromString("dl_vlan=" + vlan);
+                assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+                assertEquals(vlan, match.getDataLayerVirtualLan());
+                assertEquals(pcp,
+                        match.getDataLayerVirtualLanPriorityCodePoint());
+            }
+        }
+
+        // Test for OFP_VLAN_NONE when VLAN PCP is not set.
+        V6Match match = new V6Match();
+        match.fromString("dl_vlan=" + OFP_VLAN_NONE);
+        assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+        assertEquals(OFP_VLAN_NONE, match.getDataLayerVirtualLan());
+
+        // Test for OFP_VLAN_NONE when VLAN PCP is set.
+        match = new V6Match();
+        match.fromString("dl_vpcp=" + 1);
+        try {
+            match.fromString("dl_vlan=" + OFP_VLAN_NONE);
+            fail("Throwing exception was expected.");
+        } catch (IllegalArgumentException e) {
+            // Throwing exception was expected.
+        }
+    }
+
+    /**
+     * Test case for {@link V6Match#writeTo(ByteBuffer)} for VLAN TCI field.
+     */
+    @Test
+    public void testWriteToVlanTci() {
+        byte mask = 0;
+
+        // Set only VLAN ID.
+        short vlans[] = {1, 10, 1000, 4095};
+        for (short vlan: vlans) {
+            V6Match match = new V6Match();
+            match.setDataLayerVirtualLan(vlan, mask);
+            ByteBuffer data = ByteBuffer.allocate(10);
+            match.writeTo(data);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, data.position());
+            data.flip();
+            // Header
+            assertEquals(HEADER_VLAN_TCI_W, data.getInt());
+            // Value
+            short expectedTci = (short) (VLAN_TCI_CFI | vlan);
+            assertEquals(expectedTci, data.getShort());
+            // Mask
+            short expectedMask = 0x1fff;
+            assertEquals(expectedMask, data.getShort());
+        }
+
+        // Set only VLAN PCP.
+        byte pcps[] = {1, 3, 7};
+        for (byte pcp: pcps) {
+            V6Match match = new V6Match();
+            match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask);
+            ByteBuffer data = ByteBuffer.allocate(10);
+            match.writeTo(data);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, data.position());
+            data.flip();
+            // Header
+            assertEquals(HEADER_VLAN_TCI_W, data.getInt());
+            // Value
+            short expectedTci = (short) (pcp << 13 | VLAN_TCI_CFI);
+            assertEquals(expectedTci, data.getShort());
+            // Mask
+            short expectedMask = (short) 0xf000;
+            assertEquals(expectedMask, data.getShort());
+        }
+
+        // Set both VLAN ID and PCP.
+        for (short vlan: vlans) {
+            for (byte pcp: pcps) {
+                V6Match match = new V6Match();
+                match.setDataLayerVirtualLan(vlan, mask);
+                match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask);
+                ByteBuffer data = ByteBuffer.allocate(10);
+                match.writeTo(data);
+                assertEquals(MATCH_LEN_VLAN_TCI, data.position());
+                data.flip();
+                // Header
+                assertEquals(HEADER_VLAN_TCI, data.getInt());
+                // Value
+                short expectedTci = (short) (pcp << 13 | VLAN_TCI_CFI | vlan);
+                assertEquals(expectedTci, data.getShort());
+            }
+        }
+
+        // Set OFP_VLAN_NONE.
+        V6Match match = new V6Match();
+        match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask);
+        ByteBuffer data = ByteBuffer.allocate(10);
+        match.writeTo(data);
+        assertEquals(MATCH_LEN_VLAN_TCI, data.position());
+        data.flip();
+        // Header
+        assertEquals(HEADER_VLAN_TCI, data.getInt());
+        // Value
+        assertEquals(0, data.getShort());
+    }
+
+    /**
+     * Test case for {@link V6Match#writeTo(ByteBuffer)} for input port field.
+     */
+    @Test
+    public void testWriteToInputPort() {
+        // Set input port.
+        short ports[] = {1, 10, 100, 1000};
+        for (short port: ports) {
+            V6Match match = new V6Match();
+            match.setInputPort(port, (short) 0);
+            ByteBuffer data = ByteBuffer.allocate(10);
+            match.writeTo(data);
+            assertEquals(MATCH_LEN_INPUT_PORT, data.position());
+            data.flip();
+            // Header
+            assertEquals(HEADER_INPUT_PORT, data.getInt());
+            // Value
+            assertEquals(port, data.getShort());
+        }
+    }
+
+    /**
+     * Test case for {@link V6Match#readFrom(ByteBuffer)} for VLAN TCI field.
+     */
+    @Test
+    public void testReadFromVlanTci() {
+        // Test for an exact match a TCI value with CFI=1.
+        // It matches packets that have an 802.1Q header with a specified
+        // VID and PCP.
+        short vlans[] = {1, 10, 1000, 4095};
+        byte pcps[] = {1, 3, 7};
+        for (short vlan: vlans) {
+            for (byte pcp: pcps) {
+                ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI);
+                data.putInt(HEADER_VLAN_TCI);
+                short tci = (short) (pcp << 13 | VLAN_TCI_CFI | vlan);
+                data.putShort(tci);
+                data.flip();
+
+                V6Match match = new V6Match();
+                match.readFrom(data);
+                assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+                assertEquals(pcp,
+                        match.getDataLayerVirtualLanPriorityCodePoint());
+                assertEquals(vlan, match.getDataLayerVirtualLan());
+                int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN_PCP & ~OFPFW_DL_VLAN;
+                assertEquals(wildcards, match.getWildcards());
+            }
+        }
+
+        // Test with a specific VID and CFI=1 with mask=0x1fff.
+        // It matches packets that have an 802.1Q header with that VID
+        // and any PCP.
+        for (short vlan: vlans) {
+            ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI_WITH_MASK);
+            data.putInt(HEADER_VLAN_TCI_W);
+            short tci = (short) (VLAN_TCI_CFI | vlan);
+            data.putShort(tci);
+            short mask = (short) 0x1fff;
+            data.putShort(mask);
+            data.flip();
+
+            V6Match match = new V6Match();
+            match.readFrom(data);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen());
+            assertEquals(vlan, match.getDataLayerVirtualLan());
+            int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN;
+            assertEquals(wildcards, match.getWildcards());
+        }
+
+        // Test with a specific PCP and CFI=1 with mask=0xf000.
+        // It matches packets that have an 802.1Q header with that PCP
+        // and any VID.
+        for (byte pcp: pcps) {
+            ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI_WITH_MASK);
+            data.putInt(HEADER_VLAN_TCI_W);
+            short tci = (short) (pcp << 13| VLAN_TCI_CFI);
+            data.putShort(tci);
+            short mask = (short) 0xf000;
+            data.putShort(mask);
+            data.flip();
+
+            V6Match match = new V6Match();
+            match.readFrom(data);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen());
+            assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint());
+            int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN_PCP;
+            assertEquals(wildcards, match.getWildcards());
+        }
+
+        // Test for an exact match with 0.
+        // It matches only packets without an 802.1Q header.
+        ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_VLAN_TCI);
+        data.putInt(HEADER_VLAN_TCI);
+        short tci = 0;
+        data.putShort(tci);
+        data.flip();
+
+        V6Match match = new V6Match();
+        match.readFrom(data);
+        assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+        assertEquals(OFP_VLAN_NONE, match.getDataLayerVirtualLan());
+        int wildcards = OFPFW_ALL & ~OFPFW_DL_VLAN;
+        assertEquals(wildcards, match.getWildcards());
+    }
+
+    /**
+     * Test case for {@link V6Match#readFrom(ByteBuffer)} for input port field.
+     */
+    @Test
+    public void testReadFromInputPort() {
+        // Set input port.
+        short ports[] = {1, 10, 100, 1000};
+        for (short port: ports) {
+            ByteBuffer data = ByteBuffer.allocate(MATCH_LEN_INPUT_PORT);
+            data.putInt(HEADER_INPUT_PORT);
+            data.putShort(port);
+            data.flip();
+
+            V6Match match = new V6Match();
+            match.readFrom(data);
+            assertEquals(MATCH_LEN_INPUT_PORT, match.getIPv6MatchLen());
+            assertEquals(port, match.getInputPort());
+            int wildcards = OFPFW_ALL & ~OFPFW_IN_PORT;
+            assertEquals(wildcards, match.getWildcards());
+        }
+    }
+
+    /**
+     * Test case for {@link V6Match#setDataLayerVirtualLan(short, short)}.
+     */
+    @Test
+    public void testSetDataLayerVirtualLan() {
+        short vlans[] = {1, 10, 1000, 4095};
+        short mask = 0;
+        for (short vlan: vlans) {
+            V6Match match = new V6Match();
+            match.setDataLayerVirtualLan(vlan, mask);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen());
+            assertEquals(vlan, match.getDataLayerVirtualLan());
+        }
+
+        // Test for OFP_VLAN_NONE.
+        V6Match match = new V6Match();
+        match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask);
+        assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+        assertEquals(OFP_VLAN_NONE, match.getDataLayerVirtualLan());
+    }
+
+    /**
+     * Test case for
+     * {@link V6Match#setDataLayerVirtualLanPriorityCodePoint(byte, byte)}.
+     */
+    @Test
+    public void testSetDataLayerVirtualLanPriorityCodePoint() {
+        byte pcps[] = {1, 3, 7};
+        byte mask = 0;
+        for (byte pcp: pcps) {
+            V6Match match = new V6Match();
+            match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask);
+            assertEquals(MATCH_LEN_VLAN_TCI_WITH_MASK, match.getIPv6MatchLen());
+            assertEquals(pcp, match.getDataLayerVirtualLanPriorityCodePoint());
+        }
+    }
+
+    /**
+     * Test case for setter methods for VLAN TCI field.
+     *
+     * This test case calls {@link V6Match#setDataLayerVirtualLan(short, short)}
+     * and {@link V6Match#setDataLayerVirtualLanPriorityCodePoint(byte, byte)}.
+     */
+    @Test
+    public void testSetVlanTCI() {
+        short vlans[] = {1, 10, 1000, 4095};
+        byte pcps[] = {1, 3, 7};
+        byte mask = 0;
+
+        // Call setDataLayerVirtualLan(short, short) firstly,
+        // and setDataLayerVirtualLanPriorityCodePoint(byte, byte) secondly,
+        for (short vlan: vlans) {
+            for (byte pcp: pcps) {
+                V6Match match = new V6Match();
+                match.setDataLayerVirtualLan(vlan, mask);
+                match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask);
+                assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+                assertEquals(vlan, match.getDataLayerVirtualLan());
+                assertEquals(pcp,
+                             match.getDataLayerVirtualLanPriorityCodePoint());
+            }
+        }
+
+        // Call setDataLayerVirtualLanPriorityCodePoint(byte, byte) firstly,
+        // and setDataLayerVirtualLan(short, short) secondly.
+        for (short vlan: vlans) {
+            for (byte pcp: pcps) {
+                V6Match match = new V6Match();
+                match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask);
+                match.setDataLayerVirtualLan(vlan, mask);
+                assertEquals(MATCH_LEN_VLAN_TCI, match.getIPv6MatchLen());
+                assertEquals(vlan, match.getDataLayerVirtualLan());
+                assertEquals(pcp,
+                             match.getDataLayerVirtualLanPriorityCodePoint());
+            }
+        }
+
+        // Test for setting OFP_VLAN_NONE when VLAN PCP is set.
+        for (byte pcp: pcps) {
+            V6Match match = new V6Match();
+            match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask);
+            try {
+                match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask);
+            } catch (IllegalStateException e) {
+                // Throwing exception was expected.
+            }
+        }
+
+        // Test for set VLAN PCP when OFP_VLAN_NONE is set to VLAN match.
+        for (byte pcp: pcps) {
+            V6Match match = new V6Match();
+            match.setDataLayerVirtualLan(OFP_VLAN_NONE, mask);
+            try {
+                match.setDataLayerVirtualLanPriorityCodePoint(pcp, mask);
+            } catch (IllegalStateException e) {
+                // Throwing exception was expected.
+            }
+        }
+    }
+
+    /**
+     * Test case for {@link V6Match#setInputPort(short, short)}.
+     */
+    @Test
+    public void testSetInputPort() {
+        short ports[] = {1, 10, 100, 1000};
+        for (short port: ports) {
+            V6Match match = new V6Match();
+            match.setInputPort(port, (short) 0);
+            assertEquals(MATCH_LEN_INPUT_PORT, match.getIPv6MatchLen());
+            assertEquals(port, match.getInputPort());
+        }
+    }
+}
index 8fc0d625ebe0dd5b08bff4df864efe6a2e3068bd..21c17b366c04c025683b5c032981f043428e326a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -258,18 +258,23 @@ public class ARP extends Packet {
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
+        if (this == obj) {
             return true;
-        if (!super.equals(obj))
+        }
+        if (!super.equals(obj)) {
             return false;
-        if (getClass() != obj.getClass())
+        }
+        if (getClass() != obj.getClass()) {
             return false;
+        }
         ARP other = (ARP) obj;
         if (fieldValues == null) {
-            if (other.fieldValues != null)
+            if (other.fieldValues != null) {
                 return false;
-        } else if (!fieldValues.equals(other.fieldValues))
+            }
+        } else if (!fieldValues.equals(other.fieldValues)) {
             return false;
+        }
         return true;
     }
 }
index d0068564a93b29a326395b1e6cae9eeacf968a53..235e71a760faa01eb9cf9d2acf92a73c8acf00ce 100644 (file)
@@ -15,6 +15,8 @@ import java.util.Map;
 
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.controller.sal.utils.EtherTypes;
 import org.opendaylight.controller.sal.utils.NetUtils;
 
@@ -139,4 +141,10 @@ public class Ethernet extends Packet {
         return this;
     }
 
+    @Override
+    public void populateMatch(Match match) {
+        match.setField(MatchType.DL_SRC, this.getSourceMACAddress());
+        match.setField(MatchType.DL_DST, this.getDestinationMACAddress());
+        match.setField(MatchType.DL_TYPE, this.getEtherType());
+    }
 }
index 39c7d386bc1fe3ccf5ff397ebfcc491fe108aad6..9825d0eefb791098bf1724d5996c44f881c0da6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -13,6 +13,8 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 
 /**
  * Class that represents the IEEE 802.1Q objects
@@ -148,4 +150,10 @@ public class IEEE8021Q extends Packet {
         return this;
     }
 
+    @Override
+    public void populateMatch(Match match) {
+        match.setField(MatchType.DL_VLAN, this.getVid());
+        match.setField(MatchType.DL_VLAN_PR, this.getPcp());
+        match.setField(MatchType.DL_TYPE, this.getEtherType());
+    }
 }
index 559acd633ab7e56b6cb22042f7d3974a1e217212..3363f423d695f1b2f090e6c5274715f47d765e3c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -20,6 +20,8 @@ import java.util.Random;
 
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.controller.sal.utils.IPProtocols;
 import org.opendaylight.controller.sal.utils.NetUtils;
 import org.slf4j.Logger;
@@ -577,4 +579,12 @@ public class IPv4 extends Packet {
             corrupted = true;
         }
     }
+
+    @Override
+    public void populateMatch(Match match) {
+        match.setField(MatchType.NW_SRC, NetUtils.getInetAddress(this.getSourceAddress()));
+        match.setField(MatchType.NW_DST, NetUtils.getInetAddress(this.getDestinationAddress()));
+        match.setField(MatchType.NW_PROTO, this.getProtocol());
+        match.setField(MatchType.NW_TOS, this.getDiffServ());
+    }
 }
index 6f5cf04a529ed5a2872ff1d7c299eac71a1e060a..9b5dc082bb2303084775026131a11552b5614add 100644 (file)
@@ -12,6 +12,7 @@ import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.NetUtils;
 
index efb938e37f50745aae8f1f560b0d85f2bb7e7c07..35244ea697d871617b09db6e232da95af0d51ebf 100644 (file)
@@ -151,18 +151,23 @@ public class LLDPTLV extends Packet {
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
+        if (this == obj) {
             return true;
-        if (!super.equals(obj))
+        }
+        if (!super.equals(obj)) {
             return false;
-        if (getClass() != obj.getClass())
+        }
+        if (getClass() != obj.getClass()) {
             return false;
+        }
         LLDPTLV other = (LLDPTLV) obj;
         if (fieldValues == null) {
-            if (other.fieldValues != null)
+            if (other.fieldValues != null) {
                 return false;
-        } else if (!fieldValues.equals(other.fieldValues))
+            }
+        } else if (!fieldValues.equals(other.fieldValues)) {
             return false;
+        }
         return true;
     }
 
index 58b5d3914aa2dc199111dd2f2dc1ff8d5289dcc0..789aa126533c93c16660e5eafcfc995dc510fab1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -13,6 +13,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.NetUtils;
 import org.slf4j.Logger;
@@ -364,4 +365,31 @@ public abstract class Packet {
         return true;
     }
 
+    /**
+     * Adds to the passed Match this packet's header fields
+     *
+     * @param match
+     *            The Match object to populate
+     */
+    public void populateMatch(Match match) {
+        // To be overridden by derived packet classes which have well known
+        // header fields so that Packet.getMatch would return desired result
+    }
+
+    /**
+     * Returns the Match object containing this packet and its payload
+     * encapsulated packets' header fields
+     *
+     * @return The Match containing the header fields of this packet and of its
+     *         payload encapsulated packets
+     */
+    public Match getMatch() {
+        Match match = new Match();
+        Packet packet = this;
+        while (packet != null) {
+            packet.populateMatch(match);
+            packet = packet.getPayload();
+        }
+        return match;
+    }
 }
index 8253ac46d3f5405ace57da8022be90a183645a68..d27494599c280418044e4ef78210678562852cc0 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -15,6 +15,8 @@ import java.util.Map;
 
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 
 /**
  * Class that represents the TCP segment objects
@@ -238,4 +240,9 @@ public class TCP extends Packet {
         return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
     }
 
+    @Override
+    public void populateMatch(Match match) {
+        match.setField(MatchType.TP_SRC, this.getSourcePort());
+        match.setField(MatchType.TP_DST, this.getDestinationPort());
+    }
 }
index f82ed8fcaee00115bef01f4a6b03813389bf1a0c..069a277f89d9ee44df2e4ca22d9783fb9b9a6404 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -15,6 +15,8 @@ import java.util.Map;
 
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 
 /**
  * Class that represents the UDP datagram objects
@@ -156,4 +158,10 @@ public class UDP extends Packet {
         fieldValues.put(CHECKSUM, checksum);
         return this;
     }
+
+    @Override
+    public void populateMatch(Match match) {
+        match.setField(MatchType.TP_SRC, this.getSourcePort());
+        match.setField(MatchType.TP_DST, this.getDestinationPort());
+    }
 }
index a3ebd7ee0d164163b18f8091199f63bc89c4e30a..10bd535eb2790a1876fe2f9cfa29afb681b4ed1b 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
index 2494eb6b2d459460c0ab825e9b18c0fc15d30029..494dd2abf28c0d0e660debeb6a9936c3c752315a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -9,9 +9,14 @@
 
 package org.opendaylight.controller.sal.packet;
 
+import java.util.Arrays;
+
 import junit.framework.Assert;
 
 import org.junit.Test;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.EtherTypes;
 
 public class EthernetTest {
 
@@ -95,4 +100,22 @@ public class EthernetTest {
 
     }
 
+    @Test
+    public void testGetMatch() throws Exception {
+        Ethernet eth = new Ethernet();
+        byte smac[] = { (byte) 0xf0, (byte) 0xde, (byte) 0xf1, (byte) 0x71, (byte) 0x72, (byte) 0x8d };
+        byte dmac[] = { (byte) 0xde, (byte) 0x28, (byte) 0xdb, (byte) 0xb3, (byte) 0x7c, (byte) 0xf8 };
+        short ethType = EtherTypes.IPv4.shortValue();
+        eth.setDestinationMACAddress(dmac);
+        eth.setSourceMACAddress(smac);
+        eth.setEtherType(ethType);
+
+        Match match = eth.getMatch();
+
+        Assert.assertTrue(Arrays.equals(smac, (byte[]) match.getField(MatchType.DL_SRC).getValue()));
+        Assert.assertTrue(Arrays.equals(dmac, (byte[]) match.getField(MatchType.DL_DST).getValue()));
+        Assert.assertEquals(ethType, (short) match.getField(MatchType.DL_TYPE).getValue());
+
+    }
+
 }
index a4c6c1fc4b335472d302c655ffd52e1544767e36..2443b491c7e8a7fb69fba50c65681a6bd691f597 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -9,7 +9,11 @@
 package org.opendaylight.controller.sal.packet;
 
 import junit.framework.Assert;
+
 import org.junit.Test;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.EtherTypes;
 import org.opendaylight.controller.sal.utils.NetUtils;
 
 public class IEEE8021QTest {
@@ -212,4 +216,21 @@ public class IEEE8021QTest {
         Assert.assertTrue(data[44] == (byte) 0x09);
         Assert.assertTrue(data[45] == (byte) 0xFE);
     }
+
+    @Test
+    public void testGetMatchFullPacket() throws Exception {
+        IEEE8021Q dot1q = new IEEE8021Q();
+        byte priority = 4;
+        short vlanId = 59;
+        short ethType = EtherTypes.IPv4.shortValue();
+        dot1q.setPcp(priority);
+        dot1q.setVid(vlanId);
+        dot1q.setEtherType(ethType);
+
+        Match match = dot1q.getMatch();
+
+        Assert.assertEquals(priority, (byte) match.getField(MatchType.DL_VLAN_PR).getValue());
+        Assert.assertEquals(vlanId, (short) match.getField(MatchType.DL_VLAN).getValue());
+        Assert.assertEquals(ethType, (short) match.getField(MatchType.DL_TYPE).getValue());
+    }
 }
index 5afcd8be7dc4f47d79270dd00b6c3c8870c07631..f5298711b677a64ef9c80863580743ce2c394e52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -15,6 +15,8 @@ import java.util.Arrays;
 import junit.framework.Assert;
 
 import org.junit.Test;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.controller.sal.utils.EtherTypes;
 import org.opendaylight.controller.sal.utils.IPProtocols;
 import org.opendaylight.controller.sal.utils.NetUtils;
@@ -452,4 +454,31 @@ public class IPv4Test {
         Assert.assertFalse(decIcmp.isCorrupted());
         Assert.assertTrue(Arrays.equals(icmpRawPayload, decIcmp.getRawPayload()));
     }
+
+    @Test
+    public void testGetMatch() throws Exception {
+        IPv4 ip = new IPv4();
+        InetAddress sourceAddress = InetAddress.getByName("172.168.190.15");
+        InetAddress destintationAddress = InetAddress.getByName("23.128.0.11");
+        byte protocol = IPProtocols.TCP.byteValue();
+        byte tos = 7;
+        ip.setVersion((byte) 4);
+        ip.setIdentification((short) 5);
+        ip.setDiffServ(tos);
+        ip.setECN((byte) 0);
+        ip.setTotalLength((short) 84);
+        ip.setFlags((byte) 2);
+        ip.setFragmentOffset((short) 0);
+        ip.setTtl((byte) 64);
+        ip.setProtocol(protocol);
+        ip.setDestinationAddress(destintationAddress);
+        ip.setSourceAddress(sourceAddress);
+
+        Match match = ip.getMatch();
+
+        Assert.assertEquals(sourceAddress, match.getField(MatchType.NW_SRC).getValue());
+        Assert.assertEquals(destintationAddress, match.getField(MatchType.NW_DST).getValue());
+        Assert.assertEquals(protocol, (byte) match.getField(MatchType.NW_PROTO).getValue());
+        Assert.assertEquals(tos, (byte) match.getField(MatchType.NW_TOS).getValue());
+    }
 }
index 8f3b283b2ea020a175b53e952d08f41cd7ca1c69..95eff32ef1899f39a3838f2f46fea8c0f51923fa 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -9,11 +9,17 @@
 
 package org.opendaylight.controller.sal.packet;
 
+import java.net.InetAddress;
+import java.util.Arrays;
 import java.util.Map;
 
 import junit.framework.Assert;
 
 import org.junit.Test;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.IPProtocols;
 
 public class PacketTest {
 
@@ -120,9 +126,9 @@ public class PacketTest {
         eth.setSourceMACAddress(sMAC);
         eth.setEtherType(etherType);
 
-        dMACdata = (byte[]) fCValues.get("DestinationMACAddress");
-        sMACdata = (byte[]) fCValues.get("SourceMACAddress");
-        etherTypedata = (byte[]) fCValues.get("EtherType");
+        dMACdata = fCValues.get("DestinationMACAddress");
+        sMACdata = fCValues.get("SourceMACAddress");
+        etherTypedata = fCValues.get("EtherType");
 
         Assert.assertTrue(dMACdata[0] == 10);
         Assert.assertTrue(dMACdata[1] == 12);
@@ -160,4 +166,62 @@ public class PacketTest {
         Assert.assertTrue(data[13] == 6);
 
     }
+
+    @Test
+    public void testGetMatch() throws Exception {
+        TCP tcp = new TCP();
+        short sport = (short) 11093;
+        short dport = (short) 23;
+        tcp.setSourcePort(sport);
+        tcp.setDestinationPort(dport);
+
+        IPv4 ip = new IPv4();
+        InetAddress sourceAddress = InetAddress.getByName("192.168.100.100");
+        InetAddress destintationAddress = InetAddress.getByName("192.168.100.101");
+        byte protocol = IPProtocols.TCP.byteValue();
+        byte tos = 5;
+        ip.setVersion((byte) 4);
+        ip.setIdentification((short) 5);
+        ip.setDiffServ(tos);
+        ip.setECN((byte) 0);
+        ip.setTotalLength((short) 84);
+        ip.setFlags((byte) 2);
+        ip.setFragmentOffset((short) 0);
+        ip.setTtl((byte) 64);
+        ip.setProtocol(protocol);
+        ip.setDestinationAddress(destintationAddress);
+        ip.setSourceAddress(sourceAddress);
+        ip.setPayload(tcp);
+
+        IEEE8021Q dot1q = new IEEE8021Q();
+        byte priority = 4;
+        short vlanId = 59;
+        short ethType = EtherTypes.IPv4.shortValue();
+        dot1q.setPcp(priority);
+        dot1q.setVid(vlanId);
+        dot1q.setEtherType(ethType);
+        dot1q.setPayload(ip);
+
+        Ethernet eth = new Ethernet();
+        byte smac[] = { (byte) 0xf0, (byte) 0xde, (byte) 0xf1, (byte) 0x71, (byte) 0x72, (byte) 0x8d };
+        byte dmac[] = { (byte) 0xde, (byte) 0x28, (byte) 0xdb, (byte) 0xb3, (byte) 0x7c, (byte) 0xf8 };
+        eth.setDestinationMACAddress(dmac);
+        eth.setSourceMACAddress(smac);
+        eth.setEtherType(EtherTypes.VLANTAGGED.shortValue());
+        eth.setPayload(dot1q);
+
+        Match match = eth.getMatch();
+
+        Assert.assertTrue(Arrays.equals(smac, (byte[]) match.getField(MatchType.DL_SRC).getValue()));
+        Assert.assertTrue(Arrays.equals(dmac, (byte[]) match.getField(MatchType.DL_DST).getValue()));
+        Assert.assertEquals(priority, (byte) match.getField(MatchType.DL_VLAN_PR).getValue());
+        Assert.assertEquals(vlanId, (short) match.getField(MatchType.DL_VLAN).getValue());
+        Assert.assertEquals(ethType, (short) match.getField(MatchType.DL_TYPE).getValue());
+        Assert.assertEquals(sourceAddress, match.getField(MatchType.NW_SRC).getValue());
+        Assert.assertEquals(destintationAddress, match.getField(MatchType.NW_DST).getValue());
+        Assert.assertEquals(protocol, (byte) match.getField(MatchType.NW_PROTO).getValue());
+        Assert.assertEquals(tos, (byte) match.getField(MatchType.NW_TOS).getValue());
+        Assert.assertEquals(sport, (short) match.getField(MatchType.TP_SRC).getValue());
+        Assert.assertEquals(dport, (short) match.getField(MatchType.TP_DST).getValue());
+    }
 }
index 3e18aedfdb38b7238ef9a72c9d49bff151aec685..e56f41e5c1b301cf78eb8e1e5df3f29fcbe1e7e2 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -12,6 +12,8 @@ package org.opendaylight.controller.sal.packet;
 import junit.framework.Assert;
 
 import org.junit.Test;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 
 public class TCPTest {
 
@@ -113,4 +115,18 @@ public class TCPTest {
         short checksum = tcp.getChecksum();
         Assert.assertTrue(checksum == 200);
     }
+
+    @Test
+    public void testGetMatch() throws Exception {
+        TCP tcp = new TCP();
+        short sport = (short) 52012;
+        short dport = (short) 40345;
+        tcp.setSourcePort(sport);
+        tcp.setDestinationPort(dport);
+
+        Match match = tcp.getMatch();
+
+        Assert.assertEquals(sport, (short) match.getField(MatchType.TP_SRC).getValue());
+        Assert.assertEquals(dport, (short) match.getField(MatchType.TP_DST).getValue());
+    }
 }
index 8d5be849a034d5a147998d7adcf5099481acb552..a3a597a82d0fcb4524da02f174c9ca0419174c81 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2013-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,
@@ -12,6 +12,8 @@ package org.opendaylight.controller.sal.packet;
 import junit.framework.Assert;
 
 import org.junit.Test;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
 
 public class UDPTest {
 
@@ -95,4 +97,19 @@ public class UDPTest {
 
     }
 
+    @Test
+    public void testGetMatch() throws Exception {
+        UDP udp = new UDP();
+        short sport = (short) 33000;
+        short dport = (short) 843;
+        udp.setSourcePort(sport);
+        udp.setDestinationPort(dport);
+
+        Match match = udp.getMatch();
+
+        Assert.assertEquals(sport, (short) match.getField(MatchType.TP_SRC).getValue());
+        Assert.assertEquals(dport, (short) match.getField(MatchType.TP_DST).getValue());
+
+    }
+
 }
diff --git a/pom.xml b/pom.xml
index a26533819c45e8a8a89d696eef00093551db1b49..c54d9a930f28ad39ad680f30314508248bd2eea5 100644 (file)
--- a/pom.xml
+++ b/pom.xml
       </activation>
       <modules>
         <module>opendaylight/northbound/java-client</module>
+        <module>opendaylight/northbound/swagger-ui</module>
       </modules>
     </profile>
   </profiles>