Merge "Bug 1308 - Unable to publish NodeUpdated message via NotificationService"
authorTony Tkacik <ttkacik@cisco.com>
Thu, 7 Aug 2014 20:05:07 +0000 (20:05 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 7 Aug 2014 20:05:07 +0000 (20:05 +0000)
388 files changed:
.gitignore
features/config-netty/pom.xml
features/config-netty/src/main/resources/features.xml
features/config-persister/pom.xml
features/netconf/pom.xml
features/nsf/src/main/resources/features.xml
features/protocol-framework/pom.xml
itests/base-features-it/pom.xml [new file with mode: 0644]
itests/base-features-it/src/test/java/org/opendaylight/controller/base/BaseFeatureTest.java [new file with mode: 0644]
itests/pom.xml [new file with mode: 0644]
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/pom.xml
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/SimpleDispatcher.java
opendaylight/config/config-manager/pom.xml
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/runtimembean/RuntimeBeanRegistratorImplTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java
opendaylight/config/config-netty-config/pom.xml [new file with mode: 0644]
opendaylight/config/config-netty-config/src/main/resources/initial/00-netty.xml [moved from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.xml with 99% similarity]
opendaylight/config/config-util/pom.xml
opendaylight/config/pom.xml
opendaylight/config/yang-jmx-generator-it/pom.xml
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntryTest.java
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IHostTrackerShell.java [new file with mode: 0644]
opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java
opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java
opendaylight/hosttracker/shell/pom.xml [new file with mode: 0644]
opendaylight/hosttracker/shell/src/main/java/org/opendaylight/controller/hosttracker/shell/DumpFailedARPReqList.java [new file with mode: 0644]
opendaylight/hosttracker/shell/src/main/java/org/opendaylight/controller/hosttracker/shell/DumpPendingARPReqList.java [new file with mode: 0644]
opendaylight/hosttracker/shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml [new file with mode: 0644]
opendaylight/hosttracker/shell/src/test/java/org/opendaylight/controller/hosttracker/shell/HostTrackerShellTest.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.java [deleted file]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.java [deleted file]
opendaylight/md-sal/compatibility/pom.xml
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/md-sal-config/pom.xml [new file with mode: 0644]
opendaylight/md-sal/md-sal-config/src/main/resources/initial/01-md-sal.xml [moved from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml with 100% similarity]
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleConfigParamsImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ReadTransaction.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/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/BindingDataReadTransactionImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDataReadWriteTransactionImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/MountPointManagerImpl.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
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
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java [deleted file]
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-clustering-commons/README-FIRST [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/README-FIRST with 77% similarity]
opendaylight/md-sal/sal-clustering-commons/pom.xml [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/run.sh [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/run.sh with 93% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeToNormalizedNodeBuilder.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeToNormalizedNodeBuilder.java with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeValueCodec.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NodeValueCodec.java with 86% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodec.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodec.java with 87% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToProtocolBufferNode.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToProtocolBufferNode.java with 97% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/AugmentationIdentifierGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/AugmentationIdentifierGenerator.java with 81% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactory.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactory.java with 87% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierGenerator.java with 63% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithPredicatesGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithPredicatesGenerator.java with 89% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithValueGenerator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierWithValueGenerator.java with 84% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeGetter.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeGetter.java with 71% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeNavigator.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeNavigator.java with 91% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodePrinter.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodePrinter.java with 79% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtils.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/PathUtils.java with 65% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactory.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/QNameFactory.java with 67% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/util/EncoderDecoderUtil.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/util/EncoderDecoderUtil.java with 97% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtils.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtils.java with 97% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java with 99% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java with 98% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/Cohort.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Cohort.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/Common.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Common.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/CompositeModificationPayload.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/CompositeModificationPayload.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/DataChangeListener.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/DataChangeListener.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ListenerRegistration.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ListenerRegistration.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/Persistent.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Persistent.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardManager.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardManager.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransaction.proto with 96% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransactionChain.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransactionChain.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/main/resources/SimpleNormalizedNode.proto [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/SimpleNormalizedNode.proto with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/AbstractMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/application.conf [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/application.conf with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/augment_choice.xml [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/augment_choice.xml with 54% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/augment_choice.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/augment_choice.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-augmentation.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/odl-datastore-augmentation.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-test-notification.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/odl-datastore-test-notification.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/odl-datastore-test.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/odl-datastore-test.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/simple_xml_with_attributes.xml [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/simple_xml_with_attributes.xml with 51% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/test.yang [moved from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/test.yang with 100% similarity]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/DataChangeListenerMessagesData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ListenerRegistrationMessagesData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/NormalizedNodeMessagesTestData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/PersistentMessagesTestData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardManagerMessagesTestData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionChainMessagesTestData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionMessagesTestData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ThreePhaseCommitCohortMessagesTestData [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/readme.txt [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/05-clustering.xml.conf [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/module-shards.conf [new file with mode: 0644]
opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/modules.conf [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/pom.xml
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/ReadFailedException.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionCommitDeadlockException.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionCommitFailedException.java
opendaylight/md-sal/sal-common-util/pom.xml
opendaylight/md-sal/sal-distributed-datastore/client.conf [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/pom.xml
opendaylight/md-sal/sal-distributed-datastore/server.conf [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ActorSystemFactory.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayload.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListener.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxy.java
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/DistributedDataStoreFactory.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/NoOpDataChangeListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardWriteTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxy.java
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/jmx/mbeans/shard/ShardStats.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/jmx/mbeans/shard/ShardStatsMBean.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/EnableNotification.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindLocalShard.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/LocalShardFound.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/LocalShardNotFound.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ModuleShardStrategy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java
opendaylight/md-sal/sal-distributed-datastore/src/main/resources/application.conf
opendaylight/md-sal/sal-distributed-datastore/src/main/resources/modules.conf
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerRegistrationTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DataChangeListenerTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java
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
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohortProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ModuleShardStrategyTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/ActorContextTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/EchoActor.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/MockActorContext.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/CarsModel.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/SampleModelsTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Server.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/application.conf
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/modules.conf
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadTransaction.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
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/DomInmemoryDataBrokerModule.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/DOMDataCommitCoordinatorImpl.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/DOMForwardedReadWriteTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/TransactionCommitFailedExceptionMapper.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/sal/dom/broker/BackwardsCompatibleMountPoint.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/osgi/SchemaServiceProxy.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerTest.java
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/resources/odl-datastore-test.yang
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreReadTransaction.java
opendaylight/md-sal/sal-dom-xsql/src/main/java/org/opendaylight/yang/gen/v1/http/netconfcentral/org/ns/xsql/rev140626/XSQLModule.java
opendaylight/md-sal/sal-inmemory-datastore/pom.xml
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java
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/NetconfDevice.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/listener/NetconfSessionCapabilities.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceDataBroker.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadWriteTx.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTx.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/NetconfToNotificationTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToRpcRequestTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilitiesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/config-test-rpc.yang [new file with mode: 0644]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java [deleted file]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java [deleted file]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java [deleted file]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java [deleted file]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java [deleted file]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java [deleted file]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/ShardManagerMessagesTest.java [deleted file]
opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java [deleted file]
opendaylight/md-sal/sal-remoterpc-connector/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorConstants.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorSystemFactory.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProvider.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcManager.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistry.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlDocumentUtils.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/resources/application.conf
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModuleFactory.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProviderImpl.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToCompositeNodeReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToNormalizedNodeReaderWithSchema.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java
opendaylight/md-sal/sal-rest-connector/src/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/InstanceIdWithSchemaNode.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/StructuredData.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/MountPointRpcExecutor.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/listeners/Notificator.java
opendaylight/md-sal/sal-rest-connector/src/main/yang/sal-remote-augment.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnJsonBasicYangTypesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnJsonChoiceCaseTest.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/CnSnToJsonIncorrectTopLevelTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonLeafrefType.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonWithAugmentTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/input/to/cnsn/test/RestPutListDataTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonIdentityrefToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonLeafrefToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/MultipleEqualNamesForDataNodesTest.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/RestconfImplTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/URIParametersParsing.java [new file with mode: 0644]
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/XmlAndJsonToCnSnInstanceIdentifierTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlAndJsonToCnSnLeafRefTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/websockets/test/RestStream.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlAugmentedElementToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlLeafrefToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/opendaylight-inventory.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/sal-remote-augment.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/sal-remote@2014-01-14.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_short.yang
opendaylight/md-sal/sal-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java
opendaylight/md-sal/samples/pom.xml
opendaylight/md-sal/samples/toaster-config/pom.xml [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-config/src/main/resources/initial/03-toaster-sample.xml [moved from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/03-toaster-sample.xml with 99% similarity]
opendaylight/md-sal/topology-lldp-discovery/pom.xml
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
opendaylight/netconf/netconf-cli/pom.xml
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/writer/impl/NormalizedNodeWriter.java
opendaylight/netconf/netconf-config/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-config/src/main/resources/initial/01-netconf.xml [moved from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml with 100% similarity]
opendaylight/netconf/netconf-connector-config/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-connector-config/src/main/resources/initial/99-netconf-connector.xml [moved from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/99-netconf-connector.xml with 100% similarity]
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/pom.xml
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallInterface.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallPolicyInterface.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallRuleInterface.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallAware.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallCRUD.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallPolicyAware.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallPolicyCRUD.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallRuleAware.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallRuleCRUD.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewall.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewallPolicy.java [new file with mode: 0644]
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewallRule.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallNorthbound.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyNorthbound.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyRequest.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRequest.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRuleRequest.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRulesNorthbound.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java
opendaylight/topologymanager/implementation/pom.xml
opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerShell.java [new file with mode: 0644]
opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/internal/Activator.java
opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java
opendaylight/topologymanager/shell/pom.xml [new file with mode: 0644]
opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/AddUserLink.java [new file with mode: 0644]
opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/DeleteUserLink.java [new file with mode: 0644]
opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/PrintNodeEdges.java [new file with mode: 0644]
opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/PrintUserLink.java [new file with mode: 0644]
opendaylight/topologymanager/shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml [new file with mode: 0644]

index f8cf74f8263758e9cf39e2a4dbbf30d6c904628e..9144cda4cc6b40ede292b02156e21f99d136e13b 100644 (file)
@@ -27,3 +27,5 @@ out/
 maven-eclipse.xml
 .DS_STORE
 .metadata
+opendaylight/md-sal/sal-distributed-datastore/journal
+
index 98b97d1d95feabcfba4b8b4ca5b9bc15aafe8a5d..16fd975130592a1975332b6b390dbce2f9f1d614 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-persister-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index 3121ca01a2aa322a69c36d3994857df3e6507112..f1b2d1f753f66cf83dd03ddca24cb6155fe7ab33 100644 (file)
@@ -12,5 +12,6 @@
     <bundle>mvn:org.opendaylight.controller/threadpool-config-api/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.controller/threadpool-config-impl/${project.version}</bundle>
     <feature version='${project.version}'>odl-config-startup</feature>
+    <configfile finalname="configuration/initial/00-netty.xml">mvn:org.opendaylight.controller/config-netty-config/${config.version}/xml/config</configfile>
   </feature>
 </features>
\ No newline at end of file
index 969d0c8841b61caa947aa63166ff4ddba01c4a57..ec1520ed9818eb573942cde1ac6561110d2cb44f 100644 (file)
@@ -27,7 +27,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-features</artifactId>
-      <version>${netconf.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -35,7 +34,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index 90c088eaba2aab2911bdc65fbbba281af094ecb4..856557c1e8245ef24ada6cdb63e9ad4c775b696e 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -27,7 +26,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-odl-protocol-framework</artifactId>
-      <version>${protocol-framework.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index fb61f33fb32a58b82ff261a5c84a16cef3b274c4..130d72e01ae588780ccaa8d7840be0727874e2da 100644 (file)
         <bundle>mvn:org.opendaylight.controller/forwardingrulesmanager.implementation/${forwardingrulesmanager.implementation.version}</bundle>
 
         <bundle>mvn:org.opendaylight.controller/topologymanager/${topologymanager.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/topologymanager.shell/${topologymanager.shell.version}</bundle>
 
         <bundle>mvn:org.opendaylight.controller/networkconfig.neutron/${networkconfig.neutron.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/networkconfig.neutron.implementation/${networkconfig.neutron.implementation.version}</bundle>
 
         <bundle>mvn:org.opendaylight.controller/hosttracker/${hosttracker.api.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/hosttracker.implementation/${hosttracker.implementation.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/hosttracker.shell/${hosttracker.shell.version}</bundle>
 
         <bundle>mvn:org.opendaylight.controller/forwarding.staticrouting</bundle>
 
@@ -70,4 +72,4 @@
         <bundle>mvn:org.opendaylight.controller/topology.northbound/${topology.northbound.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/usermanager.northbound/${usermanager.northbound.version}</bundle>
     </feature>
-</features>
\ No newline at end of file
+</features>
index 045ac2dffec10871437ab784f53d7c97cbfe98cd..ba5dd18fc21615f3e52ddcbbe6f91c2323cc33d5 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
diff --git a/itests/base-features-it/pom.xml b/itests/base-features-it/pom.xml
new file mode 100644 (file)
index 0000000..8f73779
--- /dev/null
@@ -0,0 +1,90 @@
+<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/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>itests-controller</artifactId>
+        <version>1.4.2-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <artifactId>base-features-it</artifactId>
+    <name>base-features-it</name>
+    <packaging>jar</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>base-features</artifactId>
+            <version>${project.version}</version>
+            <classifier>features</classifier>
+            <type>xml</type>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <!-- Dependencies for pax exam karaf container -->
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-karaf</artifactId>
+            <version>${pax.exam.version}</version>
+            <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</artifactId>
+            <version>${pax.exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+            <scope>test</scope>
+        </dependency>
+         <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+            <version>${karaf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+           <groupId>org.osgi</groupId>
+           <artifactId>org.osgi.core</artifactId>
+           <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!-- Needed if you use versionAsInProject() -->
+            <!--    <plugin>
+                <groupId>org.apache.servicemix.tooling</groupId>
+                <artifactId>depends-maven-plugin</artifactId>
+                <version>1.2</version>
+                <executions>
+                    <execution>
+                        <id>generate-depends-file</id>
+                        <goals>
+                            <goal>generate-depends-file</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin> -->
+        </plugins>
+    </build>
+</project>
diff --git a/itests/base-features-it/src/test/java/org/opendaylight/controller/base/BaseFeatureTest.java b/itests/base-features-it/src/test/java/org/opendaylight/controller/base/BaseFeatureTest.java
new file mode 100644 (file)
index 0000000..0d38940
--- /dev/null
@@ -0,0 +1,74 @@
+package org.opendaylight.controller.base;
+
+import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
+
+import java.io.File;
+import java.net.URI;
+import java.util.EnumSet;
+
+import javax.inject.Inject;
+
+import junit.framework.Assert;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
+
+
+@RunWith(PaxExam.class)
+public class BaseFeatureTest {
+   @Inject
+   private FeaturesService featuresService;
+    @Configuration
+    public Option[] config() {
+       return new Option[] {
+             // Provision and launch a container based on a distribution of Karaf (Apache ServiceMix).
+             karafDistributionConfiguration()
+                 .frameworkUrl(
+                          maven()
+                                  .groupId("org.opendaylight.controller")
+                                  .artifactId("distribution.opendaylight-karaf")
+                                  .type("tar.gz")
+                                  .version("1.4.2-SNAPSHOT"))
+                 .name("OpenDaylight")
+                 .unpackDirectory(new File("target/pax"))
+                 .useDeployFolder(false),
+             // It is really nice if the container sticks around after the test so you can check the contents
+             // of the data directory when things go wrong.
+             keepRuntimeFolder(),
+             // Don't bother with local console output as it just ends up cluttering the logs
+             configureConsole().ignoreLocalConsole(),
+             // Force the log level to INFO so we have more details during the test.  It defaults to WARN.
+             logLevel(LogLevel.WARN),
+             // Remember that the test executes in another process.  If you want to debug it, you need
+             // to tell Pax Exam to launch that process with debugging enabled.  Launching the test class itself with
+             // debugging enabled (for example in Eclipse) will not get you the desired results.
+             //debugConfiguration("5000", true),
+       };
+    }
+
+    @Test
+    public void testAllFeatures() throws Exception {
+       featuresService.addRepository(new URI("mvn:org.opendaylight.controller/base-features/1.4.2-SNAPSHOT/xml/features"));
+       Repository repoUnderTest = featuresService.getRepository("base-1.4.2-SNAPSHOT");
+       Assert.assertNotNull(repoUnderTest);
+       Feature[] featuresUnderTest = repoUnderTest.getFeatures();
+       for(int i=0; i< featuresUnderTest.length; i++)
+       {
+          Feature feature = featuresUnderTest[i];
+          featuresService.installFeature(feature,EnumSet.of(FeaturesService.Option.Verbose));
+          System.out.println("Testing Feature:"+feature.getName());
+          Assert.assertTrue(featuresService.isInstalled(feature));
+       }
+    }
+}
\ No newline at end of file
diff --git a/itests/pom.xml b/itests/pom.xml
new file mode 100644 (file)
index 0000000..19836a2
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../opendaylight/commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>itests-controller</artifactId>
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <modules>
+    <module>base-features-it</module>
+  </modules>
+</project>
index be88e4a5059c335147a2ebacdb4f09851bbbc0e9..4f678f685473f5289dd73bae023ae5a0a4c271c5 100644 (file)
@@ -95,6 +95,7 @@
     <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>
+    <hosttracker.shell.version>1.0.0-SNAPSHOT</hosttracker.shell.version>
     <hosttracker_new.api.version>0.4.2-SNAPSHOT</hosttracker_new.api.version>
     <hosttracker_new.implementation.version>0.4.2-SNAPSHOT</hosttracker_new.implementation.version>
     <httpservice-bridge.northbound.version>0.0.2-SNAPSHOT</httpservice-bridge.northbound.version>
     <jsr305.api.version>2.0.1</jsr305.api.version>
     <jsr311.api.version>1.1.1</jsr311.api.version>
     <jsr311.v2.api.version>2.0</jsr311.v2.api.version>
-    <junit.version>4.8.1</junit.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>
     <northbound.jolokia.version>1.4.2-SNAPSHOT</northbound.jolokia.version>
     <opendaylight-l2-types.version>2013.08.27.4-SNAPSHOT</opendaylight-l2-types.version>
     <osgi-brandfragment.web.version>0.0.2-SNAPSHOT</osgi-brandfragment.web.version>
+    <pax.exam.version>4.0.0</pax.exam.version>
     <parboiled.version>1.1.6</parboiled.version>
     <parboiled.scala.version>1.1.6</parboiled.scala.version>
     <propertymavenplugin.version>1.0-alpha-2</propertymavenplugin.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-jacoco-listeners.version>2.4</sonar-jacoco-listeners.version>
     <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
     <sonar.language>java</sonar.language>
+    <sonar.jacoco.reportPath>target/code-coverage/jacoco.exec</sonar.jacoco.reportPath>
+    <sonar.jacoco.itReportPath>target/code-coverage/jacoco-it.exec</sonar.jacoco.itReportPath>
     <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2,org.opendaylight.controller.protobuff.messages</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>
-    <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2</sonar.skippedModules>
     <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.northbound.version>0.4.2-SNAPSHOT</topology.northbound.version>
     <topology.web.version>0.4.2-SNAPSHOT</topology.web.version>
     <topologymanager.version>0.4.2-SNAPSHOT</topologymanager.version>
+    <topologymanager.shell.version>1.0.0-SNAPSHOT</topologymanager.shell.version>
     <troubleshoot.web.version>0.4.2-SNAPSHOT</troubleshoot.web.version>
     <typesafe.config.version>1.2.0</typesafe.config.version>
     <uncommons.maths.version>1.2.2</uncommons.maths.version>
         <artifactId>akka-testkit_${scala.version}</artifactId>
         <version>${akka.version}</version>
       </dependency>
+        <dependency>
+            <groupId>com.typesafe.akka</groupId>
+            <artifactId>akka-osgi_${scala.version}</artifactId>
+            <version>${akka.version}</version>
+        </dependency>
       <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</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>sal-rest-connector-config</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-netty-config</artifactId>
+        <version>${config.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>md-sal-config</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-config</artifactId>
+        <version>${netconf.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-connector-config</artifactId>
+        <version>${netconf.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>sal-rest-docgen</artifactId>
         <artifactId>sal-test-model</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-distributed-datastore</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-clustering-commons</artifactId>
+            <version>${mdsal.version}</version>
+        </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-clustering-config</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-remoterpc-connector</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+
 
       <!-- SAL Extension bundles -->
       <dependency>
         <artifactId>model-flow-base</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller.model</groupId>
-        <artifactId>model-flow-management</artifactId>
-        <version>${mdsal.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.model</groupId>
         <artifactId>model-flow-service</artifactId>
         <artifactId>sample-toaster-provider</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.samples</groupId>
+        <artifactId>toaster-config</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>com.sun.jersey.jersey-servlet</artifactId>
         <artifactId>util</artifactId>
         <version>${yangtools.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yang-data-composite-node</artifactId>
+        <version>${yangtools.version}</version>
+      </dependency>
 
       <!-- yangtools dependencies -->
       <dependency>
         <artifactId>slf4j-simple</artifactId>
         <version>${slf4j.version}</version>
       </dependency>
-      <dependency>
-        <groupId>junit</groupId>
-        <artifactId>junit</artifactId>
-        <version>${junit.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>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-features</artifactId>
+        <version>${config.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-odl-protocol-framework</artifactId>
+        <version>${protocol-framework.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>netconf-features</artifactId>
+        <version>${netconf.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-persister-features</artifactId>
+        <version>${config.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-netty-features</artifactId>
+        <version>${config.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-adsal</artifactId>
+        <version>${sal.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-features</artifactId>
+        <version>${mdsal.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
+  <dependencies>
+    <!-- Sonar -->
+    <dependency>
+      <groupId>org.codehaus.sonar-plugins.java</groupId>
+      <artifactId>sonar-jacoco-listeners</artifactId>
+      <version>${sonar-jacoco-listeners.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
   <build>
     <pluginManagement>
       <plugins>
           <groupId>org.jacoco</groupId>
           <artifactId>jacoco-maven-plugin</artifactId>
           <version>${jacoco.version}</version>
+          <executions>
+            <execution>
+              <id>prepare-ut-agent</id>
+              <phase>process-test-classes</phase>
+              <goals>
+                <goal>prepare-agent</goal>
+              </goals>
+              <configuration>
+                <destFile>${sonar.jacoco.reportPath}</destFile>
+                <propertyName>jacoco.agent.ut.arg</propertyName>
+              </configuration>
+            </execution>
+            <execution>
+              <id>prepare-it-agent</id>
+              <phase>pre-integration-test</phase>
+              <goals>
+                <goal>prepare-agent</goal>
+              </goals>
+              <configuration>
+                <destFile>${sonar.jacoco.itReportPath}</destFile>
+                <propertyName>jacoco.agent.it.arg</propertyName>
+              </configuration>
+            </execution>
+          </executions>
         </plugin>
         <plugin>
           <groupId>org.opendaylight.yangtools</groupId>
         <artifactId>maven-failsafe-plugin</artifactId>
         <version>${failsafe.version}</version>
         <configuration>
-          <argLine>${testvm.argLine}</argLine>
+          <argLine>${testvm.argLine} ${jacoco.agent.it.arg}</argLine>
           <systemProperties>
             <property>
               <name>logback.configurationFile</name>
               <value>logback.xml</value>
             </property>
           </systemProperties>
+          <!-- Specific to generate mapping between tests and covered code -->
+          <properties>
+            <property>
+                <name>listener</name>
+                <value>org.sonar.java.jacoco.JUnitListener</value>
+            </property>
+          </properties>
         </configuration>
         <executions>
           <execution>
         <artifactId>maven-surefire-plugin</artifactId>
         <version>${surefire.version}</version>
         <configuration>
-          <argLine>${testvm.argLine}</argLine>
+          <argLine>${testvm.argLine} ${jacoco.agent.ut.arg}</argLine>
           <systemProperties>
             <property>
               <name>logback.configurationFile</name>
               <value>logback.xml</value>
             </property>
           </systemProperties>
+          <!-- Specific to generate mapping between tests and covered code -->
+          <properties>
+            <property>
+                <name>listener</name>
+                <value>org.sonar.java.jacoco.JUnitListener</value>
+            </property>
+          </properties>
         </configuration>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
       </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+      </plugin>
     </plugins>
   </build>
 
index f70698731aa0aea9e1cc6f1cff86d4ded144b454..774bc7c23f178b30f26b94d65212a595d5941b4a 100644 (file)
       <artifactId>netty-event-executor-config</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
index a62bd7da06501b355c41f36230dbf30a982d61fa..a05d02cd09ad4e1b447a61da687768bc58e3dd94 100644 (file)
@@ -7,12 +7,19 @@
  */
 package org.opendaylight.protocol.framework;
 
+import java.io.Closeable;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 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.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelInitializer;
 import io.netty.channel.ChannelOption;
@@ -28,13 +35,6 @@ 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;
-
 /**
  * Dispatcher class for creating servers and clients. The idea is to first create servers and clients and the run the
  * start method that will handle sockets in different thread.
@@ -155,7 +155,7 @@ 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);
+        final ProtocolSessionPromise<S> p = new ProtocolSessionPromise<>(executor, address, strategy, b);
         b.option(ChannelOption.SO_KEEPALIVE, true).handler(
                 new ChannelInitializer<SocketChannel>() {
                     @Override
@@ -165,18 +165,36 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
                 });
 
         customizeBootstrap(b);
+        setWorkerGroup(b);
+        setChannelFactory(b);
+
+        p.connect();
+        LOG.debug("Client created.");
+        return p;
+    }
 
+    private void setWorkerGroup(final Bootstrap 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);
-        }
+    /**
+     * Create a client but use a pre-configured bootstrap.
+     * This method however replaces the ChannelInitializer in the bootstrap. All other configuration is preserved.
+     *
+     * @param address remote address
+     */
+    protected Future<S> createClient(final InetSocketAddress address, final ReconnectStrategy strategy, final Bootstrap bootstrap, final PipelineInitializer<S> initializer) {
+        final ProtocolSessionPromise<S> p = new ProtocolSessionPromise<>(executor, address, strategy, bootstrap);
+
+        bootstrap.handler(
+                new ChannelInitializer<SocketChannel>() {
+                    @Override
+                    protected void initChannel(final SocketChannel ch) {
+                        initializer.initializeChannel(ch, p);
+                    }
+                });
 
         p.connect();
         LOG.debug("Client created.");
@@ -195,6 +213,9 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
     }
 
     /**
+     *
+     * @deprecated use {@link org.opendaylight.protocol.framework.AbstractDispatcher#createReconnectingClient(java.net.InetSocketAddress, ReconnectStrategyFactory, org.opendaylight.protocol.framework.AbstractDispatcher.PipelineInitializer)} with only one reconnectStrategyFactory instead.
+     *
      * Creates a client.
      *
      * @param address remote address
@@ -204,15 +225,47 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
      * @return Future representing the reconnection task. It will report completion based on reestablishStrategy, e.g.
      *         success if it indicates no further attempts should be made and failure if it reports an error
      */
+    @Deprecated
     protected Future<Void> createReconnectingClient(final InetSocketAddress address, final ReconnectStrategyFactory connectStrategyFactory,
             final ReconnectStrategy reestablishStrategy, final PipelineInitializer<S> initializer) {
+        return createReconnectingClient(address, connectStrategyFactory, initializer);
+    }
 
-        final ReconnectPromise<S, L> p = new ReconnectPromise<S, L>(GlobalEventExecutor.INSTANCE, this, address, connectStrategyFactory, reestablishStrategy, initializer);
-        p.connect();
+    /**
+     * Creates a reconnecting client.
+     *
+     * @param address remote address
+     * @param connectStrategyFactory Factory for creating reconnection strategy for every reconnect attempt
+     *
+     * @return Future representing the reconnection task. It will report completion based on reestablishStrategy, e.g.
+     *         success if it indicates no further attempts should be made and failure if it reports an error
+     */
+    protected Future<Void> createReconnectingClient(final InetSocketAddress address, final ReconnectStrategyFactory connectStrategyFactory,
+            final PipelineInitializer<S> initializer) {
+        final Bootstrap b = new Bootstrap();
+
+        final ReconnectPromise<S, L> p = new ReconnectPromise<>(GlobalEventExecutor.INSTANCE, this, address, connectStrategyFactory, b, initializer);
+
+        b.option(ChannelOption.SO_KEEPALIVE, true);
 
+        customizeBootstrap(b);
+        setWorkerGroup(b);
+        setChannelFactory(b);
+
+        p.connect();
         return p;
     }
 
+    private void setChannelFactory(final Bootstrap b) {
+        // There is no way to detect if this was already set by
+        // customizeBootstrap()
+        try {
+            b.channel(NioSocketChannel.class);
+        } catch (final IllegalStateException e) {
+            LOG.trace("Not overriding channelFactory on bootstrap {}", b, e);
+        }
+    }
+
     /**
      * @deprecated Should only be used with {@link AbstractDispatcher#AbstractDispatcher()}
      */
@@ -225,5 +278,4 @@ public abstract class AbstractDispatcher<S extends ProtocolSession<?>, L extends
             this.bossGroup.shutdownGracefully();
         }
     }
-
 }
index a78274cca0ca4f49e3c14ce69e6e6815b7a7e395..a38db61eaddcdb4ebd2daa79f03790fc6bde2007 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.protocol.framework;
 
+import com.google.common.base.Preconditions;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
@@ -16,17 +17,12 @@ import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.FutureListener;
 import io.netty.util.concurrent.Promise;
-
 import java.net.InetSocketAddress;
-
 import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.ThreadSafe;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 @ThreadSafe
 final class ProtocolSessionPromise<S extends ProtocolSession<?>> extends DefaultPromise<S> {
     private static final Logger LOG = LoggerFactory.getLogger(ProtocolSessionPromise.class);
@@ -54,72 +50,12 @@ final class ProtocolSessionPromise<S extends ProtocolSession<?>> extends Default
             LOG.debug("Promise {} attempting connect for {}ms", lock, timeout);
 
             this.b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeout);
-            this.pending = this.b.connect(this.address).addListener(new ChannelFutureListener() {
-                @Override
-                public void operationComplete(final ChannelFuture cf) throws Exception {
-                    synchronized (lock) {
-
-                        LOG.debug("Promise {} connection resolved", lock);
-
-                        // Triggered when a connection attempt is resolved.
-                        Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(cf));
-
-                        /*
-                         * The promise we gave out could have been cancelled,
-                         * which cascades to the connect getting cancelled,
-                         * but there is a slight race window, where the connect
-                         * is already resolved, but the listener has not yet
-                         * been notified -- cancellation at that point won't
-                         * stop the notification arriving, so we have to close
-                         * the race here.
-                         */
-                        if (isCancelled()) {
-                            if (cf.isSuccess()) {
-                                LOG.debug("Closing channel for cancelled promise {}", lock);
-                                cf.channel().close();
-                            }
-                            return;
-                        }
-
-                        if (!cf.isSuccess()) {
-                            LOG.debug("Attempt to connect to {} failed", ProtocolSessionPromise.this.address, cf.cause());
-
-                            final Future<Void> rf = ProtocolSessionPromise.this.strategy.scheduleReconnect(cf.cause());
-                            rf.addListener(new FutureListener<Void>() {
-                                @Override
-                                public void operationComplete(final Future<Void> sf) {
-                                    synchronized (lock) {
-                                        // Triggered when a connection attempt is to be made.
-                                        Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(sf));
-
-                                        /*
-                                         * The promise we gave out could have been cancelled,
-                                         * which cascades to the reconnect attempt getting
-                                         * cancelled, but there is a slight race window, where
-                                         * the reconnect attempt is already enqueued, but the
-                                         * listener has not yet been notified -- if cancellation
-                                         * happens at that point, we need to catch it here.
-                                         */
-                                        if (!isCancelled()) {
-                                            if (sf.isSuccess()) {
-                                                connect();
-                                            } else {
-                                                setFailure(sf.cause());
-                                            }
-                                        }
-                                    }
-                                }
-                            });
-
-                            ProtocolSessionPromise.this.pending = rf;
-                        } else {
-                            LOG.debug("Promise {} connection successful", lock);
-                        }
-                    }
-                }
-            });
+            final ChannelFuture connectFuture = this.b.connect(this.address);
+            // Add listener that attempts reconnect by invoking this method again.
+            connectFuture.addListener(new BootstrapConnectListener(lock));
+            this.pending = connectFuture;
         } catch (final Exception e) {
-            LOG.info("Failed to connect to {}", e);
+            LOG.info("Failed to connect to {}", address, e);
             setFailure(e);
         }
     }
@@ -140,4 +76,79 @@ final class ProtocolSessionPromise<S extends ProtocolSession<?>> extends Default
         this.strategy.reconnectSuccessful();
         return super.setSuccess(result);
     }
+
+    private class BootstrapConnectListener implements ChannelFutureListener {
+        private final Object lock;
+
+        public BootstrapConnectListener(final Object lock) {
+            this.lock = lock;
+        }
+
+        @Override
+        public void operationComplete(final ChannelFuture cf) throws Exception {
+            synchronized (lock) {
+
+                LOG.debug("Promise {} connection resolved", lock);
+
+                // Triggered when a connection attempt is resolved.
+                Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(cf));
+
+                /*
+                 * The promise we gave out could have been cancelled,
+                 * which cascades to the connect getting cancelled,
+                 * but there is a slight race window, where the connect
+                 * is already resolved, but the listener has not yet
+                 * been notified -- cancellation at that point won't
+                 * stop the notification arriving, so we have to close
+                 * the race here.
+                 */
+                if (isCancelled()) {
+                    if (cf.isSuccess()) {
+                        LOG.debug("Closing channel for cancelled promise {}", lock);
+                        cf.channel().close();
+                    }
+                    return;
+                }
+
+                if(cf.isSuccess()) {
+                    LOG.debug("Promise {} connection successful", lock);
+                    return;
+                }
+
+                LOG.debug("Attempt to connect to {} failed", ProtocolSessionPromise.this.address, cf.cause());
+
+                final Future<Void> rf = ProtocolSessionPromise.this.strategy.scheduleReconnect(cf.cause());
+                rf.addListener(new ReconnectingStrategyListener());
+                ProtocolSessionPromise.this.pending = rf;
+            }
+        }
+
+        private class ReconnectingStrategyListener implements FutureListener<Void> {
+            @Override
+            public void operationComplete(final Future<Void> sf) {
+                synchronized (lock) {
+                    // Triggered when a connection attempt is to be made.
+                    Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(sf));
+
+                    /*
+                     * The promise we gave out could have been cancelled,
+                     * which cascades to the reconnect attempt getting
+                     * cancelled, but there is a slight race window, where
+                     * the reconnect attempt is already enqueued, but the
+                     * listener has not yet been notified -- if cancellation
+                     * happens at that point, we need to catch it here.
+                     */
+                    if (!isCancelled()) {
+                        if (sf.isSuccess()) {
+                            connect();
+                        } else {
+                            setFailure(sf.cause());
+                        }
+                    }
+                }
+            }
+        }
+
+    }
+
 }
index 1fa6a8175352617aa8f87a56e90f6d391bdef029..fe1012f443fc7824b1e2b8b3d3c4ed15ecbfb30d 100644 (file)
  */
 package org.opendaylight.protocol.framework;
 
-import io.netty.channel.ChannelFuture;
+import com.google.common.base.Preconditions;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.DefaultPromise;
 import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.FutureListener;
 import io.netty.util.concurrent.Promise;
-
-import java.io.Closeable;
 import java.net.InetSocketAddress;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.opendaylight.protocol.framework.AbstractDispatcher.PipelineInitializer;
-
-import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 final class ReconnectPromise<S extends ProtocolSession<?>, L extends SessionListener<?, ?, ?>> extends DefaultPromise<Void> {
+    private static final Logger LOG = LoggerFactory.getLogger(ReconnectPromise.class);
+
     private final AbstractDispatcher<S, L> dispatcher;
     private final InetSocketAddress address;
     private final ReconnectStrategyFactory strategyFactory;
-    private final ReconnectStrategy strategy;
-    private final PipelineInitializer<S> initializer;
+    private final Bootstrap b;
+    private final AbstractDispatcher.PipelineInitializer<S> initializer;
     private Future<?> pending;
 
-    private final AtomicBoolean negotiationFinished = new AtomicBoolean(false);
-
     public ReconnectPromise(final EventExecutor executor, final AbstractDispatcher<S, L> dispatcher, final InetSocketAddress address,
-            final ReconnectStrategyFactory connectStrategyFactory, final ReconnectStrategy reestablishStrategy,
-            final PipelineInitializer<S> initializer) {
+                            final ReconnectStrategyFactory connectStrategyFactory, final Bootstrap b, final AbstractDispatcher.PipelineInitializer<S> initializer) {
         super(executor);
+        this.b = b;
+        this.initializer = Preconditions.checkNotNull(initializer);
         this.dispatcher = Preconditions.checkNotNull(dispatcher);
         this.address = Preconditions.checkNotNull(address);
         this.strategyFactory = Preconditions.checkNotNull(connectStrategyFactory);
-        this.strategy = Preconditions.checkNotNull(reestablishStrategy);
-        this.initializer = Preconditions.checkNotNull(initializer);
     }
 
-    // FIXME: BUG-190: refactor
-
     synchronized void connect() {
-        negotiationFinished.set(false);
-
         final ReconnectStrategy cs = this.strategyFactory.createReconnectStrategy();
-        final ReconnectStrategy rs = new ReconnectStrategy() {
-            @Override
-            public Future<Void> scheduleReconnect(final Throwable cause) {
-                return cs.scheduleReconnect(cause);
-            }
 
-            @Override
-            public void reconnectSuccessful() {
-                cs.reconnectSuccessful();
-            }
-
-            @Override
-            public int getConnectTimeout() throws Exception {
-                final int cst = cs.getConnectTimeout();
-                final int rst = ReconnectPromise.this.strategy.getConnectTimeout();
-
-                if (cst == 0) {
-                    return rst;
-                }
-                if (rst == 0) {
-                    return cst;
-                }
-                return Math.min(cst, rst);
-            }
-        };
-
-        final Future<S> cf = this.dispatcher.createClient(this.address, rs, new PipelineInitializer<S>() {
+        // Set up a client with pre-configured bootstrap, but add a closed channel handler into the pipeline to support reconnect attempts
+        pending = this.dispatcher.createClient(this.address, cs, b, new AbstractDispatcher.PipelineInitializer<S>() {
             @Override
             public void initializeChannel(final SocketChannel channel, final Promise<S> promise) {
-                addChannelClosedListener(channel.closeFuture());
                 initializer.initializeChannel(channel, promise);
+
+                // add closed channel handler
+                channel.pipeline().addFirst(new ClosedChannelHandler(ReconnectPromise.this));
             }
         });
+    }
 
-        final Object lock = this;
-        this.pending = cf;
+    /**
+     *
+     * @return true if initial connection was established successfully, false if initial connection failed due to e.g. Connection refused, Negotiation failed
+     */
+    private boolean isInitialConnectFinished() {
+        Preconditions.checkNotNull(pending);
+        return pending.isDone() && pending.isSuccess();
+    }
 
-        cf.addListener(new FutureListener<S>() {
+    @Override
+    public synchronized boolean cancel(final boolean mayInterruptIfRunning) {
+        if (super.cancel(mayInterruptIfRunning)) {
+            Preconditions.checkNotNull(pending);
+            this.pending.cancel(mayInterruptIfRunning);
+            return true;
+        }
 
-            @Override
-            public void operationComplete(final Future<S> future) {
-                synchronized (lock) {
-                    if (!future.isSuccess()) {
-                        final Future<Void> rf = ReconnectPromise.this.strategy.scheduleReconnect(cf.cause());
-
-                        if(rf == null) {
-                            // This should reflect: no more reconnecting strategies, enough
-                            // Currently all reconnect strategies fail with exception, should return null
-                            return;
-                        }
-
-                        ReconnectPromise.this.pending = rf;
-
-                        rf.addListener(new FutureListener<Void>() {
-                            @Override
-                            public void operationComplete(final Future<Void> sf) {
-                                synchronized (lock) {
-                                    /*
-                                     * The promise we gave out could have been cancelled,
-                                     * which cascades to the reconnect attempt getting
-                                     * cancelled, but there is a slight race window, where
-                                     * the reconnect attempt is already enqueued, but the
-                                     * listener has not yet been notified -- if cancellation
-                                     * happens at that point, we need to catch it here.
-                                     */
-                                    if (!isCancelled()) {
-                                        if (sf.isSuccess()) {
-                                            connect();
-                                        } else {
-                                            setFailure(sf.cause());
-                                        }
-                                    }
-                                }
-                            }
-                        });
-                    } else {
-                        /*
-                         *  FIXME: BUG-190: we have a slight race window with cancellation
-                         *         here. Analyze and define its semantics.
-                         */
-                        ReconnectPromise.this.strategy.reconnectSuccessful();
-                        negotiationFinished.set(true);
-                    }
-                }
-            }
-        });
+        return false;
     }
 
-    private final ClosedChannelListener closedChannelListener = new ClosedChannelListener();
-
-    class ClosedChannelListener implements Closeable, FutureListener<Void> {
+    /**
+     * Channel handler that responds to channelInactive event and reconnects the session.
+     * Only if the initial connection was successfully established and promise was not canceled.
+     */
+    private static final class ClosedChannelHandler extends ChannelInboundHandlerAdapter {
+        private final ReconnectPromise<?, ?> promise;
 
-        private final AtomicBoolean stop = new AtomicBoolean(false);
+        public ClosedChannelHandler(final ReconnectPromise<?, ?> promise) {
+            this.promise = promise;
+        }
 
         @Override
-        public void operationComplete(final Future<Void> future) throws Exception {
-            if (stop.get()) {
+        public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
+            if (promise.isCancelled()) {
                 return;
             }
 
-            // Start reconnecting crashed session after negotiation was successful
-            if (!negotiationFinished.get()) {
+            // Check if initial connection was fully finished. If the session was dropped during negotiation, reconnect will not happen.
+            // Session can be dropped during negotiation on purpose by the client side and would make no sense to initiate reconnect
+            if (promise.isInitialConnectFinished() == false) {
                 return;
             }
 
-            connect();
-        }
-
-        @Override
-        public void close() {
-            this.stop.set(true);
+            LOG.debug("Reconnecting after connection to {} was dropped", promise.address);
+            promise.connect();
         }
     }
 
-    private void addChannelClosedListener(final ChannelFuture channelFuture) {
-        channelFuture.addListener(closedChannelListener);
-    }
-
-    @Override
-    public synchronized boolean cancel(final boolean mayInterruptIfRunning) {
-        closedChannelListener.close();
-
-        if (super.cancel(mayInterruptIfRunning)) {
-            this.pending.cancel(mayInterruptIfRunning);
-            return true;
-        }
-
-        return false;
-    }
 }
index 3c429fc7749be6b4ac37cf5e5800f5978861fa2c..a756a0da7e780e84510d8e329b475b9342e0c9e7 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.protocol.framework;
 import java.util.EventListener;
 
 /**
- * Listener that receives session state informations. This interface should be
+ * Listener that receives session state information. This interface should be
  * implemented by a protocol specific abstract class, that is extended by
  * a final class that implements the methods.
  */
index bead1ee49e64bd1b708ecc6d23c51321f4cc72bd..63026e384c498ce12dca810c94886f9a562215d8 100644 (file)
@@ -9,6 +9,14 @@ package org.opendaylight.protocol.framework;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.nio.NioEventLoopGroup;
@@ -16,50 +24,139 @@ import io.netty.util.concurrent.DefaultPromise;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
 import io.netty.util.concurrent.Promise;
-
+import io.netty.util.concurrent.SucceededFuture;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 public class ServerTest {
     SimpleDispatcher clientDispatcher, dispatcher;
 
-    final SimpleSessionListener pce = new SimpleSessionListener();
-
     SimpleSession session = null;
 
     ChannelFuture server = null;
 
     InetSocketAddress serverAddress;
     private NioEventLoopGroup eventLoopGroup;
-
+    // Dedicated loop group for server, needed for testing reconnection client
+    // With dedicated server group we can simulate session drop by shutting only the server group down
+    private NioEventLoopGroup serverLoopGroup;
 
     @Before
     public void setUp() {
         final int port = 10000 + (int)(10000 * Math.random());
         serverAddress = new InetSocketAddress("127.0.0.1", port);
         eventLoopGroup = new NioEventLoopGroup();
+        serverLoopGroup = new NioEventLoopGroup();
+    }
+
+    @After
+    public void tearDown() throws IOException, InterruptedException, ExecutionException {
+        if(server != null) {
+            this.server.channel().close();
+        }
+        this.eventLoopGroup.shutdownGracefully().get();
+        this.serverLoopGroup.shutdownGracefully().get();
+        try {
+            Thread.sleep(500);
+        } catch (final InterruptedException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
-    public void testConnectionEstablished() throws Exception {
+    public void testConnectionRefused() throws Exception {
+        this.clientDispatcher = getClientDispatcher();
+
+        final ReconnectStrategy mockReconnectStrategy = getMockedReconnectStrategy();
+
+        this.clientDispatcher.createClient(this.serverAddress,
+                mockReconnectStrategy, new SessionListenerFactory<SimpleSessionListener>() {
+                    @Override
+                    public SimpleSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                });
+
+        Mockito.verify(mockReconnectStrategy, timeout(5000).atLeast(2)).scheduleReconnect(any(Throwable.class));
+    }
+
+    @Test
+    public void testConnectionReestablishInitial() throws Exception {
+        this.clientDispatcher = getClientDispatcher();
+
+        final ReconnectStrategy mockReconnectStrategy = getMockedReconnectStrategy();
+
+        this.clientDispatcher.createClient(this.serverAddress,
+                mockReconnectStrategy, new SessionListenerFactory<SimpleSessionListener>() {
+                    @Override
+                    public SimpleSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                });
+
+        Mockito.verify(mockReconnectStrategy, timeout(5000).atLeast(2)).scheduleReconnect(any(Throwable.class));
+
+        final Promise<Boolean> p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+        this.dispatcher = getServerDispatcher(p);
+
+        this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory<SimpleSessionListener>() {
+            @Override
+            public SimpleSessionListener getSessionListener() {
+                return new SimpleSessionListener();
+            }
+        });
+
+        this.server.get();
+
+        assertEquals(true, p.get(3, TimeUnit.SECONDS));
+    }
+
+    @Test
+    public void testConnectionDrop() throws Exception {
         final Promise<Boolean> p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
 
-        this.dispatcher = new SimpleDispatcher(new SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener>() {
+        this.dispatcher = getServerDispatcher(p);
 
+        this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory<SimpleSessionListener>() {
             @Override
-            public SessionNegotiator<SimpleSession> getSessionNegotiator(final SessionListenerFactory<SimpleSessionListener> factory,
-                    final Channel channel, final Promise<SimpleSession> promise) {
-                p.setSuccess(true);
-                return new SimpleSessionNegotiator(promise, channel);
+            public SimpleSessionListener getSessionListener() {
+                return new SimpleSessionListener();
             }
-        }, new DefaultPromise<SimpleSession>(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+        });
+
+        this.server.get();
+
+        this.clientDispatcher = getClientDispatcher();
+
+        final ReconnectStrategy reconnectStrategy = getMockedReconnectStrategy();
+        this.session = this.clientDispatcher.createClient(this.serverAddress,
+                reconnectStrategy, new SessionListenerFactory<SimpleSessionListener>() {
+                    @Override
+                    public SimpleSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                }).get(6, TimeUnit.SECONDS);
+
+        assertEquals(true, p.get(3, TimeUnit.SECONDS));
+
+        shutdownServer();
+
+        // No reconnect should be scheduled after server drops connection with not-reconnecting client
+        verify(reconnectStrategy, times(0)).scheduleReconnect(any(Throwable.class));
+    }
+
+    @Test
+    public void testConnectionReestablishAfterDrop() throws Exception {
+        final Promise<Boolean> p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+
+        this.dispatcher = getServerDispatcher(p);
 
         this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory<SimpleSessionListener>() {
             @Override
@@ -70,13 +167,42 @@ public class ServerTest {
 
         this.server.get();
 
-        this.clientDispatcher = new SimpleDispatcher(new SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener>() {
+        this.clientDispatcher = getClientDispatcher();
+
+        final ReconnectStrategyFactory reconnectStrategyFactory = mock(ReconnectStrategyFactory.class);
+        final ReconnectStrategy reconnectStrategy = getMockedReconnectStrategy();
+        doReturn(reconnectStrategy).when(reconnectStrategyFactory).createReconnectStrategy();
+
+        this.clientDispatcher.createReconnectingClient(this.serverAddress,
+                reconnectStrategyFactory, new SessionListenerFactory<SimpleSessionListener>() {
+                    @Override
+                    public SimpleSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                });
+
+        assertEquals(true, p.get(3, TimeUnit.SECONDS));
+        shutdownServer();
+
+        verify(reconnectStrategyFactory, timeout(20000).atLeast(2)).createReconnectStrategy();
+    }
+
+    @Test
+    public void testConnectionEstablished() throws Exception {
+        final Promise<Boolean> p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+
+        this.dispatcher = getServerDispatcher(p);
+
+        this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory<SimpleSessionListener>() {
             @Override
-            public SessionNegotiator<SimpleSession> getSessionNegotiator(final SessionListenerFactory<SimpleSessionListener> factory,
-                    final Channel channel, final Promise<SimpleSession> promise) {
-                return new SimpleSessionNegotiator(promise, channel);
+            public SimpleSessionListener getSessionListener() {
+                return new SimpleSessionListener();
             }
-        }, new DefaultPromise<SimpleSession>(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+        });
+
+        this.server.get();
+
+        this.clientDispatcher = getClientDispatcher();
 
         this.session = this.clientDispatcher.createClient(this.serverAddress,
                 new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 5000), new SessionListenerFactory<SimpleSessionListener>() {
@@ -93,15 +219,7 @@ public class ServerTest {
     public void testConnectionFailed() throws IOException, InterruptedException, ExecutionException, TimeoutException {
         final Promise<Boolean> p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
 
-        this.dispatcher = new SimpleDispatcher(new SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener>() {
-
-            @Override
-            public SessionNegotiator<SimpleSession> getSessionNegotiator(final SessionListenerFactory<SimpleSessionListener> factory,
-                    final Channel channel, final Promise<SimpleSession> promise) {
-                p.setSuccess(true);
-                return new SimpleSessionNegotiator(promise, channel);
-            }
-        }, new DefaultPromise<SimpleSession>(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+        this.dispatcher = getServerDispatcher(p);
 
         this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory<SimpleSessionListener>() {
             @Override
@@ -112,13 +230,7 @@ public class ServerTest {
 
         this.server.get();
 
-        this.clientDispatcher = new SimpleDispatcher(new SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener>() {
-            @Override
-            public SessionNegotiator<SimpleSession> getSessionNegotiator(final SessionListenerFactory<SimpleSessionListener> factory,
-                    final Channel channel, final Promise<SimpleSession> promise) {
-                return new SimpleSessionNegotiator(promise, channel);
-            }
-        }, new DefaultPromise<SimpleSession>(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+        this.clientDispatcher = getClientDispatcher();
 
         this.session = this.clientDispatcher.createClient(this.serverAddress,
                 new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 5000), new SessionListenerFactory<SimpleSessionListener>() {
@@ -138,14 +250,89 @@ public class ServerTest {
         assertFalse(session.isSuccess());
     }
 
-    @After
-    public void tearDown() throws IOException, InterruptedException {
-        this.server.channel().close();
-        this.eventLoopGroup.shutdownGracefully();
-        try {
-            Thread.sleep(500);
-        } catch (final InterruptedException e) {
-            throw new RuntimeException(e);
-        }
+    @Test
+    public void testNegotiationFailedNoReconnect() throws Exception {
+        final Promise<Boolean> p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+
+        this.dispatcher = getServerDispatcher(p);
+
+        this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory<SimpleSessionListener>() {
+            @Override
+            public SimpleSessionListener getSessionListener() {
+                return new SimpleSessionListener();
+            }
+        });
+
+        this.server.get();
+
+        this.clientDispatcher = new SimpleDispatcher(new SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener>() {
+            @Override
+            public SessionNegotiator<SimpleSession> getSessionNegotiator(final SessionListenerFactory<SimpleSessionListener> factory,
+                                                                         final Channel channel, final Promise<SimpleSession> promise) {
+
+                return new SimpleSessionNegotiator(promise, channel) {
+                    @Override
+                    protected void startNegotiation() throws Exception {
+                        negotiationFailed(new IllegalStateException("Negotiation failed"));
+                    }
+                };
+            }
+        }, new DefaultPromise<SimpleSession>(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+
+        final ReconnectStrategyFactory reconnectStrategyFactory = mock(ReconnectStrategyFactory.class);
+        final ReconnectStrategy reconnectStrategy = getMockedReconnectStrategy();
+        doReturn(reconnectStrategy).when(reconnectStrategyFactory).createReconnectStrategy();
+
+        this.clientDispatcher.createReconnectingClient(this.serverAddress,
+                reconnectStrategyFactory, new SessionListenerFactory<SimpleSessionListener>() {
+                    @Override
+                    public SimpleSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                });
+
+
+        // Only one strategy should be created for initial connect, no more = no reconnects
+        verify(reconnectStrategyFactory, times(1)).createReconnectStrategy();
     }
+
+    private SimpleDispatcher getClientDispatcher() {
+        return new SimpleDispatcher(new SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener>() {
+            @Override
+            public SessionNegotiator<SimpleSession> getSessionNegotiator(final SessionListenerFactory<SimpleSessionListener> factory,
+                                                                         final Channel channel, final Promise<SimpleSession> promise) {
+                return new SimpleSessionNegotiator(promise, channel);
+            }
+        }, new DefaultPromise<SimpleSession>(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+    }
+
+    private ReconnectStrategy getMockedReconnectStrategy() throws Exception {
+        final ReconnectStrategy mockReconnectStrategy = mock(ReconnectStrategy.class);
+        final Future<Void> future = new SucceededFuture<>(GlobalEventExecutor.INSTANCE, null);
+        doReturn(future).when(mockReconnectStrategy).scheduleReconnect(any(Throwable.class));
+        doReturn(5000).when(mockReconnectStrategy).getConnectTimeout();
+        doNothing().when(mockReconnectStrategy).reconnectSuccessful();
+        return mockReconnectStrategy;
+    }
+
+
+    private void shutdownServer() throws InterruptedException, ExecutionException {
+        // Shutdown server
+        server.channel().close().get();
+        // Closing server channel does not close established connections, eventLoop has to be closed as well to simulate dropped session
+        serverLoopGroup.shutdownGracefully().get();
+    }
+
+    private SimpleDispatcher getServerDispatcher(final Promise<Boolean> p) {
+        return new SimpleDispatcher(new SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener>() {
+
+            @Override
+            public SessionNegotiator<SimpleSession> getSessionNegotiator(final SessionListenerFactory<SimpleSessionListener> factory,
+                                                                         final Channel channel, final Promise<SimpleSession> promise) {
+                p.setSuccess(true);
+                return new SimpleSessionNegotiator(promise, channel);
+            }
+        }, null, serverLoopGroup);
+    }
+
 }
index 12aac9ecc5257432ee282159f24dbb1fd2c319a5..d83738520cccc1e7bc24b4f97cb31c30ff6e51ad 100644 (file)
@@ -54,6 +54,10 @@ public class SimpleDispatcher extends AbstractDispatcher<SimpleSession, SimpleSe
         return super.createClient(address, strategy, new SimplePipelineInitializer(listenerFactory));
     }
 
+    public Future<Void> createReconnectingClient(final InetSocketAddress address, final ReconnectStrategyFactory strategy, final SessionListenerFactory<SimpleSessionListener> listenerFactory) {
+        return super.createReconnectingClient(address, strategy, new SimplePipelineInitializer(listenerFactory));
+    }
+
     public ChannelFuture createServer(final InetSocketAddress address, final SessionListenerFactory<SimpleSessionListener> listenerFactory) {
         return super.createServer(address, new SimplePipelineInitializer(listenerFactory));
     }
index fc2c0fd85b86f79a60c30fb34bc8199b1459c1c9..c98a47660ee3c92a8ebec0ea586d40af31dca99d 100644 (file)
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
       </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-          <threadCount>1</threadCount>
-        </configuration>
-      </plugin>
     </plugins>
   </build>
 
index ec46219aaf8469e3d8ecadcc9988bb4a47188e3f..6050f7c07073061fe4233e99d915308489bc5a7f 100644 (file)
@@ -14,7 +14,7 @@ import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy
 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.osgi.framework.BundleContext;
 
 /**
@@ -31,7 +31,7 @@ public class CodecRegistryProvider implements AutoCloseable {
     public CodecRegistryProvider(final ClassLoadingStrategy classLoadingStrategy, final BundleContext context) {
         service = new RuntimeGeneratedMappingServiceImpl(CLASS_POOL, classLoadingStrategy);
         registration = OsgiRegistrationUtil.registerService(context, service,
-                SchemaServiceListener.class, BindingIndependentMappingService.class);
+                SchemaContextListener.class, BindingIndependentMappingService.class);
     }
 
     public CodecRegistry getCodecRegistry() {
index ce3648d1607009aacd5ecc41e2a1f119660d8045..16de00508ab4e7ecf4d7fc6df22b6b476b37ae1d 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.controller.config.manager.impl.runtimembean;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
-import static org.junit.internal.matchers.StringContains.containsString;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
 
 import java.lang.management.ManagementFactory;
 import java.util.Map;
@@ -29,9 +31,6 @@ import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.HierarchicalRuntimeBeanRegistrationImpl;
 import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl;
 
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
 public class RuntimeBeanRegistratorImplTest extends
         AbstractLockedPlatformMBeanServerTest {
     static final String module1 = "module1";
@@ -60,11 +59,11 @@ public class RuntimeBeanRegistratorImplTest extends
         assertEquals(0, baseJMXRegistrator.getRegisteredObjectNames().size());
     }
 
-    protected void checkExists(ObjectName on) throws Exception {
+    protected void checkExists(final ObjectName on) throws Exception {
         platformMBeanServer.getMBeanInfo(on);
     }
 
-    protected void checkNotExists(ObjectName on) throws Exception {
+    protected void checkNotExists(final ObjectName on) throws Exception {
         try {
             platformMBeanServer.getMBeanInfo(on);
             fail();
@@ -98,7 +97,7 @@ public class RuntimeBeanRegistratorImplTest extends
     }
 
     private HierarchicalRuntimeBeanRegistration createAdditional(
-            HierarchicalRuntimeBeanRegistrationImpl rootRegistration)
+            final HierarchicalRuntimeBeanRegistrationImpl rootRegistration)
             throws Exception {
 
         HierarchicalRuntimeBeanRegistrationImpl registration = rootRegistration
index c9810d052149ead1b358d14b42bda64d33c707c9..165a6c7ed62e02bdbb05e5644962dc15b42712d9 100644 (file)
@@ -7,14 +7,16 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
 
+import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.junit.internal.matchers.StringContains.containsString;
 
 import java.util.Map;
+
 import javax.management.ObjectName;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/opendaylight/config/config-netty-config/pom.xml b/opendaylight/config/config-netty-config/pom.xml
new file mode 100644 (file)
index 0000000..8dc31dc
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-subsystem</artifactId>
+    <version>0.2.5-SNAPSHOT</version>
+  </parent>
+  <artifactId>config-netty-config</artifactId>
+  <description>Configuration files for sal-rest-connector</description>
+  <packaging>jar</packaging>
+  <build>
+       <plugins>
+               <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/initial/00-netty.xml</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
similarity index 99%
rename from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.xml
rename to opendaylight/config/config-netty-config/src/main/resources/initial/00-netty.xml
index 686d3631108d250f5dc56b825200e387536dd9c5..2bf5b36d7a770c43bc5a51fa2e7eb7c057624041 100644 (file)
@@ -15,7 +15,7 @@
         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&amp;revision=2013-11-19</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>
@@ -35,7 +35,7 @@
                     <name>singleton</name>
                 </module>
             </modules>
-            
+
             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                 <service>
                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
index 7429f4d57431c9922d9a33ef5e8053ef1cfd174f..fd9c1b91e3944146b0d1ad9fb63f78acc5b2daff 100644 (file)
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
       </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-          <threadCount>1</threadCount>
-        </configuration>
-      </plugin>
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
index 66bb01f051fa1042e9fc08d4019a236f1e07bb04..343d13e9c19194ad67680801639fdf52df9563b3 100644 (file)
@@ -39,6 +39,7 @@
     <module>shutdown-impl</module>
     <module>netconf-config-dispatcher</module>
     <module>config-module-archetype</module>
+    <module>config-netty-config</module>
   </modules>
 
   <dependencies>
             </execution>
           </executions>
         </plugin>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-surefire-plugin</artifactId>
-          <configuration>
-            <redirectTestOutputToFile>true</redirectTestOutputToFile>
-            <parallel>classes</parallel>
-            <forkCount>1C</forkCount>
-            <reuseForks>false</reuseForks>
-            <perCoreThreadCount>true</perCoreThreadCount>
-            <threadCount>2</threadCount>
-          </configuration>
-        </plugin>
         <plugin>
           <groupId>org.codehaus.groovy.maven</groupId>
           <artifactId>gmaven-plugin</artifactId>
index c91881bd3e639e48424dd9e8d02ee4f7201b970e..f9e0c7036a858b60246a7956a8bdc6fc7ba18d44 100644 (file)
       <scope>test</scope>
     </dependency>
   </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-        </configuration>
-        <executions>
-          <execution>
-            <id>default-test</id>
-            <configuration>
-              <skip>true</skip>
-            </configuration>
-          </execution>
-          <execution>
-            <id>integration-tests</id>
-            <goals>
-              <goal>test</goal>
-            </goals>
-            <phase>integration-test</phase>
-            <configuration>
-              <includes>
-                <include>**/org/opendaylight/controller/config/yangjmxgenerator/it/*.java</include>
-              </includes>
-              <skip>false</skip>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
 </project>
index b570302563b9d9c4e00a4171614beb28df578cd8..e80ebc67a566197294ac64e2c431dd07c5131b3c 100644 (file)
@@ -7,7 +7,22 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.openmbean.SimpleType;
+
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
@@ -18,20 +33,6 @@ import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 
-import javax.management.openmbean.SimpleType;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static org.hamcrest.CoreMatchers.is;
-
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.doReturn;
-
 public class RuntimeBeanEntryTest extends AbstractYangTest {
 
     public static final String PACKAGE_NAME = "packages.sis";
@@ -54,10 +55,10 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
         Map<String, RuntimeBeanEntry> runtimeBeans = RuntimeBeanEntry
                 .extractClassNameToRuntimeBeanMap(PACKAGE_NAME, caseNode, "test-name", new TypeProviderWrapper(new
                         TypeProviderImpl(context)), "test", jmxImplModule);
-        assertThat(runtimeBeans.size(), is(1));
+        assertEquals(1, runtimeBeans.size());
         RuntimeBeanEntry runtimeMXBean = runtimeBeans.get("testRuntimeMXBean");
-        assertThat(runtimeMXBean.isRoot(), is(true));
-        assertThat(runtimeMXBean.getYangName(), is("test-name"));
+        assertTrue(runtimeMXBean.isRoot());
+        assertEquals("test-name", runtimeMXBean.getYangName());
     }
 
     @Test
@@ -72,7 +73,7 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
                 threadsJavaModule, modulesToSIEs, context,
                 new TypeProviderWrapper(new TypeProviderImpl(context)),
                 PACKAGE_NAME);
-        assertThat(namesToMBEs.isEmpty(), is(false));
+        assertFalse(namesToMBEs.isEmpty());
 
         // get threadfactory-naming bean
         ModuleMXBeanEntry threadfactoryNamingMXBean = namesToMBEs
@@ -82,13 +83,13 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
         // get runtime beans
         Collection<RuntimeBeanEntry> runtimeBeanEntries = threadfactoryNamingMXBean
                 .getRuntimeBeans();
-        assertThat(runtimeBeanEntries.isEmpty(), is(false));
+        assertFalse(runtimeBeanEntries.isEmpty());
 
         // get root runtime bean
         RuntimeBeanEntry threadfactoryRuntimeBeanEntry = getRuntimeBeanEntryByJavaName(
                 runtimeBeanEntries, "NamingThreadFactoryRuntimeMXBean");
         assertNotNull(threadfactoryRuntimeBeanEntry);
-        assertThat(threadfactoryRuntimeBeanEntry.isRoot(), is(true));
+        assertTrue(threadfactoryRuntimeBeanEntry.isRoot());
 
         // get thread runtime bean
         RuntimeBeanEntry runtimeBeanEntry = getRuntimeBeanEntryByJavaName(
@@ -96,43 +97,41 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
         assertNotNull(runtimeBeanEntry);
 
         // test thread runtime bean properties
-        assertThat(runtimeBeanEntry.getJavaNamePrefix(),
-                is(THREAD_RUNTIME_BEAN_JAVA_PREFIX));
-        assertThat(runtimeBeanEntry.getPackageName(), is(PACKAGE_NAME));
-        assertThat(runtimeBeanEntry.getFullyQualifiedName(runtimeBeanEntry
-                .getJavaNameOfRuntimeMXBean()), is(PACKAGE_NAME + "."
-                + THREAD_RUNTIME_BEAN_JAVA_NAME));
-        assertThat(runtimeBeanEntry.getYangName(),
-                is(THREAD_RUNTIME_BEAN_YANG_NAME));
+        assertEquals(THREAD_RUNTIME_BEAN_JAVA_PREFIX, runtimeBeanEntry.getJavaNamePrefix());
+        assertEquals(PACKAGE_NAME, runtimeBeanEntry.getPackageName());
+        assertEquals(PACKAGE_NAME + "." + THREAD_RUNTIME_BEAN_JAVA_NAME,
+            runtimeBeanEntry.getFullyQualifiedName(runtimeBeanEntry
+                .getJavaNameOfRuntimeMXBean()));
+        assertEquals(THREAD_RUNTIME_BEAN_YANG_NAME, runtimeBeanEntry.getYangName());
 
         // get thread runtime bean rpcs
         List<RuntimeBeanEntry.Rpc> rpcs = new ArrayList<RuntimeBeanEntry.Rpc>(
                 runtimeBeanEntry.getRpcs());
-        assertThat(rpcs.size(), is(2));
+        assertEquals(2, rpcs.size());
 
         // get sleep rpc and test it
         RuntimeBeanEntry.Rpc rpc = getRpcByName(rpcs, SLEEP_RPC_NAME);
         assertNotNull(rpc);
-        assertThat(rpc.getYangName(), is(SLEEP_RPC_NAME));
+        assertEquals(SLEEP_RPC_NAME, rpc.getYangName());
 
-        assertThat(((JavaAttribute)rpc.getReturnType()).getType().getFullyQualifiedName().endsWith(SLEEP_RPC_OUTPUT),  is(true));
+        assertTrue(((JavaAttribute)rpc.getReturnType()).getType().getFullyQualifiedName().endsWith(SLEEP_RPC_OUTPUT));
 
         // get sleep rpc input attribute and test it
         List<JavaAttribute> attributes = rpc.getParameters();
-        assertThat(attributes.size(), is(1));
+        assertEquals(1, attributes.size());
         JavaAttribute attribute = attributes.get(0);
-        assertThat(attribute.getAttributeYangName(), is(SLEEP_RPC_INPUT_NAME));
-        assertThat(attribute.getType().getName(), is(SLEEP_RPC_INPUT_TYPE));
-        assertThat(attribute.getLowerCaseCammelCase(), is(SLEEP_RPC_INPUT_NAME));
-        assertThat(attribute.getUpperCaseCammelCase(), is("Millis"));
+        assertEquals(SLEEP_RPC_INPUT_NAME, attribute.getAttributeYangName());
+        assertEquals(SLEEP_RPC_INPUT_TYPE, attribute.getType().getName());
+        assertEquals(SLEEP_RPC_INPUT_NAME, attribute.getLowerCaseCammelCase());
+        assertEquals("Millis", attribute.getUpperCaseCammelCase());
         assertNull(attribute.getNullableDefault());
         assertNull(attribute.getNullableDescription());
-        assertThat(attribute.getOpenType(), is(SimpleType.class));
+        assertTrue(attribute.getOpenType() instanceof SimpleType);
     }
 
     private RuntimeBeanEntry getRuntimeBeanEntryByJavaName(
             final Collection<RuntimeBeanEntry> runtimeBeanEntries,
-            String javaName) {
+            final String javaName) {
         if (runtimeBeanEntries != null && !runtimeBeanEntries.isEmpty()) {
             for (RuntimeBeanEntry runtimeBeanEntry : runtimeBeanEntries) {
                 if (runtimeBeanEntry.getJavaNameOfRuntimeMXBean().equals(
@@ -145,7 +144,7 @@ public class RuntimeBeanEntryTest extends AbstractYangTest {
     }
 
     private RuntimeBeanEntry.Rpc getRpcByName(
-            final List<RuntimeBeanEntry.Rpc> rpcs, String name) {
+            final List<RuntimeBeanEntry.Rpc> rpcs, final String name) {
         if (rpcs != null && !rpcs.isEmpty()) {
             for (RuntimeBeanEntry.Rpc rpc : rpcs) {
                 if (rpc.getName().equals(name)) {
index 977fab1334ae48791f9901aedbc1420eabb1e2e7..5effbb09fc81536ed2cf176427c37f25d16e9ddf 100644 (file)
@@ -64,7 +64,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-netty-features</artifactId>
-      <version>${config.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -74,7 +73,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-adsal</artifactId>
-      <version>${sal.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
@@ -92,7 +90,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>mdsal-features</artifactId>
-      <version>${mdsal.version}</version>
       <classifier>features</classifier>
       <type>xml</type>
       <scope>runtime</scope>
index 541c1300f35da009dc0ca2aa4434fe3e51b3dee9..7ab56e6d03d63071216189c716f3022b6e834967 100644 (file)
             <phase>generate-resources</phase>
             <configuration>
                <outputDirectory>${project.build.directory}/configuration</outputDirectory>
-               <includeArtifactIds>sal-rest-connector-config</includeArtifactIds>
-               <includes>**\/*.xml</includes>
+               <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config,sal-clustering-config</includeArtifactIds>
+               <includes>**\/*.xml,**/*.conf</includes>
                <excludeTransitive>true</excludeTransitive>
                <ignorePermissions>false</ignorePermissions>
             </configuration>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-rest-connector-config</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>config-netty-config</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>md-sal-config</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-config</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-connector-config</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller.samples</groupId>
+          <artifactId>toaster-config</artifactId>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-rest-docgen</artifactId>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-restconf-broker</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-remoterpc-connector</artifactId>
+        </dependency>
+
 
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>yang-parser-impl</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>yang-data-composite-node</artifactId>
+        </dependency>
         <!-- yang model dependencies -->
         <dependency>
           <groupId>org.opendaylight.yangtools.model</groupId>
           <artifactId>jeromq</artifactId>
           <version>0.3.1</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-distributed-datastore</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-clustering-config</artifactId>
+        </dependency>
       </dependencies>
     </profile>
     <profile>
                 <phase>generate-resources</phase>
                 <configuration>
                    <outputDirectory>${project.build.directory}/configuration</outputDirectory>
-                   <includeArtifactIds>sal-rest-connector-config</includeArtifactIds>
+                   <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config</includeArtifactIds>
                    <includes>**\/*.xml</includes>
                    <excludeTransitive>true</excludeTransitive>
                    <ignorePermissions>false</ignorePermissions>
diff --git a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IHostTrackerShell.java b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IHostTrackerShell.java
new file mode 100644 (file)
index 0000000..5d11be4
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.hosttracker;
+
+import java.util.List;
+
+public interface IHostTrackerShell{
+
+    public List<String> dumpPendingArpReqList();
+    public List<String> dumpFailedArpReqList();
+}
\ No newline at end of file
index 825b2453aac1cb18cb4af3527f19331dd718048d..7e527712b1058b756ad743896f94a5447b65a61b 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Set;
 import org.apache.felix.dm.Component;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.hosttracker.IHostTrackerShell;
 import org.opendaylight.controller.hosttracker.IfHostListener;
 import org.opendaylight.controller.hosttracker.IfIptoHost;
 import org.opendaylight.controller.hosttracker.IfNewHostNotify;
@@ -78,6 +79,7 @@ public class Activator extends ComponentActivatorAbstractBase {
                             IInventoryListener.class.getName(),
                             IfIptoHost.class.getName(),
                             IfHostListener.class.getName(),
+                            IHostTrackerShell.class.getName(),
                             ITopologyManagerAware.class.getName(),
                             ICacheUpdateAware.class.getName() }, props);
 
index ce49b599e18f90833f1850bc23bfb74b457aabaf..f728b35bbfa7f492c3937b87616e4b655ba3f16f 100644 (file)
@@ -39,6 +39,7 @@ import org.opendaylight.controller.clustering.services.IClusterContainerServices
 import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.hosttracker.HostIdFactory;
 import org.opendaylight.controller.hosttracker.IHostId;
+import org.opendaylight.controller.hosttracker.IHostTrackerShell;
 import org.opendaylight.controller.hosttracker.IPHostId;
 import org.opendaylight.controller.hosttracker.IPMacHostId;
 import org.opendaylight.controller.hosttracker.IfHostListener;
@@ -100,7 +101,7 @@ import org.slf4j.LoggerFactory;
  *
  */
 
-public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAware, IInventoryListener,
+public class HostTracker implements IfIptoHost, IfHostListener, IHostTrackerShell, ISwitchManagerAware, IInventoryListener,
         ITopologyManagerAware, ICacheUpdateAware<IHostId, HostNodeConnector>, CommandProvider {
     static final String ACTIVE_HOST_CACHE = "hosttracker.ActiveHosts";
     static final String INACTIVE_HOST_CACHE = "hosttracker.InactiveHosts";
@@ -1618,4 +1619,24 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
         IHostId id = HostIdFactory.create(addr, null);
         return getHostNetworkHierarchy(id);
     }
+
+    @Override
+    public List<String> dumpPendingArpReqList() {
+        ARPPending arphost;
+        List<String> arpReq = new ArrayList<String>();
+        for (Entry<IHostId, ARPPending> entry : ARPPendingList.entrySet()) {
+            arpReq.add(entry.getValue().getHostId().toString());
+        }
+        return arpReq;
+    }
+
+    @Override
+    public List<String> dumpFailedArpReqList() {
+        ARPPending arphost;
+        List<String> arpReq = new ArrayList<String>();
+        for (Entry<IHostId, ARPPending> entry : failedARPReqList.entrySet()) {
+            arpReq.add(entry.getValue().getHostId().toString());
+        }
+        return arpReq;
+    }
 }
diff --git a/opendaylight/hosttracker/shell/pom.xml b/opendaylight/hosttracker/shell/pom.xml
new file mode 100644 (file)
index 0000000..3f73303
--- /dev/null
@@ -0,0 +1,52 @@
+<?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>hosttracker.shell</artifactId>
+  <version>${hosttracker.shell.version}</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.shell</groupId>
+      <artifactId>org.apache.karaf.shell.console</artifactId>
+      <version>3.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.implementation</artifactId>
+      <version>${hosttracker.implementation.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
+        <configuration>
+          <instructions>
+            <Import-Package>org.apache.felix.service.command,
+              org.apache.karaf.shell.commands,
+              org.apache.karaf.shell.console,
+              *</Import-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/opendaylight/hosttracker/shell/src/main/java/org/opendaylight/controller/hosttracker/shell/DumpFailedARPReqList.java b/opendaylight/hosttracker/shell/src/main/java/org/opendaylight/controller/hosttracker/shell/DumpFailedARPReqList.java
new file mode 100644 (file)
index 0000000..ec9971f
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.controller.hosttracker.shell;
+/**
+* Copyright (c) 2014 Inocybe Technologies, and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.hosttracker.IHostTrackerShell;
+
+@Command(scope = "hosttracker", name = "dumpFailedARPReqList", description="Display the dump failed ARPReqList")
+public class DumpFailedARPReqList extends OsgiCommandSupport{
+
+    private IHostTrackerShell hostTracker;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        System.out.print(hostTracker.dumpFailedArpReqList());
+        return null;
+    }
+
+    public void setHostTracker(IHostTrackerShell hostTracker){
+        this.hostTracker = hostTracker;
+    }
+}
diff --git a/opendaylight/hosttracker/shell/src/main/java/org/opendaylight/controller/hosttracker/shell/DumpPendingARPReqList.java b/opendaylight/hosttracker/shell/src/main/java/org/opendaylight/controller/hosttracker/shell/DumpPendingARPReqList.java
new file mode 100644 (file)
index 0000000..7f52a55
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.controller.hosttracker.shell;
+/**
+* Copyright (c) 2014 Inocybe Technologies, and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.hosttracker.IHostTrackerShell;
+
+@Command(scope = "hosttracker", name = "dumpPendingARPReqList", description="Display the dump pending ARPReqList")
+public class DumpPendingARPReqList extends OsgiCommandSupport{
+
+    private IHostTrackerShell hostTracker;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        System.out.print(hostTracker.dumpPendingArpReqList());
+        return null;
+    }
+
+    public void setHostTracker(IHostTrackerShell hostTracker){
+        this.hostTracker = hostTracker;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/hosttracker/shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/opendaylight/hosttracker/shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644 (file)
index 0000000..ba79b5d
--- /dev/null
@@ -0,0 +1,17 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+    <reference id="HostTrackerRef" interface="org.opendaylight.controller.hosttracker.IHostTrackerShell"/>
+
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+
+    <command>
+       <action class="org.opendaylight.controller.hosttracker.shell.DumpFailedARPReqList">
+          <property name="hostTracker" ref="HostTrackerRef"/>
+       </action>
+    </command>
+    <command>
+       <action class="org.opendaylight.controller.hosttracker.shell.DumpPendingARPReqList">
+          <property name="hostTracker" ref="HostTrackerRef"/>
+       </action>
+    </command>
+    </command-bundle>
+</blueprint>
diff --git a/opendaylight/hosttracker/shell/src/test/java/org/opendaylight/controller/hosttracker/shell/HostTrackerShellTest.java b/opendaylight/hosttracker/shell/src/test/java/org/opendaylight/controller/hosttracker/shell/HostTrackerShellTest.java
new file mode 100644 (file)
index 0000000..a0a5a2e
--- /dev/null
@@ -0,0 +1,47 @@
+package org.opendaylight.controller.hosttracker.shell;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.opendaylight.controller.hosttracker.IHostTrackerShell;
+
+public class HostTrackerShellTest {
+
+    private final long COMMAND_TIMEOUT = 1000;
+    private IHostTrackerShell hostTracker;
+
+    @Test
+    public void testDumpPendingARPReqList() throws Exception {
+        DumpPendingARPReqList dumpPendTest = new DumpPendingARPReqList();
+        hostTracker = mock(IHostTrackerShell.class);
+        List<String> failedList = new ArrayList<String>(Arrays.asList("a", "b", "c"));
+        when(hostTracker.dumpPendingArpReqList()).thenReturn(failedList);
+        dumpPendTest.setHostTracker(hostTracker);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(baos));
+        dumpPendTest.doExecute();
+        //Assert.assertTrue(true);
+        Assert.assertEquals("[a, b, c]", baos.toString());
+    }
+
+    @Test
+    public void testDumpFailedARPReqList() throws Exception {
+        DumpFailedARPReqList dumpFailTest = new DumpFailedARPReqList();
+        hostTracker = mock(IHostTrackerShell.class);
+        List<String> failedList = new ArrayList<String>(Arrays.asList("a", "b", "c"));
+        when(hostTracker.dumpFailedArpReqList()).thenReturn(failedList);
+        dumpFailTest.setHostTracker(hostTracker);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(baos));
+        dumpFailTest.doExecute();
+        //Assert.assertTrue(true);
+        Assert.assertEquals("[a, b, c]", baos.toString());
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml b/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml
deleted file mode 100644 (file)
index 7770c15..0000000
+++ /dev/null
@@ -1,74 +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>compatibility-parent</artifactId>
-    <version>1.1-SNAPSHOT</version>
-  </parent>
-  <artifactId>flow-management-compatibility</artifactId>
-  <packaging>bundle</packaging>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>forwardingrulesmanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-compatibility</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-all</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Name>Forwarding Rules Manager Adapter for MD-SAL</Bundle-Name>
-          </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>
-    <tag>HEAD</tag>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-  </scm>
-</project>
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java
deleted file mode 100644 (file)
index 411af28..0000000
+++ /dev/null
@@ -1,62 +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.frm.compatibility;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ConfigurationReader implements FlowManagementReader {
-
-    private final static Logger LOG = LoggerFactory.getLogger(ConfigurationReader.class);
-
-    private IForwardingRulesManager manager;
-
-    @Override
-    public Flows readAllFlows() {
-        List<FlowConfig> staticFlows = this.manager.getStaticFlows();
-        List<Flow> flowMap = new ArrayList<Flow>(staticFlows.size());
-
-        for (FlowConfig conf : staticFlows) {
-            flowMap.add(FlowConfigMapping.toConfigurationFlow(conf));
-        }
-        final FlowsBuilder flowsBuilder = new FlowsBuilder();
-        return (flowsBuilder.setFlow(flowMap)).build();
-    }
-
-    @Override
-    public Flow readFlow(final FlowKey key) {
-        try {
-            final FlowConfig flowConf =
-                    this.manager.getStaticFlow(String.valueOf(key.getId()), NodeMapping.toADNode(key.getNode()));
-            return FlowConfigMapping.toConfigurationFlow(flowConf);
-        } catch (Exception e) {
-            String errMsg = MessageFormat.format("readFlow by key {} fail", key);
-            LOG.error(errMsg, e);
-            throw new RuntimeException(errMsg, e);
-        }
-    }
-
-    public IForwardingRulesManager getManager() {
-        return this.manager;
-    }
-
-    public void setManager(final IForwardingRulesManager manager) {
-        this.manager = manager;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java
deleted file mode 100644 (file)
index 0653eeb..0000000
+++ /dev/null
@@ -1,119 +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.frm.compatibility;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.common.util.Arguments;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject> {
-
-    private final static InstanceIdentifier<Flows> FLOWS_PATH = InstanceIdentifier.<Flows> builder(Flows.class).toInstance();
-
-    private final FlowManagementReader configuration = new ConfigurationReader();
-    private DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener;
-    private DataProviderService dataService;
-    private IForwardingRulesManager manager;
-
-    public Registration init() {
-        return this.dataService.registerCommitHandler(FRMRuntimeDataProvider.FLOWS_PATH, this);
-    }
-
-    @Override
-    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
-        return this.readFrom(this.configuration, path);
-    }
-
-    @Override
-    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
-        return this.readFrom(this.configuration, path);
-    }
-
-    public DataObject readFrom(final FlowManagementReader store, final InstanceIdentifier<? extends DataObject> path) {
-        if (Objects.equal(FRMRuntimeDataProvider.FLOWS_PATH, path)) {
-            return store.readAllFlows();
-        }
-        if (FRMRuntimeDataProvider.FLOWS_PATH.contains(path)) {
-            return store.readFlow(this.toFlowKey(path));
-        }
-        return null;
-    }
-
-    @Override
-    public FlowCommitTransaction requestCommit(final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-        return new FlowCommitTransaction(this, modification);
-    }
-
-    public FlowKey toFlowKey(final InstanceIdentifier<? extends DataObject> identifier) {
-        Preconditions.<InstanceIdentifier<? extends DataObject>> checkNotNull(identifier);
-
-        Iterable<PathArgument> path = identifier.getPathArguments();
-        PathArgument get = path.iterator().next();
-        final Identifier itemKey = Arguments.<IdentifiableItem> checkInstanceOf(get, IdentifiableItem.class).getKey();
-        return Arguments.<FlowKey> checkInstanceOf(itemKey, FlowKey.class);
-    }
-
-    public RpcResult<Void> finish(final FlowCommitTransaction transaction) {
-        Iterable<FlowConfig> toRemove = transaction.getToRemove();
-        for (final FlowConfig flow : toRemove) {
-            this.manager.removeStaticFlow(flow.getName(), flow.getNode());
-        }
-        Iterable<FlowConfig> toUpdate = transaction.getToUpdate();
-        for (final FlowConfig flow : toUpdate) {
-            this.manager.removeStaticFlow(flow.getName(), flow.getNode());
-            this.manager.addStaticFlow(flow);
-        }
-        return RpcResultBuilder.<Void> success().build();
-    }
-
-    public RpcResult<Void> rollback(final FlowCommitTransaction transaction) {
-        return null;
-    }
-
-    public DataProviderService getDataService() {
-        return this.dataService;
-    }
-
-    public void setDataService(final DataProviderService dataService) {
-        this.dataService = dataService;
-    }
-
-    public DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> getChangeListener() {
-        return this.changeListener;
-    }
-
-    public void setChangeListener(final DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener) {
-        this.changeListener = changeListener;
-    }
-
-    public IForwardingRulesManager getManager() {
-        return this.manager;
-    }
-
-    public void setManager(final IForwardingRulesManager manager) {
-        this.manager = manager;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java
deleted file mode 100644 (file)
index bf0050d..0000000
+++ /dev/null
@@ -1,99 +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.frm.compatibility;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public class FlowCommitTransaction implements DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
-
-    private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-    private final HashSet<FlowConfig> toAdd = new HashSet<FlowConfig>();
-    private final FRMRuntimeDataProvider flowManager;
-    private Iterable<FlowConfig> toUpdate;
-    private Iterable<FlowConfig> toRemove;
-
-    public FlowCommitTransaction(
-            final FRMRuntimeDataProvider flowManager,
-            final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-        this.flowManager = flowManager;
-        this.modification = modification;
-        this.processModification();
-    }
-
-    @Override
-    public RpcResult<Void> finish() throws IllegalStateException {
-        return this.flowManager.finish(this);
-    }
-
-    @Override
-    public RpcResult<Void> rollback() throws IllegalStateException {
-        return this.flowManager.rollback(this);
-    }
-
-    public void processModification() {
-        final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updated =
-                this.modification.getUpdatedConfigurationData().entrySet();
-        final List<FlowConfig> forUpdate = new ArrayList<FlowConfig>(updated.size());
-
-        if (updated != null && !(updated.isEmpty())) {
-            for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : updated) {
-                if (FlowConfigMapping.isFlowPath(entry.getKey())) {
-                    forUpdate.add(FlowConfigMapping.toFlowConfig((Flow) entry.getValue()));
-                }
-            }
-        }
-        this.toUpdate = Collections.unmodifiableCollection(forUpdate);
-
-        final Set<InstanceIdentifier<? extends DataObject>> removedConfigurationData =
-                this.modification.getRemovedConfigurationData();
-        final List<FlowConfig> forRemove = new ArrayList<FlowConfig>(removedConfigurationData.size());
-
-        if (removedConfigurationData != null && !(removedConfigurationData.isEmpty())) {
-            for (InstanceIdentifier<? extends DataObject> data : removedConfigurationData) {
-                if (FlowConfigMapping.isFlowPath(data)) {
-                    forRemove.add(FlowConfigMapping.toFlowConfig(data));
-                }
-            }
-        }
-        this.toRemove = Collections.unmodifiableCollection(forRemove);
-    }
-
-    @Override
-    public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
-        return this.modification;
-    }
-
-    public FRMRuntimeDataProvider getFlowManager() {
-        return this.flowManager;
-    }
-
-    public HashSet<FlowConfig> getToAdd() {
-        return this.toAdd;
-    }
-
-    public Iterable<FlowConfig> getToUpdate() {
-        return this.toUpdate;
-    }
-
-    public Iterable<FlowConfig> getToRemove() {
-        return this.toRemove;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java
deleted file mode 100644 (file)
index 58c60ec..0000000
+++ /dev/null
@@ -1,109 +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.frm.compatibility;
-
-import java.text.MessageFormat;
-import java.util.Iterator;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FlowConfigMapping {
-
-    private final static Logger LOG = LoggerFactory.getLogger(FlowConfigMapping.class);
-
-    /* nodes/node/flow  -> 0 / 1 / 2  */
-    private static final int FLOW_KEY_IDENTIFIER_DEEP = 2;
-
-    public static Flow toConfigurationFlow(final FlowConfig sourceCfg) {
-        final FlowAdded source = MDFlowMapping.flowAdded(sourceCfg.getFlow());
-        final FlowBuilder flowBuilder = new FlowBuilder();
-        flowBuilder.setInstructions(source.getInstructions());
-        flowBuilder.setCookie(source.getCookie());
-        flowBuilder.setHardTimeout(source.getHardTimeout());
-        flowBuilder.setIdleTimeout(source.getIdleTimeout());
-        flowBuilder.setMatch(source.getMatch());
-        flowBuilder.setNode(source.getNode());
-
-        FlowKey flowKey =
-                new FlowKey(Long.valueOf(sourceCfg.getName()), flowBuilder.getNode());
-        flowBuilder.setKey(flowKey);
-        return flowBuilder.build();
-    }
-
-    public static FlowConfig toFlowConfig(final Flow sourceCfg) {
-        try {
-            final FlowConfig flowConfig = new FlowConfig();
-            flowConfig.setName(String.valueOf(sourceCfg.getId()));
-            flowConfig.setNode(NodeMapping.toADNode(sourceCfg.getNode()));
-            return flowConfig;
-        } catch (Exception e) {
-            String errMsg = MessageFormat.format("Convert from Flow {} to FlowConfig fail", sourceCfg);
-            LOG.error(errMsg, e);
-            throw new RuntimeException(errMsg, e);
-        }
-    }
-
-    public static FlowConfig toFlowConfig(final InstanceIdentifier<? extends Object> identifier) {
-        try {
-            PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(identifier);
-            if (pathArg != null) {
-                final FlowConfig flowConfig = new FlowConfig();
-                FlowKey key = ((IdentifiableItem<Flow, FlowKey>) pathArg).getKey();
-                flowConfig.setName(String.valueOf(key.getId()));
-                flowConfig.setNode(NodeMapping.toADNode(key.getNode()));
-                return flowConfig;
-            }
-            return null;
-        } catch (Exception e) {
-            String errMsg = MessageFormat.format("Convert from InstanceIdentifier {} to FlowConfig fail", identifier);
-            LOG.error(errMsg, e);
-            throw new RuntimeException(errMsg, e);
-        }
-    }
-
-    public static boolean isFlowPath(final InstanceIdentifier<? extends Object> path) {
-        PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(path);
-        if (pathArg == null) {
-            return false;
-        }
-        if (pathArg instanceof IdentifiableItem<?,?>) {
-            final Identifiable<?> key = ((IdentifiableItem<?, ? extends Identifiable<?>>) pathArg).getKey();
-            if ((key instanceof FlowKey)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static PathArgument getSecondPathArgumentFromPath(final InstanceIdentifier<? extends Object> path) {
-        if (path != null && path.getPathArguments() != null) {
-            Iterator<PathArgument> iterator = path.getPathArguments().iterator();
-            int deep = 0;
-            while (iterator.hasNext()) {
-                PathArgument pathArg = iterator.next();
-                if (deep == FlowConfigMapping.FLOW_KEY_IDENTIFIER_DEEP) {
-                    return pathArg;
-                }
-                deep++;
-            }
-        }
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java
deleted file mode 100644 (file)
index cb61c8a..0000000
+++ /dev/null
@@ -1,20 +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.frm.compatibility;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-
-public interface FlowManagementReader {
-
-    Flows readAllFlows();
-
-    Flow readFlow(FlowKey key);
-
-}
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java
deleted file mode 100644 (file)
index a91cef6..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.frm.compatibility;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class SampleConsumer {
-
-    ConsumerContext context;
-
-    void addFlowExample() {
-
-        DataBrokerService dataService = context.getSALService(DataBrokerService.class);
-
-        DataModificationTransaction transaction = dataService.beginTransaction();
-        Flow flow = createSampleFlow("foo", null);
-        InstanceIdentifier<Flow> path = InstanceIdentifier.builder(Flows.class).child(Flow.class, flow.getKey())
-                .toInstance();
-        transaction.putConfigurationData(path, flow);
-
-        transaction.commit();
-
-        dataService.readConfigurationData(path);
-    }
-
-    Flow createSampleFlow(String name, NodeRef node) {
-        FlowBuilder ret = new FlowBuilder();
-        FlowKey key = new FlowKey(Long.parseLong(name), node);
-        ret.setKey(key);
-        return ret.build();
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml
deleted file mode 100644 (file)
index 62dc2ff..0000000
+++ /dev/null
@@ -1,90 +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>compatibility-parent</artifactId>
-    <version>1.1-SNAPSHOT</version>
-  </parent>
-  <artifactId>inventory-topology-compatibility</artifactId>
-  <packaging>bundle</packaging>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>forwardingrulesmanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-util</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-compatibility</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>switchmanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>topologymanager</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-topology</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-all</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Name>Forwarding Rules Manager Adapter
-                            for MD-SAL</Bundle-Name>
-          </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>
-    <tag>HEAD</tag>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-  </scm>
-</project>
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.java
deleted file mode 100644 (file)
index b37b501..0000000
+++ /dev/null
@@ -1,97 +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.compatibility.inventory;
-
-import java.util.ArrayList;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.compatibility.InventoryMapping;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class InventoryReader implements RuntimeDataProvider {
-    private static final Logger LOG = LoggerFactory.getLogger(InventoryReader.class);
-    private ISwitchManager switchManager;
-
-    public ISwitchManager getSwitchManager() {
-        return switchManager;
-    }
-
-    public void setSwitchManager(final ISwitchManager switchManager) {
-        this.switchManager = switchManager;
-    }
-
-    @Override
-    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
-        // Topology and Inventory are operational only
-        return null;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
-        final Class<? extends DataObject> type = path.getTargetType();
-        if (Nodes.class.equals(type)) {
-            return readNodes(((InstanceIdentifier<Nodes>) path));
-        }
-        if (Node.class.equals(type)) {
-            return readNode(((InstanceIdentifier<Node>) path));
-        }
-        if (NodeConnector.class.equals(type)) {
-            return readNodeConnector(((InstanceIdentifier<NodeConnector>) path));
-        }
-
-        LOG.debug("Unsupported type {}", type);
-        return null;
-    }
-
-    private NodeConnector readNodeConnector(final InstanceIdentifier<NodeConnector> identifier) {
-        return constructNodeConnector(InventoryMapping.toAdNodeConnector(identifier));
-    }
-
-    private Node readNode(final InstanceIdentifier<Node> identifier) {
-        return constructNode(InventoryMapping.toAdNode(identifier));
-    }
-
-    private Node constructNode(final org.opendaylight.controller.sal.core.Node node) {
-        final Set<org.opendaylight.controller.sal.core.NodeConnector> connectors = getSwitchManager().getNodeConnectors(node);
-        final ArrayList<NodeConnector> tpList = new ArrayList<NodeConnector>(connectors.size());
-        for (final org.opendaylight.controller.sal.core.NodeConnector connector : connectors) {
-            tpList.add(constructNodeConnector(connector));
-        }
-
-        return new NodeBuilder()
-        .setKey(InventoryMapping.toNodeKey(node))
-        .setNodeConnector(tpList)
-        .build();
-    }
-
-    private Nodes readNodes(final InstanceIdentifier<Nodes> identifier) {
-        final Set<org.opendaylight.controller.sal.core.Node> nodes = getSwitchManager().getNodes();
-        final ArrayList<Node> nodeList = new ArrayList<Node>(nodes.size());
-        for (final org.opendaylight.controller.sal.core.Node node : nodes) {
-            nodeList.add(constructNode(node));
-        }
-
-        return new NodesBuilder().setNode(nodeList).build();
-    }
-
-    private static NodeConnector constructNodeConnector(final org.opendaylight.controller.sal.core.NodeConnector connector) {
-        return new NodeConnectorBuilder().setKey(InventoryMapping.toNodeConnectorKey(connector)).build();
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.java
deleted file mode 100644 (file)
index 82c5b7b..0000000
+++ /dev/null
@@ -1,347 +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.compatibility.switchmanager;
-
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.controller.sal.core.Bandwidth;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Description;
-import org.opendaylight.controller.sal.core.ForwardingMode;
-import org.opendaylight.controller.sal.core.MacAddress;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.Tier;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.Subnet;
-import org.opendaylight.controller.switchmanager.Switch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-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.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-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.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class CompatibleSwitchManager extends ConfigurableSwitchManager implements ISwitchManager {
-    private static final  Logger LOG = LoggerFactory.getLogger(CompatibleSwitchManager.class);
-
-    private DataBrokerService _dataService;
-
-    public DataBrokerService getDataService() {
-        return this._dataService;
-    }
-
-    public void setDataService(final DataBrokerService dataService) {
-        this._dataService = dataService;
-    }
-
-    @Override
-    public Status addNodeConnectorProp(final NodeConnector nodeConnector, final Property prop) {
-        final DataModificationTransaction it = getDataService().beginTransaction();
-        final NodeConnectorRef path = NodeMapping.toNodeConnectorRef(nodeConnector);
-        return null;
-    }
-
-    @Override
-    public Property createProperty(final String propName, final String propValue) {
-        try {
-            if (propName.equalsIgnoreCase(Description.propertyName)) {
-                return new Description(propValue);
-            } else if (propName.equalsIgnoreCase(Tier.TierPropName)) {
-                return new Tier(Integer.parseInt(propValue));
-            } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
-                return new Bandwidth(Long.parseLong(propValue));
-            } else if (propName.equalsIgnoreCase(ForwardingMode.name)) {
-                return new ForwardingMode(Integer.parseInt(propValue));
-            } else if (propName.equalsIgnoreCase(MacAddress.name)) {
-                return new MacAddress(propValue);
-            } else {
-                LOG.debug("Not able to create {} property", propName);
-            }
-        } catch (Exception e) {
-            LOG.debug("createProperty caught exception {}", e.getMessage());
-        }
-
-        return null;
-    }
-
-    @Override
-    public boolean doesNodeConnectorExist(final NodeConnector nc) {
-        return (getDataService().readOperationalData(NodeMapping.toNodeConnectorRef(nc).getValue()) != null);
-    }
-
-    @Override
-    public byte[] getControllerMAC() {
-        final Enumeration<NetworkInterface> nis;
-        try {
-            nis = NetworkInterface.getNetworkInterfaces();
-        } catch (SocketException e) {
-            LOG.error("Failed to acquire list of interfaces, cannot determine controller MAC", e);
-            return null;
-        }
-
-        while (nis.hasMoreElements()) {
-            final NetworkInterface ni = nis.nextElement();
-            try {
-                return ni.getHardwareAddress();
-            } catch (SocketException e) {
-                LOG.error("Failed to acquire controller MAC from interface {}", ni, e);
-            }
-        }
-
-        // This happens when running controller on windows VM, for example
-        // Try parsing the OS command output
-        LOG.warn("Failed to acquire controller MAC: No physical interface found");
-        return null;
-    }
-
-    @Override
-    public Map<String,Property> getControllerProperties() {
-        return Collections.<String, Property>emptyMap();
-    }
-
-    @Override
-    public Property getControllerProperty(final String propertyName) {
-        return null;
-    }
-
-    @Override
-    public List<Switch> getNetworkDevices() {
-        final InstanceIdentifier<Nodes> path = InstanceIdentifier.builder(Nodes.class).toInstance();
-        final Nodes data = ((Nodes) getDataService().readOperationalData(path));
-        final ArrayList<Switch> ret = new ArrayList<>();
-        for (final Node node : data.getNode()) {
-            try {
-                ret.add(toSwitch(node));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create switch {}", node), e);
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public NodeConnector getNodeConnector(final org.opendaylight.controller.sal.core.Node node, final String nodeConnectorName) {
-        final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(nodeConnectorName));
-        try {
-            return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, node);
-        } catch (ConstructionException e) {
-            throw new IllegalStateException(String.format("Failed to create node connector for {} {}", node, nodeConnectorName), e);
-        }
-    }
-
-    @Override
-    public Property getNodeConnectorProp(final NodeConnector nodeConnector, final String propName) {
-        return getNodeConnectorProps(nodeConnector).get(propName);
-    }
-
-    @Override
-    public Map<String,Property> getNodeConnectorProps(final NodeConnector nodeConnector) {
-        final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(nodeConnector);
-        return toAdProperties(readNodeConnector(ref.getValue()));
-    }
-
-    @Override
-    public Set<NodeConnector> getNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
-        final Node data = this.readNode(NodeMapping.toNodeRef(node).getValue());
-        final HashSet<NodeConnector> ret = new HashSet<>();
-        for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
-            try {
-                ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create node {} connector", node, nc.getKey()), e);
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public String getNodeDescription(final org.opendaylight.controller.sal.core.Node node) {
-        return ((Description) getNodeProps(node).get(Description.propertyName)).getValue();
-    }
-
-    @Override
-    public byte[] getNodeMAC(final org.opendaylight.controller.sal.core.Node node) {
-        return ((MacAddress) getNodeProps(node).get(MacAddress.name)).getMacAddress();
-    }
-
-    @Override
-    public Property getNodeProp(final org.opendaylight.controller.sal.core.Node node, final String propName) {
-        return getNodeProps(node).get(propName);
-    }
-
-    @Override
-    public Map<String,Property> getNodeProps(final org.opendaylight.controller.sal.core.Node node) {
-        final NodeRef ref = NodeMapping.toNodeRef(node);
-        return toAdProperties(((Node) getDataService().readOperationalData(ref.getValue())));
-    }
-
-    @Override
-    public Set<org.opendaylight.controller.sal.core.Node> getNodes() {
-        final InstanceIdentifier<Nodes> path = InstanceIdentifier.builder(Nodes.class).toInstance();
-        final Nodes data = ((Nodes) getDataService().readOperationalData(path));
-        final HashSet<org.opendaylight.controller.sal.core.Node> ret = new HashSet<>();
-        for (final Node node : data.getNode()) {
-            try {
-                ret.add(new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, node.getKey()));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create node for {}", node), e);
-            }
-        }
-        return ret;
-    }
-
-    private static Switch toSwitch(final Node node) throws ConstructionException {
-        return new Switch(new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, node.getKey()));
-    }
-
-    @Override
-    public Set<NodeConnector> getPhysicalNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
-        final NodeRef ref = NodeMapping.toNodeRef(node);
-        final Node data = readNode(ref.getValue());
-        final HashSet<NodeConnector> ret = new HashSet<>();
-        for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
-            final FlowCapableNodeConnector flowConnector = nc.getAugmentation(FlowCapableNodeConnector.class);
-            try {
-                ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create connector for {} on node {}", nc.getKey(), node), e);
-            }
-        }
-        return ret;
-    }
-
-    private static Map<String,Property> toAdProperties(final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector connector) {
-        return Collections.emptyMap();
-    }
-
-    private static Map<String,Property> toAdProperties(final Node connector) {
-        return Collections.emptyMap();
-    }
-
-    private Node readNode(final InstanceIdentifier<? extends Object> ref) {
-        return (Node) getDataService().readOperationalData((ref));
-    }
-
-    private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector readNodeConnector(final InstanceIdentifier<? extends Object> ref) {
-        return ((org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector) getDataService().readOperationalData(ref));
-    }
-
-    @Override
-    public List<NodeConnector> getSpanPorts(final org.opendaylight.controller.sal.core.Node node) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Subnet getSubnetByNetworkAddress(final InetAddress networkAddress) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Set<NodeConnector> getUpNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
-        final Node data = readNode(NodeMapping.toNodeRef(node).getValue());
-        final HashSet<NodeConnector> ret = new HashSet<>();
-        for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
-            final FlowCapableNodeConnector flowConn = nc.<FlowCapableNodeConnector>getAugmentation(FlowCapableNodeConnector.class);
-            if (flowConn != null && flowConn.getState() != null && !flowConn.getState().isLinkDown()) {
-                try {
-                    ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
-                } catch (ConstructionException e) {
-                    throw new IllegalStateException(String.format("Failed to create node connector for node {} connector {}", node, nc), e);
-                }
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public Boolean isNodeConnectorEnabled(final NodeConnector nodeConnector) {
-        final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(nodeConnector);
-        final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector data = readNodeConnector(ref.getValue());
-        return true;
-    }
-
-    @Override
-    public boolean isSpecial(final NodeConnector p) {
-        final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(p);
-        final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector data = readNodeConnector(ref.getValue());
-        return true;
-    }
-
-    @Override
-    public Status removeControllerProperty(final String propertyName) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeAllProps(final org.opendaylight.controller.sal.core.Node node) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeConnectorAllProps(final NodeConnector nodeConnector) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeConnectorProp(final NodeConnector nc, final String propName) {
-        return null;
-    }
-
-    @Override
-    public Status removeNodeProp(final org.opendaylight.controller.sal.core.Node node, final String propName) {
-        return null;
-    }
-
-    @Override
-    public Status removePortsFromSubnet(final String name, final List<String> nodeConnectors) {
-        return null;
-    }
-
-    @Override
-    public Status removeSubnet(final String name) {
-        return null;
-    }
-
-    @Override
-    public Status setControllerProperty(final Property property) {
-        return null;
-    }
-
-    @Override
-    public void setNodeProp(final org.opendaylight.controller.sal.core.Node node, final Property prop) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status addPortsToSubnet(final String name, final List<String> nodeConnectors) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Set<Switch> getConfiguredNotConnectedSwitches() {
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.java
deleted file mode 100644 (file)
index 63f682a..0000000
+++ /dev/null
@@ -1,86 +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.compatibility.switchmanager;
-
-import java.util.List;
-
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.SpanConfig;
-import org.opendaylight.controller.switchmanager.SubnetConfig;
-import org.opendaylight.controller.switchmanager.SwitchConfig;
-
-/**
- * These methods should be backed by config subsystem.
- */
-public abstract class ConfigurableSwitchManager implements ISwitchManager {
-    @Override
-    public Status saveSwitchConfig() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status removeSpanConfig(final SpanConfig cfgObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status addSubnet(final SubnetConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status addSpanConfig(final SpanConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final List<SpanConfig> getSpanConfigList() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final void updateSwitchConfig(final SwitchConfig cfgObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status updateNodeConfig(final SwitchConfig switchConfig) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final SubnetConfig getSubnetConfig(final String subnet) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status removeNodeConfig(final String nodeId) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status removeSubnet(final SubnetConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final List<SubnetConfig> getSubnetsConfigList() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final SwitchConfig getSwitchConfig(final String nodeId) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public Status modifySubnet(final SubnetConfig configObject) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.java
deleted file mode 100644 (file)
index 8e50bd8..0000000
+++ /dev/null
@@ -1,82 +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.compatibility.topology;
-
-import java.util.Iterator;
-
-import org.opendaylight.controller.sal.compatibility.InventoryMapping;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-
-import com.google.common.base.Splitter;
-
-public class TopologyMapping {
-    private static final String HEAD_TAIL_STRING = "::::";
-    private static final Splitter HEAD_TAIL_SPLITTER = Splitter.on(HEAD_TAIL_STRING);
-
-    public TopologyMapping(final TopologyKey path, final InstanceIdentifier<Topology> key) {
-        // No-op for now. Multi-instance will require fixing InventoryMapping first.
-    }
-
-    public Edge toAdTopologyEdge(final InstanceIdentifier<Link> identifier) throws ConstructionException {
-        @SuppressWarnings("unchecked")
-        final LinkKey linkKey = ((KeyedInstanceIdentifier<Link, LinkKey>)identifier).getKey();
-
-        final Iterator<String> it = HEAD_TAIL_SPLITTER.split(linkKey.getLinkId().getValue()).iterator();
-        final NodeConnector tail = InventoryMapping.nodeConnectorFromId(it.next());
-        final NodeConnector head = InventoryMapping.nodeConnectorFromId(it.next());
-        return new Edge(tail, head);
-    }
-
-    public NodeConnector toAdTopologyNodeConnector(final InstanceIdentifier<TerminationPoint> identifier) {
-        @SuppressWarnings("unchecked")
-        final TerminationPointKey tpKey = ((KeyedInstanceIdentifier<TerminationPoint, TerminationPointKey>)identifier).getKey();
-
-        return InventoryMapping.nodeConnectorFromId(tpKey.getTpId().getValue());
-    }
-
-    public org.opendaylight.controller.sal.core.Node toAdTopologyNode(final InstanceIdentifier<Node> identifier) {
-        @SuppressWarnings("unchecked")
-        final NodeKey nodeKey = ((KeyedInstanceIdentifier<Node, NodeKey>)identifier).getKey();
-
-        return InventoryMapping.nodeFromNodeId(nodeKey.getNodeId().getValue());
-    }
-
-    public NodeKey toTopologyNodeKey(final org.opendaylight.controller.sal.core.Node node) {
-        return new NodeKey(new NodeId(InventoryMapping.toNodeId(node)));
-    }
-
-    public TerminationPointKey toTopologyTerminationPointKey(final NodeConnector nc) {
-        return new TerminationPointKey(new TpId(InventoryMapping.toNodeConnectorId(nc)));
-    }
-
-    public LinkKey toTopologyLinkKey(final Edge edge) {
-        final TerminationPointKey sourceTp = toTopologyTerminationPointKey(edge.getTailNodeConnector());
-        final TerminationPointKey destTp = toTopologyTerminationPointKey(edge.getHeadNodeConnector());
-
-        final StringBuilder sb = new StringBuilder();
-        sb.append(sourceTp.getTpId().toString());
-        sb.append(HEAD_TAIL_STRING);
-        sb.append(destTp.getTpId().toString());
-        return new LinkKey(new LinkId(sb.toString()));
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.java
deleted file mode 100644 (file)
index a4ac6f9..0000000
+++ /dev/null
@@ -1,199 +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.compatibility.topology;
-
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TopologyReader implements RuntimeDataProvider {
-    private static final Logger LOG = LoggerFactory.getLogger(TopologyReader.class);
-    private final InstanceIdentifier<Topology> topologyPath;
-    private final TopologyKey topologyKey;
-    private final TopologyMapping mapping;
-    private ITopologyManager topologyManager;
-    private ISwitchManager switchManager;
-
-    public ISwitchManager getSwitchManager() {
-        return this.switchManager;
-    }
-
-    public void setSwitchManager(final ISwitchManager switchManager) {
-        this.switchManager = switchManager;
-    }
-
-    public ITopologyManager getTopologyManager() {
-        return this.topologyManager;
-    }
-
-    public void setTopologyManager(final ITopologyManager topologyManager) {
-        this.topologyManager = topologyManager;
-    }
-
-    public TopologyKey getTopologyKey() {
-        return this.topologyKey;
-    }
-
-    public TopologyMapping getMapping() {
-        return this.mapping;
-    }
-
-    public TopologyReader() {
-        this.topologyKey = new TopologyKey(new TopologyId("compatibility:ad-sal"));
-        this.topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
-                .child(Topology.class, topologyKey)
-                .toInstance();
-        this.mapping = new TopologyMapping(topologyKey, topologyPath);
-    }
-
-    @Override
-    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
-        // Topology and Inventory are operational only
-        return null;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
-        if (!topologyPath.contains(path)) {
-            return null;
-        }
-
-        final Class<? extends DataObject> type = path.getTargetType();
-        if (Link.class.equals(type)) {
-            return readLink((InstanceIdentifier<Link>) path);
-        }
-        if (Node.class.equals(type)) {
-            return readNode((InstanceIdentifier<Node>) path);
-        }
-        if (TerminationPoint.class.equals(type)) {
-            return readTerminationPoint((InstanceIdentifier<TerminationPoint>) path);
-
-        }
-        if (Topology.class.equals(type)) {
-            return readTopology((InstanceIdentifier<Topology>) path);
-        }
-
-        LOG.debug("Unsupported type {}", type);
-        return null;
-    }
-
-    private Link readLink(final InstanceIdentifier<Link> identifier) {
-        final Edge edge;
-        try {
-            edge = this.mapping.toAdTopologyEdge(identifier);
-        } catch (ConstructionException e) {
-            throw new IllegalStateException(String.format("Failed to construct edge for link %s", identifier), e);
-        }
-
-        final Map<Edge,Set<Property>> edges;
-        if (topologyManager != null) {
-            edges = topologyManager.getEdges();
-        } else {
-            edges = null;
-        }
-
-        final Set<Property> properties;
-        if (edges != null) {
-            properties = edges.get(edge);
-        } else {
-            properties = null;
-        }
-
-        return constructLink(edge);
-    }
-
-    private TerminationPoint readTerminationPoint(final InstanceIdentifier<TerminationPoint> identifier) {
-        return constructTerminationPoint(mapping.toAdTopologyNodeConnector(identifier));
-    }
-
-    private Node readNode(final InstanceIdentifier<Node> identifier) {
-        return constructNode(mapping.toAdTopologyNode(identifier));
-    }
-
-    private Topology readTopology(final InstanceIdentifier<Topology> identifier) {
-        final Set<org.opendaylight.controller.sal.core.Node> nodes = getSwitchManager().getNodes();
-        final ArrayList<Node> nodeList = new ArrayList<Node>(nodes.size());
-        for (final org.opendaylight.controller.sal.core.Node node : nodes) {
-            nodeList.add(constructNode(node));
-        }
-
-        final Map<Edge,Set<Property>> edges = getTopologyManager().getEdges();
-        final ArrayList<Link> linkList = new ArrayList<Link>(edges.size());
-        for (final Edge edge : edges.keySet()) {
-            linkList.add(constructLink(edge));
-        }
-
-        return new TopologyBuilder()
-        .setKey(topologyKey)
-        .setNode(nodeList)
-        .setLink(linkList)
-        .build();
-    }
-
-    private Link constructLink(final Edge edge) {
-        final NodeConnector sourceNc = edge.getTailNodeConnector();
-        final NodeConnector destNc = edge.getHeadNodeConnector();
-
-        final LinkBuilder it = new LinkBuilder().setKey(mapping.toTopologyLinkKey(edge));
-
-        it.setSource(new SourceBuilder()
-        .setSourceNode(mapping.toTopologyNodeKey(sourceNc.getNode()).getNodeId())
-        .setSourceTp(mapping.toTopologyTerminationPointKey(sourceNc).getTpId())
-        .build());
-
-        it.setDestination(new DestinationBuilder()
-        .setDestNode(mapping.toTopologyNodeKey(destNc.getNode()).getNodeId())
-        .setDestTp(mapping.toTopologyTerminationPointKey(destNc).getTpId())
-        .build());
-
-        return it.build();
-    }
-
-    private Node constructNode(final org.opendaylight.controller.sal.core.Node node) {
-        final Set<NodeConnector> connectors = getSwitchManager().getNodeConnectors(node);
-        final ArrayList<TerminationPoint> tpList = new ArrayList<TerminationPoint>(connectors.size());
-        for (final NodeConnector connector : connectors) {
-            tpList.add(constructTerminationPoint(connector));
-        }
-
-        return new NodeBuilder()
-        .setKey(mapping.toTopologyNodeKey(node))
-        .setTerminationPoint(tpList)
-        .build();
-    }
-
-    private TerminationPoint constructTerminationPoint(final NodeConnector connector) {
-        return new TerminationPointBuilder().setKey(mapping.toTopologyTerminationPointKey(connector)).build();
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.java
deleted file mode 100644 (file)
index a7a7a9a..0000000
+++ /dev/null
@@ -1,109 +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.compatibility.topologymanager;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-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.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Destination;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Source;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class AdSalTopologyMapping {
-    private final InstanceIdentifier<Topology> topologyPath;
-
-    public AdSalTopologyMapping(final TopologyKey topology) {
-        this.topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
-                .child(Topology.class, topology).toInstance();
-    }
-
-    public InstanceIdentifier<Topology> getTopologyPath() {
-        return topologyPath;
-    }
-
-    public InstanceIdentifier<TerminationPoint> toTerminationPoint(final NodeConnector connector) {
-        return getTopologyPath().builder()
-                .child(Node.class)
-                .child(TerminationPoint.class, toTerminationPointKey(connector))
-                .toInstance();
-    }
-
-    public Map<Edge,Set<Property>> toEdgePropertiesMap(final Iterable<Link> links) {
-        final HashMap<Edge,Set<Property>> ret = new HashMap<>();
-        for (final Link link : links) {
-            try {
-                ret.put(toEdge(link), toProperties(link));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to create edge properties for {}", link), e);
-            }
-        }
-        return ret;
-    }
-
-    public static Set<Edge> toEdges(final Iterable<Link> links) throws ConstructionException {
-        final HashSet<Edge> ret = new HashSet<Edge>();
-        for (final Link link : links) {
-            ret.add(toEdge(link));
-        }
-        return ret;
-    }
-
-    public static Edge toEdge(final Link link) throws ConstructionException {
-        final NodeConnector tail = toNodeConnector(link.getSource());
-        final NodeConnector head = toNodeConnector(link.getDestination());
-        return new Edge(tail, head);
-    }
-
-    public static org.opendaylight.controller.sal.core.Node toAdNode(final Node node) throws ConstructionException {
-        return toAdNode(node.getNodeId());
-    }
-
-    public static org.opendaylight.controller.sal.core.Node toAdNode(final NodeId node) throws ConstructionException {
-        final NodeKey key = new NodeKey(
-                new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(node));
-        return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, key);
-    }
-
-    public static NodeConnector toNodeConnector(final Source ref) throws ConstructionException {
-        final org.opendaylight.controller.sal.core.Node adNode = toAdNode(ref.getSourceNode());
-        final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(ref.getSourceTp()));
-        return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
-    }
-
-    public static NodeConnector toNodeConnector(final Destination ref) throws ConstructionException {
-        final org.opendaylight.controller.sal.core.Node adNode = toAdNode(ref.getDestNode());
-        final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(ref.getDestTp()));
-        return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
-    }
-
-    public TerminationPointKey toTerminationPointKey(final NodeConnector connector) {
-        return null;
-    }
-
-    public Set<Property> toProperties(final Link link) {
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.java
deleted file mode 100644 (file)
index 11320a1..0000000
+++ /dev/null
@@ -1,149 +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.compatibility.topologymanager;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.Host;
-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.utils.Status;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-
-@SuppressWarnings("all")
-public class CompatibleTopologyManager extends ConfigurableLinkManager implements ITopologyManager {
-    private AdSalTopologyMapping topologyMapping;
-    private TypeSafeDataReader dataReader;
-
-    public TypeSafeDataReader getDataReader() {
-        return dataReader;
-    }
-
-    public void setDataReader(final TypeSafeDataReader dataReader) {
-        this.dataReader = dataReader;
-    }
-
-    public AdSalTopologyMapping getTopologyMapping() {
-        return topologyMapping;
-    }
-
-    public void setTopologyMapping(final AdSalTopologyMapping topologyMapping) {
-        this.topologyMapping = topologyMapping;
-    }
-
-    @Override
-    public Map<Edge,Set<Property>> getEdges() {
-        final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
-        return this.topologyMapping.toEdgePropertiesMap(topology.getLink());
-    }
-
-    @Override
-    public Map<org.opendaylight.controller.sal.core.Node, Set<Edge>> getNodeEdges() {
-        final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
-        final HashMap<org.opendaylight.controller.sal.core.Node, Set<Edge>> ret = new HashMap<>();
-        for (final Node node : topology.getNode()) {
-            try {
-                ret.put(topologyMapping.toAdNode(node), topologyMapping.toEdges(
-                        FluentIterable.from(topology.getLink()).filter(new Predicate<Link>() {
-                            @Override
-                            public boolean apply(final Link input) {
-                                final NodeId nodeId = node.getNodeId();
-                                if (nodeId.equals(input.getSource().getSourceNode())) {
-                                    return true;
-                                }
-                                if (nodeId.equals(input.getDestination().getDestNode())) {
-                                    return true;
-                                }
-
-                                return false;
-                            }
-                        })));
-            } catch (ConstructionException e) {
-                throw new IllegalStateException(String.format("Failed to construct node for {}", node), e);
-            }
-        }
-        return ret;
-    }
-
-    /**
-     * Returns true if point is connected to link
-     */
-    private boolean isInternal(final TerminationPoint point) {
-        final Topology topology = getDataReader().readConfigurationData(topologyMapping.getTopologyPath());
-        final TpId tpId = point.getKey().getTpId();
-        return FluentIterable.from(topology.getLink()).anyMatch(new Predicate<Link>() {
-            @Override
-            public boolean apply(final Link input) {
-                if (tpId.equals(input.getSource().getSourceTp())) {
-                    return true;
-                }
-                if (tpId.equals(input.getDestination().getDestTp())) {
-                    return true;
-                }
-                return false;
-            }
-        });
-    }
-
-    @Override
-    public Set<NodeConnector> getNodeConnectorWithHost() {
-        return null;
-    }
-
-    @Override
-    public Host getHostAttachedToNodeConnector(final NodeConnector p) {
-        final InstanceIdentifier<TerminationPoint> tpPath = topologyMapping.toTerminationPoint(p);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public List<Host> getHostsAttachedToNodeConnector(final NodeConnector p) {
-        final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
-        throw new UnsupportedOperationException("Hosts not mapped yet");
-    }
-
-    @Override
-    public Map<org.opendaylight.controller.sal.core.Node, Set<NodeConnector>> getNodesWithNodeConnectorHost() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public boolean isInternal(final NodeConnector p) {
-        final TerminationPoint connector = getDataReader()
-                .readConfigurationData(topologyMapping.toTerminationPoint(p));
-        return this.isInternal(connector);
-    }
-
-    @Override
-    public void updateHostLink(final NodeConnector p, final Host h, final UpdateType t, final Set<Property> props) {
-        // Update app defined topology
-    }
-
-    @Override
-    public Status saveConfig() {
-        // FIXME: commit configuration
-        return null;
-    }
-}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.java b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.java
deleted file mode 100644 (file)
index 2d85f76..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.compatibility.topologymanager;
-
-import java.util.concurrent.ConcurrentMap;
-
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
-
-public abstract class ConfigurableLinkManager implements ITopologyManager {
-    @Override
-    public final Status addUserLink(final TopologyUserLinkConfig link) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final Status deleteUserLink(final String linkName) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-
-    @Override
-    public final ConcurrentMap<String,TopologyUserLinkConfig> getUserLinks() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub");
-    }
-}
index 688e6ac09b25b29d8160ad05b10ef078430e1d37..b9e9d19b48dce4eed7f5e42cc335588306ad1692 100644 (file)
@@ -12,8 +12,6 @@
 
   <modules>
     <module>sal-compatibility</module>
-    <module>inventory-topology-compatibility</module>
-    <module>flow-management-compatibility</module>
   </modules>
 
   <dependencies>
index ed5e19219353e3265a5b7f55ef58dccd5f6b7ad7..5a9b19021945b947e7601fbdaa82dd74676fbdc8 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
diff --git a/opendaylight/md-sal/md-sal-config/pom.xml b/opendaylight/md-sal/md-sal-config/pom.xml
new file mode 100644 (file)
index 0000000..2e19b5a
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>sal-parent</artifactId>
+    <version>1.1-SNAPSHOT</version>
+  </parent>
+  <artifactId>md-sal-config</artifactId>
+  <description>Configuration files for md-sal</description>
+  <packaging>jar</packaging>
+  <build>
+    <plugins>
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/initial/01-md-sal.xml</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
index 3f02765affd8a062420f327fb489ed3adf5d3966..6c6760d789a086157bdb35a0a66d620db8057d3c 100644 (file)
@@ -32,6 +32,9 @@
 
     <module>sal-binding-util</module>
 
+    <!-- Configuration File -->
+    <module>md-sal-config</module>
+
     <!-- Samples -->
     <module>samples</module>
 
     <!--InMemory DOM DataStore-->
     <module>sal-inmemory-datastore</module>
 
-    <!--sal-protocolbuffer-encoding-->
-    <module>sal-protocolbuffer-encoding</module>
+    <!--sal-protocolbuffer-encoding is now part of sal-clutering-commons-->
+    <module>sal-clustering-commons</module>
+
+    <!-- sal clustering configuration -->
+    <module>sal-clustering-config</module>
 
     <!-- sal-distributed-datastore -->
     <module>sal-distributed-datastore</module>
 
+    <!-- XSQL -->
+    <module>sal-dom-xsql</module>
+
     <!-- Yang Test Models for MD-SAL -->
     <module>sal-test-model</module>
 
index 641ec0582c3790cac20a6b7102ad5e12134e72e1..cbd7ca2d70f5dc090a1e842b75c200cb0c1976b9 100644 (file)
@@ -11,10 +11,12 @@ package org.opendaylight.controller.cluster.example;
 import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.japi.Creator;
+import com.google.common.base.Optional;
 import org.opendaylight.controller.cluster.example.messages.KeyValue;
 import org.opendaylight.controller.cluster.example.messages.KeyValueSaved;
 import org.opendaylight.controller.cluster.example.messages.PrintRole;
 import org.opendaylight.controller.cluster.example.messages.PrintState;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
 import org.opendaylight.controller.cluster.raft.RaftActor;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
 
@@ -31,15 +33,17 @@ public class ExampleActor extends RaftActor {
     private long persistIdentifier = 1;
 
 
-    public ExampleActor(String id, Map<String, String> peerAddresses) {
-        super(id, peerAddresses);
+    public ExampleActor(String id, Map<String, String> peerAddresses,
+        Optional<ConfigParams> configParams) {
+        super(id, peerAddresses, configParams);
     }
 
-    public static Props props(final String id, final Map<String, String> peerAddresses){
+    public static Props props(final String id, final Map<String, String> peerAddresses,
+        final Optional<ConfigParams> configParams){
         return Props.create(new Creator<ExampleActor>(){
 
             @Override public ExampleActor create() throws Exception {
-                return new ExampleActor(id, peerAddresses);
+                return new ExampleActor(id, peerAddresses, configParams);
             }
         });
     }
@@ -56,10 +60,12 @@ public class ExampleActor extends RaftActor {
             }
 
         } else if (message instanceof PrintState) {
-            LOG.debug("State of the node:"+getId() + " has = "+state.size() + " entries");
+            LOG.debug("State of the node:{} has entries={}, {}",
+                getId(), state.size(), getReplicatedLogState());
 
         } else if (message instanceof PrintRole) {
-            LOG.debug(getId() + " = " + getRaftState());
+            LOG.debug("{} = {}, Peers={}", getId(), getRaftState(),getPeers());
+
         } else {
             super.onReceiveCommand(message);
         }
@@ -83,6 +89,11 @@ public class ExampleActor extends RaftActor {
     @Override protected void applySnapshot(Object snapshot) {
         state.clear();
         state.putAll((HashMap) snapshot);
+        LOG.debug("Snapshot applied to state :" + ((HashMap) snapshot).size());
+    }
+
+    @Override protected void onStateChanged() {
+
     }
 
     @Override public void onReceiveRecover(Object message) {
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleConfigParamsImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleConfigParamsImpl.java
new file mode 100644 (file)
index 0000000..d11377d
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.example;
+
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
+
+/**
+ * Implementation of ConfigParams for Example
+ */
+public class ExampleConfigParamsImpl extends DefaultConfigParamsImpl {
+    @Override
+    public long getSnapshotBatchCount() {
+        return 50;
+    }
+}
index a148ed4009e81870d7443fa867faac43605d4c25..0e5d643a643731277003781b75dd353c92697285 100644 (file)
@@ -11,7 +11,9 @@ package org.opendaylight.controller.cluster.example;
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import akka.actor.PoisonPill;
+import com.google.common.base.Optional;
 import org.opendaylight.controller.cluster.example.messages.KeyValue;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
 
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
@@ -34,15 +36,15 @@ public class Main {
     public static void main(String[] args) throws Exception{
         ActorRef example1Actor =
             actorSystem.actorOf(ExampleActor.props("example-1",
-                withoutPeer("example-1")), "example-1");
+                withoutPeer("example-1"), Optional.<ConfigParams>absent()), "example-1");
 
         ActorRef example2Actor =
             actorSystem.actorOf(ExampleActor.props("example-2",
-                withoutPeer("example-2")), "example-2");
+                withoutPeer("example-2"), Optional.<ConfigParams>absent()), "example-2");
 
         ActorRef example3Actor =
             actorSystem.actorOf(ExampleActor.props("example-3",
-                withoutPeer("example-3")), "example-3");
+                withoutPeer("example-3"), Optional.<ConfigParams>absent()), "example-3");
 
 
         List<ActorRef> examples = Arrays.asList(example1Actor, example2Actor, example3Actor);
@@ -74,7 +76,8 @@ public class Main {
                         String actorName = "example-" + i;
                         examples.add(i - 1,
                             actorSystem.actorOf(ExampleActor.props(actorName,
-                                withoutPeer(actorName)), actorName));
+                                withoutPeer(actorName), Optional.<ConfigParams>absent()),
+                                actorName));
                         System.out.println("Created actor : " + actorName);
                         continue;
                     }
index c2d0b3a6b7cf9a043554ee092de35fd22a8d293d..fd6e192bf0497777de2643a1b3f28a2a76b72e42 100644 (file)
@@ -2,8 +2,10 @@ package org.opendaylight.controller.cluster.example;
 
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
+import com.google.common.base.Optional;
 import org.opendaylight.controller.cluster.example.messages.PrintRole;
 import org.opendaylight.controller.cluster.example.messages.PrintState;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
 import org.opendaylight.controller.cluster.raft.client.messages.AddRaftPeer;
 import org.opendaylight.controller.cluster.raft.client.messages.RemoveRaftPeer;
 
@@ -11,14 +13,13 @@ import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Random;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This is a test driver for testing akka-raft implementation
  * Its uses ExampleActors and threads to push content(key-vals) to these actors
  * Each ExampleActor can have one or more ClientActors. Each ClientActor spawns
- * a thread and starts push logs to the actor its assignged to.
+ * a thread and starts push logs to the actor its assigned to.
  */
 public class TestDriver {
 
@@ -26,7 +27,9 @@ public class TestDriver {
     private static Map<String, String> allPeers = new HashMap<>();
     private static Map<String, ActorRef> clientActorRefs  = new HashMap<String, ActorRef>();
     private static Map<String, ActorRef> actorRefs = new HashMap<String, ActorRef>();
-    private static LogGenerator logGenerator = new LogGenerator();;
+    private static LogGenerator logGenerator = new LogGenerator();
+    private int nameCounter = 0;
+    private static ConfigParams configParams = new ExampleConfigParamsImpl();
 
     /**
      * Create nodes, add clients and start logging.
@@ -35,6 +38,7 @@ public class TestDriver {
      *  createNodes:{num}
      *  addNodes:{num}
      *  stopNode:{nodeName}
+     *  reinstateNode:{nodeName}
      *  addClients:{num}
      *  addClientsToNode:{nodeName, num}
      *  startLogging
@@ -83,6 +87,10 @@ public class TestDriver {
                 String[] arr = command.split(":");
                 td.stopNode(arr[1]);
 
+            } else if (command.startsWith("reinstateNode")) {
+                String[] arr = command.split(":");
+                td.reinstateNode(arr[1]);
+
             } else if (command.startsWith("startLogging")) {
                 td.startAllLogging();
 
@@ -106,15 +114,19 @@ public class TestDriver {
         }
     }
 
+    public static ActorRef createExampleActor(String name) {
+        return actorSystem.actorOf(ExampleActor.props(name, withoutPeer(name),
+            Optional.of(configParams)), name);
+    }
+
     public void createNodes(int num) {
         for (int i=0; i < num; i++)  {
-            int rand = getUnusedRandom(num);
-            allPeers.put("example-"+rand, "akka://default/user/example-"+rand);
+            nameCounter = nameCounter + 1;
+            allPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
         }
 
         for (String s : allPeers.keySet())  {
-            ActorRef exampleActor = actorSystem.actorOf(
-                ExampleActor.props(s, withoutPeer(s)), s);
+            ActorRef exampleActor = createExampleActor(s);
             actorRefs.put(s, exampleActor);
             System.out.println("Created node:"+s);
 
@@ -125,15 +137,14 @@ public class TestDriver {
     public void addNodes(int num) {
         Map<String, String> newPeers = new HashMap<>();
         for (int i=0; i < num; i++)  {
-            int rand = getUnusedRandom(num);
-            newPeers.put("example-"+rand, "akka://default/user/example-"+rand);
-            allPeers.put("example-"+rand, "akka://default/user/example-"+rand);
+            nameCounter = nameCounter + 1;
+            newPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
+            allPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
 
         }
         Map<String, ActorRef> newActorRefs = new HashMap<String, ActorRef>(num);
         for (Map.Entry<String, String> entry : newPeers.entrySet())  {
-            ActorRef exampleActor = actorSystem.actorOf(
-                ExampleActor.props(entry.getKey(), withoutPeer(entry.getKey())), entry.getKey());
+            ActorRef exampleActor = createExampleActor(entry.getKey());
             newActorRefs.put(entry.getKey(), exampleActor);
 
             //now also add these new nodes as peers from the previous nodes
@@ -165,7 +176,7 @@ public class TestDriver {
     public void addClientsToNode(String actorName, int num) {
         ActorRef actorRef = actorRefs.get(actorName);
         for (int i=0; i < num; i++) {
-            String clientName = "client-" + i + "-" + actorRef;
+            String clientName = "client-" + i + "-" + actorName;
             clientActorRefs.put(clientName,
                 actorSystem.actorOf(ClientActor.props(actorRef), clientName));
             System.out.println("Added client-node:" + clientName);
@@ -174,11 +185,13 @@ public class TestDriver {
 
     public void stopNode(String actorName) {
         ActorRef actorRef = actorRefs.get(actorName);
-        String clientName = "client-"+actorName;
-        if(clientActorRefs.containsKey(clientName)) {
-            actorSystem.stop(clientActorRefs.get(clientName));
-            clientActorRefs.remove(clientName);
+
+        for (Map.Entry<String,ActorRef> entry : clientActorRefs.entrySet()) {
+            if (entry.getKey().endsWith(actorName)) {
+                actorSystem.stop(entry.getValue());
+            }
         }
+
         actorSystem.stop(actorRef);
         actorRefs.remove(actorName);
 
@@ -187,7 +200,21 @@ public class TestDriver {
         }
 
         allPeers.remove(actorName);
+    }
 
+    public void reinstateNode(String actorName) {
+        String address = "akka://default/user/"+actorName;
+        allPeers.put(actorName, address);
+
+        ActorRef exampleActor = createExampleActor(actorName);
+
+        for (ActorRef actor : actorRefs.values()) {
+            actor.tell(new AddRaftPeer(actorName, address), null);
+        }
+
+        actorRefs.put(actorName, exampleActor);
+
+        addClientsToNode(actorName, 1);
     }
 
     public void startAllLogging() {
@@ -232,14 +259,6 @@ public class TestDriver {
         return null;
     }
 
-    private int getUnusedRandom(int num) {
-        int rand = -1;
-        do {
-            rand = (new Random()).nextInt(num * num);
-        } while (allPeers.keySet().contains("example-"+rand));
-
-        return rand;
-    }
 
     private static Map<String, String> withoutPeer(String peerId) {
         Map<String, String> without = new ConcurrentHashMap<>(allPeers);
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java
new file mode 100644 (file)
index 0000000..b5b034a
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse 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.raft;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract class handling the mapping of
+ * logical LogEntry Index and the physical list index.
+ */
+public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
+
+    protected final List<ReplicatedLogEntry> journal;
+    protected final Object snapshot;
+    protected long snapshotIndex = -1;
+    protected long snapshotTerm = -1;
+
+    public AbstractReplicatedLogImpl(Object state, long snapshotIndex,
+        long snapshotTerm, List<ReplicatedLogEntry> unAppliedEntries) {
+        this.snapshot = state;
+        this.snapshotIndex = snapshotIndex;
+        this.snapshotTerm = snapshotTerm;
+        this.journal = new ArrayList<>(unAppliedEntries);
+    }
+
+
+    public AbstractReplicatedLogImpl() {
+        this.snapshot = null;
+        this.journal = new ArrayList<>();
+    }
+
+    protected int adjustedIndex(long logEntryIndex) {
+        if(snapshotIndex < 0){
+            return (int) logEntryIndex;
+        }
+        return (int) (logEntryIndex - (snapshotIndex + 1));
+    }
+
+    @Override
+    public ReplicatedLogEntry get(long logEntryIndex) {
+        int adjustedIndex = adjustedIndex(logEntryIndex);
+
+        if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
+            // physical index should be less than list size and >= 0
+            return null;
+        }
+
+        return journal.get(adjustedIndex);
+    }
+
+    @Override
+    public ReplicatedLogEntry last() {
+        if (journal.isEmpty()) {
+            return null;
+        }
+        // get the last entry directly from the physical index
+        return journal.get(journal.size() - 1);
+    }
+
+    @Override
+    public long lastIndex() {
+        if (journal.isEmpty()) {
+            // it can happen that after snapshot, all the entries of the
+            // journal are trimmed till lastApplied, so lastIndex = snapshotIndex
+            return snapshotIndex;
+        }
+        return last().getIndex();
+    }
+
+    @Override
+    public long lastTerm() {
+        if (journal.isEmpty()) {
+            // it can happen that after snapshot, all the entries of the
+            // journal are trimmed till lastApplied, so lastTerm = snapshotTerm
+            return snapshotTerm;
+        }
+        return last().getTerm();
+    }
+
+    @Override
+    public void removeFrom(long logEntryIndex) {
+        int adjustedIndex = adjustedIndex(logEntryIndex);
+        if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
+            // physical index should be less than list size and >= 0
+            return;
+        }
+        journal.subList(adjustedIndex , journal.size()).clear();
+    }
+
+    @Override
+    public void append(ReplicatedLogEntry replicatedLogEntry) {
+        journal.add(replicatedLogEntry);
+    }
+
+    @Override
+    public List<ReplicatedLogEntry> getFrom(long logEntryIndex) {
+        return getFrom(logEntryIndex, journal.size());
+    }
+
+    @Override
+    public List<ReplicatedLogEntry> getFrom(long logEntryIndex, int max) {
+        int adjustedIndex = adjustedIndex(logEntryIndex);
+        int size = journal.size();
+        List<ReplicatedLogEntry> entries = new ArrayList<>(100);
+        if (adjustedIndex >= 0 && adjustedIndex < size) {
+            // physical index should be less than list size and >= 0
+            int maxIndex = adjustedIndex + max;
+            if(maxIndex > size){
+                maxIndex = size;
+            }
+            entries.addAll(journal.subList(adjustedIndex, maxIndex));
+        }
+        return entries;
+    }
+
+
+    @Override
+    public long size() {
+       return journal.size();
+    }
+
+    @Override
+    public boolean isPresent(long logEntryIndex) {
+        if (logEntryIndex > lastIndex()) {
+            // if the request logical index is less than the last present in the list
+            return false;
+        }
+        int adjustedIndex = adjustedIndex(logEntryIndex);
+        return (adjustedIndex >= 0);
+    }
+
+    @Override
+    public boolean isInSnapshot(long logEntryIndex) {
+        return logEntryIndex <= snapshotIndex;
+    }
+
+    @Override
+    public Object getSnapshot() {
+        return snapshot;
+    }
+
+    @Override
+    public long getSnapshotIndex() {
+        return snapshotIndex;
+    }
+
+    @Override
+    public long getSnapshotTerm() {
+        return snapshotTerm;
+    }
+
+    @Override
+    public abstract void appendAndPersist(ReplicatedLogEntry replicatedLogEntry);
+
+    @Override
+    public abstract void removeFromAndPersist(long index);
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java
new file mode 100644 (file)
index 0000000..4c6434a
--- /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.cluster.raft;
+
+import scala.concurrent.duration.FiniteDuration;
+
+/**
+ * Configuration Parameter interface for configuring the Raft consensus system
+ * <p/>
+ * Any component using this implementation might want to provide an implementation of
+ * this interface to configure
+ *
+ * A default implementation will be used if none is provided.
+ *
+ * @author Kamal Rameshan
+ */
+public interface ConfigParams {
+    /**
+     * The minimum number of entries to be present in the in-memory Raft log
+     * for a snapshot to be taken
+     *
+     * @return long
+     */
+    public long getSnapshotBatchCount();
+
+    /**
+     * The interval at which a heart beat message will be sent to the remote
+     * RaftActor
+     *
+     * @return FiniteDuration
+     */
+    public FiniteDuration getHeartBeatInterval();
+
+    /**
+     * The interval in which a new election would get triggered if no leader is found
+     *
+     * Normally its set to atleast twice the heart beat interval
+     *
+     * @return FiniteDuration
+     */
+    public FiniteDuration getElectionTimeOutInterval();
+
+    /**
+     * The maximum election time variance. The election is scheduled using both
+     * the Election Timeout and Variance
+     *
+     * @return int
+     */
+    public int getElectionTimeVariance();
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java
new file mode 100644 (file)
index 0000000..6432fa4
--- /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.cluster.raft;
+
+import scala.concurrent.duration.FiniteDuration;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Default implementation of the ConfigParams
+ *
+ * If no implementation is provided for ConfigParams, then this will be used.
+ */
+public class DefaultConfigParamsImpl implements ConfigParams {
+
+    private static final int SNAPSHOT_BATCH_COUNT = 100000;
+
+    /**
+     * The maximum election time variance
+     */
+    private static final int ELECTION_TIME_MAX_VARIANCE = 100;
+
+
+    /**
+     * The interval at which a heart beat message will be sent to the remote
+     * RaftActor
+     * <p/>
+     * Since this is set to 100 milliseconds the Election timeout should be
+     * at least 200 milliseconds
+     */
+    public static final FiniteDuration HEART_BEAT_INTERVAL =
+        new FiniteDuration(100, TimeUnit.MILLISECONDS);
+
+
+    @Override
+    public long getSnapshotBatchCount() {
+        return SNAPSHOT_BATCH_COUNT;
+    }
+
+    @Override
+    public FiniteDuration getHeartBeatInterval() {
+        return HEART_BEAT_INTERVAL;
+    }
+
+
+    @Override
+    public FiniteDuration getElectionTimeOutInterval() {
+        // returns 2 times the heart beat interval
+        return getHeartBeatInterval().$times(2);
+    }
+
+    @Override
+    public int getElectionTimeVariance() {
+        return ELECTION_TIME_MAX_VARIANCE;
+    }
+}
index b8e9653bc5db92ffa4cb15afd391c6a9ec05cd16..0a979d24eef2a26d60cb6168c18d84815037cf18 100644 (file)
@@ -22,6 +22,7 @@ import akka.persistence.UntypedPersistentActor;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
 import org.opendaylight.controller.cluster.raft.base.messages.Replicate;
+import com.google.common.base.Optional;
 import org.opendaylight.controller.cluster.raft.behaviors.Candidate;
 import org.opendaylight.controller.cluster.raft.behaviors.Follower;
 import org.opendaylight.controller.cluster.raft.behaviors.Leader;
@@ -33,7 +34,6 @@ import org.opendaylight.controller.cluster.raft.client.messages.RemoveRaftPeer;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -100,14 +100,22 @@ public abstract class RaftActor extends UntypedPersistentActor {
 
 
     public RaftActor(String id, Map<String, String> peerAddresses) {
+        this(id, peerAddresses, Optional.<ConfigParams>absent());
+    }
+
+    public RaftActor(String id, Map<String, String> peerAddresses,
+         Optional<ConfigParams> configParams) {
+
         context = new RaftActorContextImpl(this.getSelf(),
-            this.getContext(),
-            id, new ElectionTermImpl(),
-            -1, -1, replicatedLog, peerAddresses, LOG);
+            this.getContext(), id, new ElectionTermImpl(),
+            -1, -1, replicatedLog, peerAddresses,
+            (configParams.isPresent() ? configParams.get(): new DefaultConfigParamsImpl()),
+            LOG);
     }
 
     @Override public void onReceiveRecover(Object message) {
         if (message instanceof SnapshotOffer) {
+            LOG.debug("SnapshotOffer called..");
             SnapshotOffer offer = (SnapshotOffer) message;
             Snapshot snapshot = (Snapshot) offer.snapshot();
 
@@ -116,6 +124,13 @@ public abstract class RaftActor extends UntypedPersistentActor {
             // when we need to install it on a peer
             replicatedLog = new ReplicatedLogImpl(snapshot);
 
+            context.setReplicatedLog(replicatedLog);
+
+            LOG.debug("Applied snapshot to replicatedLog. " +
+                "snapshotIndex={}, snapshotTerm={}, journal-size={}",
+                replicatedLog.snapshotIndex, replicatedLog.snapshotTerm,
+                replicatedLog.size());
+
             // Apply the snapshot to the actors state
             applySnapshot(snapshot.getState());
 
@@ -127,8 +142,13 @@ public abstract class RaftActor extends UntypedPersistentActor {
             context.getTermInformation().update(((UpdateElectionTerm) message).getCurrentTerm(), ((UpdateElectionTerm) message).getVotedFor());
         } else if (message instanceof RecoveryCompleted) {
             LOG.debug(
-                "Last index in log : " + replicatedLog.lastIndex());
+                "RecoveryCompleted - Switching actor to Follower - " +
+                    "Last index in log:{}, snapshotIndex={}, snapshotTerm={}, " +
+                    "journal-size={}",
+                replicatedLog.lastIndex(), replicatedLog.snapshotIndex,
+                replicatedLog.snapshotTerm, replicatedLog.size());
             currentBehavior = switchBehavior(RaftState.Follower);
+            onStateChanged();
         }
     }
 
@@ -187,10 +207,23 @@ public abstract class RaftActor extends UntypedPersistentActor {
 
             RaftState state =
                 currentBehavior.handleMessage(getSender(), message);
+            RaftActorBehavior oldBehavior = currentBehavior;
             currentBehavior = switchBehavior(state);
+            if(oldBehavior != currentBehavior){
+                onStateChanged();
+            }
         }
     }
 
+    public java.util.Set<String> getPeers() {
+        return context.getPeerAddresses().keySet();
+    }
+
+    protected String getReplicatedLogState() {
+        return "snapshotIndex=" + context.getReplicatedLog().getSnapshotIndex()
+            + ", snapshotTerm=" + context.getReplicatedLog().getSnapshotTerm()
+            + ", im-mem journal size=" + context.getReplicatedLog().size();
+    }
 
 
     /**
@@ -243,9 +276,21 @@ public abstract class RaftActor extends UntypedPersistentActor {
         String peerAddress = context.getPeerAddress(leaderId);
         LOG.debug("getLeader leaderId = " + leaderId + " peerAddress = "
             + peerAddress);
+
+        if(peerAddress == null){
+            return null;
+        }
         return context.actorSelection(peerAddress);
     }
 
+    /**
+     *
+     * @return the current leader's id
+     */
+    protected String getLeaderId(){
+        return currentBehavior.getLeaderId();
+    }
+
     protected RaftState getRaftState() {
         return currentBehavior.state();
     }
@@ -313,6 +358,13 @@ public abstract class RaftActor extends UntypedPersistentActor {
      */
     protected abstract void applySnapshot(Object snapshot);
 
+    /**
+     * This method will be called by the RaftActor when the state of the
+     * RaftActor changes. The derived actor can then use methods like
+     * isLeader or getLeader to do something useful
+     */
+    protected abstract void onStateChanged();
+
     private RaftActorBehavior switchBehavior(RaftState state) {
         if (currentBehavior != null) {
             if (currentBehavior.state() == state) {
@@ -339,89 +391,40 @@ public abstract class RaftActor extends UntypedPersistentActor {
         } else {
             behavior = new Leader(context);
         }
+
+
+
         return behavior;
     }
 
     private void trimPersistentData(long sequenceNumber) {
-        // Trim snapshots
+        // Trim akka snapshots
         // FIXME : Not sure how exactly the SnapshotSelectionCriteria is applied
         // For now guessing that it is ANDed.
         deleteSnapshots(new SnapshotSelectionCriteria(
-            sequenceNumber - 100000, 43200000));
+            sequenceNumber - context.getConfigParams().getSnapshotBatchCount(), 43200000));
 
-        // Trim journal
+        // Trim akka journal
         deleteMessages(sequenceNumber);
     }
 
 
-    private class ReplicatedLogImpl implements ReplicatedLog {
-        private final List<ReplicatedLogEntry> journal;
-        private final Object snapshot;
-        private long snapshotIndex = -1;
-        private long snapshotTerm = -1;
+    private class ReplicatedLogImpl extends AbstractReplicatedLogImpl {
 
         public ReplicatedLogImpl(Snapshot snapshot) {
-            this.snapshot = snapshot.getState();
-            this.snapshotIndex = snapshot.getLastAppliedIndex();
-            this.snapshotTerm = snapshot.getLastAppliedTerm();
-
-            this.journal = new ArrayList<>(snapshot.getUnAppliedEntries());
+            super(snapshot.getState(),
+                snapshot.getLastAppliedIndex(), snapshot.getLastAppliedTerm(),
+                snapshot.getUnAppliedEntries());
         }
 
         public ReplicatedLogImpl() {
-            this.snapshot = null;
-            this.journal = new ArrayList<>();
-        }
-
-        @Override public ReplicatedLogEntry get(long index) {
-            int adjustedIndex = adjustedIndex(index);
-
-            if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
-                return null;
-            }
-
-            return journal.get(adjustedIndex);
-        }
-
-        @Override public ReplicatedLogEntry last() {
-            if (journal.size() == 0) {
-                return null;
-            }
-            return get(journal.size() - 1);
-        }
-
-        @Override public long lastIndex() {
-            if (journal.size() == 0) {
-                return -1;
-            }
-
-            return last().getIndex();
-        }
-
-        @Override public long lastTerm() {
-            if (journal.size() == 0) {
-                return -1;
-            }
-
-            return last().getTerm();
+            super();
         }
 
+        @Override public void removeFromAndPersist(long logEntryIndex) {
+            int adjustedIndex = adjustedIndex(logEntryIndex);
 
-        @Override public void removeFrom(long index) {
-            int adjustedIndex = adjustedIndex(index);
-
-            if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
-                return;
-            }
-
-            journal.subList(adjustedIndex , journal.size()).clear();
-        }
-
-
-        @Override public void removeFromAndPersist(long index) {
-            int adjustedIndex = adjustedIndex(index);
-
-            if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
+            if (adjustedIndex < 0) {
                 return;
             }
 
@@ -435,29 +438,6 @@ public abstract class RaftActor extends UntypedPersistentActor {
                     //FIXME : Doing nothing for now
                 }
             });
-
-
-        }
-
-        @Override public void append(
-            final ReplicatedLogEntry replicatedLogEntry) {
-            journal.add(replicatedLogEntry);
-        }
-
-        @Override public List<ReplicatedLogEntry> getFrom(long index) {
-            int adjustedIndex = adjustedIndex(index);
-
-            List<ReplicatedLogEntry> entries = new ArrayList<>(100);
-            if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
-                return entries;
-            }
-
-
-            for (int i = adjustedIndex;
-                 i < journal.size(); i++) {
-                entries.add(journal.get(i));
-            }
-            return entries;
         }
 
         @Override public void appendAndPersist(
@@ -482,20 +462,42 @@ public abstract class RaftActor extends UntypedPersistentActor {
                 new Procedure<ReplicatedLogEntry>() {
                     public void apply(ReplicatedLogEntry evt) throws Exception {
                         // FIXME : Tentatively create a snapshot every hundred thousand entries. To be tuned.
-                        if (size() > 100000) {
-                            ReplicatedLogEntry lastAppliedEntry =
-                                get(context.getLastApplied());
+                        if (journal.size() > context.getConfigParams().getSnapshotBatchCount()) {
+                            LOG.info("Initiating Snapshot Capture..");
                             long lastAppliedIndex = -1;
                             long lastAppliedTerm = -1;
+
+                            ReplicatedLogEntry lastAppliedEntry = get(context.getLastApplied());
                             if (lastAppliedEntry != null) {
                                 lastAppliedIndex = lastAppliedEntry.getIndex();
                                 lastAppliedTerm = lastAppliedEntry.getTerm();
                             }
 
-                            saveSnapshot(Snapshot.create(createSnapshot(),
+                            LOG.debug("Snapshot Capture logSize: {}", journal.size());
+                            LOG.debug("Snapshot Capture lastApplied:{} ", context.getLastApplied());
+                            LOG.debug("Snapshot Capture lastAppliedIndex:{}", lastAppliedIndex);
+                            LOG.debug("Snapshot Capture lastAppliedTerm:{}", lastAppliedTerm);
+
+                            // create a snapshot object from the state provided and save it
+                            // when snapshot is saved async, SaveSnapshotSuccess is raised.
+                            Snapshot sn = Snapshot.create(createSnapshot(),
                                 getFrom(context.getLastApplied() + 1),
                                 lastIndex(), lastTerm(), lastAppliedIndex,
-                                lastAppliedTerm));
+                                lastAppliedTerm);
+                            saveSnapshot(sn);
+
+                            LOG.info("Persisting of snapshot done:{}", sn.getLogMessage());
+
+                            //be greedy and remove entries from in-mem journal which are in the snapshot
+                            // and update snapshotIndex and snapshotTerm without waiting for the success,
+                            // TODO: damage-recovery to be done on failure
+                            journal.subList(0, (int) (lastAppliedIndex - snapshotIndex)).clear();
+                            snapshotIndex = lastAppliedIndex;
+                            snapshotTerm = lastAppliedTerm;
+
+                            LOG.info("Removed in-memory snapshotted entries, " +
+                                "adjusted snaphsotIndex:{}" +
+                                "and term:{}", snapshotIndex, lastAppliedTerm);
                         }
                         // Send message for replication
                         if (clientActor != null) {
@@ -509,46 +511,8 @@ public abstract class RaftActor extends UntypedPersistentActor {
             );
         }
 
-        @Override public long size() {
-            return journal.size() + snapshotIndex + 1;
-        }
-
-        @Override public boolean isPresent(long index) {
-            int adjustedIndex = adjustedIndex(index);
-
-            if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override public boolean isInSnapshot(long index) {
-            return index <= snapshotIndex;
-        }
-
-        @Override public Object getSnapshot() {
-            return snapshot;
-        }
-
-        @Override public long getSnapshotIndex() {
-            return snapshotIndex;
-        }
-
-        @Override public long getSnapshotTerm() {
-            return snapshotTerm;
-        }
-
-        private int adjustedIndex(long index) {
-            if(snapshotIndex < 0){
-                return (int) index;
-            }
-            return (int) (index - snapshotIndex);
-        }
     }
 
-
-
-
     private static class DeleteEntries implements Serializable {
         private final int fromIndex;
 
@@ -609,6 +573,17 @@ public abstract class RaftActor extends UntypedPersistentActor {
         public long getLastAppliedTerm() {
             return lastAppliedTerm;
         }
+
+        public String getLogMessage() {
+            StringBuilder sb = new StringBuilder();
+            return sb.append("Snapshot={")
+                .append("lastTerm:" + this.getLastTerm()  + ", ")
+                .append("LastAppliedIndex:" + this.getLastAppliedIndex()  + ", ")
+                .append("LastAppliedTerm:" + this.getLastAppliedTerm()  + ", ")
+                .append("UnAppliedEntries size:" + this.getUnAppliedEntries().size()  + "}")
+                .toString();
+
+        }
     }
 
     private class ElectionTermImpl implements ElectionTerm {
index ae9431a43acf576f2769672b49d3ce234014e3c0..0eb4b7377976526ac48eaefa9a9922b6a70c0076 100644 (file)
@@ -85,6 +85,12 @@ public interface RaftActorContext {
      */
     void setLastApplied(long lastApplied);
 
+    /**
+     *
+     * @param replicatedLog
+     */
+    public void setReplicatedLog(ReplicatedLog replicatedLog);
+
     /**
      * @return A representation of the log
      */
@@ -155,4 +161,9 @@ public interface RaftActorContext {
      * @param peerAddress
      */
     void setPeerAddress(String peerId, String peerAddress);
+
+    /**
+     * @return ConfigParams
+     */
+    public ConfigParams getConfigParams();
 }
index 833c8a9e8ad1ca7b8fe170aadffc25b3c12b6b24..25da37105cea18e46270a4baccfdae9b459a2500 100644 (file)
@@ -19,7 +19,7 @@ import java.util.Map;
 
 import static com.google.common.base.Preconditions.checkState;
 
-public class RaftActorContextImpl implements RaftActorContext{
+public class RaftActorContextImpl implements RaftActorContext {
 
     private final ActorRef actor;
 
@@ -33,16 +33,20 @@ public class RaftActorContextImpl implements RaftActorContext{
 
     private long lastApplied;
 
-    private final ReplicatedLog replicatedLog;
+    private ReplicatedLog replicatedLog;
 
     private final Map<String, String> peerAddresses;
 
     private final LoggingAdapter LOG;
 
+    private final ConfigParams configParams;
+
     public RaftActorContextImpl(ActorRef actor, UntypedActorContext context,
         String id,
         ElectionTerm termInformation, long commitIndex,
-        long lastApplied, ReplicatedLog replicatedLog, Map<String, String> peerAddresses, LoggingAdapter logger) {
+        long lastApplied, ReplicatedLog replicatedLog,
+        Map<String, String> peerAddresses, ConfigParams configParams,
+        LoggingAdapter logger) {
         this.actor = actor;
         this.context = context;
         this.id = id;
@@ -51,6 +55,7 @@ public class RaftActorContextImpl implements RaftActorContext{
         this.lastApplied = lastApplied;
         this.replicatedLog = replicatedLog;
         this.peerAddresses = peerAddresses;
+        this.configParams = configParams;
         this.LOG = logger;
     }
 
@@ -90,6 +95,10 @@ public class RaftActorContextImpl implements RaftActorContext{
         this.lastApplied = lastApplied;
     }
 
+    @Override public void setReplicatedLog(ReplicatedLog replicatedLog) {
+        this.replicatedLog = replicatedLog;
+    }
+
     @Override public ReplicatedLog getReplicatedLog() {
         return replicatedLog;
     }
@@ -110,6 +119,10 @@ public class RaftActorContextImpl implements RaftActorContext{
         return peerAddresses.get(peerId);
     }
 
+    @Override public ConfigParams getConfigParams() {
+        return configParams;
+    }
+
     @Override public void addToPeers(String name, String address) {
         peerAddresses.put(name, address);
     }
index b7c8955aad982873ee02fff78f629b7f7bc1f1b5..e6e160bc02bf1fd72305325aefc91a1ac2a9fac0 100644 (file)
@@ -84,6 +84,11 @@ public interface ReplicatedLog {
      */
     List<ReplicatedLogEntry> getFrom(long index);
 
+    /**
+     *
+     * @param index the index of the log entry
+     */
+    List<ReplicatedLogEntry> getFrom(long index, int max);
 
     /**
      *
index f7281bb8e3967c3ca2be583adb35210cbd07e87b..0a553b40fd59aab555f258f897a2154830afd1c8 100644 (file)
@@ -43,27 +43,6 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior {
      */
     protected final RaftActorContext context;
 
-    /**
-     * The maximum election time variance
-     */
-    private static final int ELECTION_TIME_MAX_VARIANCE = 100;
-
-    /**
-     * The interval at which a heart beat message will be sent to the remote
-     * RaftActor
-     * <p/>
-     * Since this is set to 100 milliseconds the Election timeout should be
-     * at least 200 milliseconds
-     */
-    protected static final FiniteDuration HEART_BEAT_INTERVAL =
-        new FiniteDuration(100, TimeUnit.MILLISECONDS);
-
-    /**
-     * The interval in which a new election would get triggered if no leader is found
-     */
-    private static final long ELECTION_TIME_INTERVAL =
-        HEART_BEAT_INTERVAL.toMillis() * 2;
-
     /**
      *
      */
@@ -208,9 +187,9 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior {
      * @return
      */
     protected FiniteDuration electionDuration() {
-        long variance = new Random().nextInt(ELECTION_TIME_MAX_VARIANCE);
-        return new FiniteDuration(ELECTION_TIME_INTERVAL + variance,
-            TimeUnit.MILLISECONDS);
+        long variance = new Random().nextInt(context.getConfigParams().getElectionTimeVariance());
+        return context.getConfigParams().getElectionTimeOutInterval().$plus(
+            new FiniteDuration(variance, TimeUnit.MILLISECONDS));
     }
 
     /**
index db62dfc2ac1cd4f10c59849c0666b9291ca946a3..c8cd41dfa1883a1c7d1d43d2f7697b0ff988ab38 100644 (file)
@@ -126,15 +126,10 @@ public class Follower extends AbstractRaftActorBehavior {
             int addEntriesFrom = 0;
             if (context.getReplicatedLog().size() > 0) {
 
-                // Find the entry up until which the one that is not in the
-                // follower's log
-                for (int i = 0;
-                     i < appendEntries.getEntries()
-                         .size(); i++, addEntriesFrom++) {
-                    ReplicatedLogEntry matchEntry =
-                        appendEntries.getEntries().get(i);
-                    ReplicatedLogEntry newEntry = context.getReplicatedLog()
-                        .get(matchEntry.getIndex());
+                // Find the entry up until which the one that is not in the follower's log
+                for (int i = 0;i < appendEntries.getEntries().size(); i++, addEntriesFrom++) {
+                    ReplicatedLogEntry matchEntry = appendEntries.getEntries().get(i);
+                    ReplicatedLogEntry newEntry = context.getReplicatedLog().get(matchEntry.getIndex());
 
                     if (newEntry == null) {
                         //newEntry not found in the log
index 53e47c2f842f17ac0b2766811745a7f1ec6eabde..a50666233c31f30b2e94cbf4c49d53a95cca93f4 100644 (file)
@@ -112,8 +112,8 @@ public class Leader extends AbstractRaftActorBehavior {
         scheduleHeartBeat(new FiniteDuration(0, TimeUnit.SECONDS));
 
         scheduleInstallSnapshotCheck(
-            new FiniteDuration(HEART_BEAT_INTERVAL.length() * 1000,
-                HEART_BEAT_INTERVAL.unit())
+            new FiniteDuration(context.getConfigParams().getHeartBeatInterval().length() * 1000,
+                context.getConfigParams().getHeartBeatInterval().unit())
         );
 
     }
@@ -241,7 +241,7 @@ public class Leader extends AbstractRaftActorBehavior {
                     (InstallSnapshotReply) message);
             }
         } finally {
-            scheduleHeartBeat(HEART_BEAT_INTERVAL);
+            scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
         }
 
         return super.handleMessage(sender, message);
@@ -310,7 +310,7 @@ public class Leader extends AbstractRaftActorBehavior {
                     // that has fallen too far behind with the log but yet is not
                     // eligible to receive a snapshot
                     entries =
-                        context.getReplicatedLog().getFrom(nextIndex);
+                        context.getReplicatedLog().getFrom(nextIndex, 1);
                 }
 
                 followerActor.tell(
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java
new file mode 100644 (file)
index 0000000..9136658
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse 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.raft;
+
+import junit.framework.Assert;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import static org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
+/**
+*
+*/
+public class AbstractReplicatedLogImplTest {
+
+    private MockAbstractReplicatedLogImpl replicatedLogImpl;
+
+    @Before
+    public void setUp() {
+        replicatedLogImpl = new MockAbstractReplicatedLogImpl();
+        // create a set of initial entries in the in-memory log
+        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
+
+    }
+
+    @After
+    public void tearDown() {
+        replicatedLogImpl.journal.clear();
+        replicatedLogImpl.setSnapshotIndex(-1);
+        replicatedLogImpl.setSnapshotTerm(-1);
+        replicatedLogImpl = null;
+    }
+
+    @Test
+    public void testIndexOperations() {
+
+        // check if the values returned are correct, with snapshotIndex = -1
+        assertEquals("B", replicatedLogImpl.get(1).getData().toString());
+        assertEquals("D", replicatedLogImpl.last().getData().toString());
+        assertEquals(3, replicatedLogImpl.lastIndex());
+        assertEquals(2, replicatedLogImpl.lastTerm());
+        assertEquals(2, replicatedLogImpl.getFrom(2).size());
+        assertEquals(4, replicatedLogImpl.size());
+        assertTrue(replicatedLogImpl.isPresent(2));
+        assertFalse(replicatedLogImpl.isPresent(4));
+        assertFalse(replicatedLogImpl.isInSnapshot(2));
+
+        // now create a snapshot of 3 entries, with 1 unapplied entry left in the log
+        // It removes the entries which have made it to snapshot
+        // and updates the snapshot index and term
+        Map state = takeSnapshot(3);
+
+        // check the values after the snapshot.
+        // each index value passed in the test is the logical index (log entry index)
+        // which gets mapped to the list's physical index
+        assertEquals("D", replicatedLogImpl.get(3).getData().toString());
+        assertEquals("D", replicatedLogImpl.last().getData().toString());
+        assertNull(replicatedLogImpl.get(1));
+        assertEquals(3, replicatedLogImpl.lastIndex());
+        assertEquals(2, replicatedLogImpl.lastTerm());
+        assertEquals(0, replicatedLogImpl.getFrom(2).size());
+        assertEquals(1, replicatedLogImpl.size());
+        assertFalse(replicatedLogImpl.isPresent(2));
+        assertTrue(replicatedLogImpl.isPresent(3));
+        assertFalse(replicatedLogImpl.isPresent(4));
+        assertTrue(replicatedLogImpl.isInSnapshot(2));
+
+        // append few more entries
+        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("E")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("F")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(3, 6, new MockPayload("G")));
+        replicatedLogImpl.append(new MockReplicatedLogEntry(3, 7, new MockPayload("H")));
+
+        // check their values as well
+        assertEquals(5, replicatedLogImpl.size());
+        assertEquals("D", replicatedLogImpl.get(3).getData().toString());
+        assertEquals("E", replicatedLogImpl.get(4).getData().toString());
+        assertEquals("H", replicatedLogImpl.last().getData().toString());
+        assertEquals(3, replicatedLogImpl.lastTerm());
+        assertEquals(7, replicatedLogImpl.lastIndex());
+        assertTrue(replicatedLogImpl.isPresent(7));
+        assertFalse(replicatedLogImpl.isInSnapshot(7));
+        assertEquals(1, replicatedLogImpl.getFrom(7).size());
+        assertEquals(2, replicatedLogImpl.getFrom(6).size());
+
+        // take a second snapshot with 5 entries with 0 unapplied entries left in the log
+        state = takeSnapshot(5);
+
+        assertEquals(0, replicatedLogImpl.size());
+        assertNull(replicatedLogImpl.last());
+        assertNull(replicatedLogImpl.get(7));
+        assertNull(replicatedLogImpl.get(1));
+        assertFalse(replicatedLogImpl.isPresent(7));
+        assertTrue(replicatedLogImpl.isInSnapshot(7));
+        assertEquals(0, replicatedLogImpl.getFrom(7).size());
+        assertEquals(0, replicatedLogImpl.getFrom(6).size());
+
+    }
+
+    @Test
+    public void testGetFromWithMax(){
+        List<ReplicatedLogEntry> from = replicatedLogImpl.getFrom(0, 1);
+        Assert.assertEquals(1, from.size());
+        Assert.assertEquals(1, from.get(0).getTerm());
+
+        from = replicatedLogImpl.getFrom(0, 20);
+        Assert.assertEquals(4, from.size());
+        Assert.assertEquals(2, from.get(3).getTerm());
+
+        from = replicatedLogImpl.getFrom(1, 2);
+        Assert.assertEquals(2, from.size());
+        Assert.assertEquals(1, from.get(1).getTerm());
+
+    }
+
+    // create a snapshot for test
+    public Map takeSnapshot(int numEntries) {
+        Map map = new HashMap(numEntries);
+        List<ReplicatedLogEntry> entries = replicatedLogImpl.getEntriesTill(numEntries);
+        for (ReplicatedLogEntry entry : entries) {
+            map.put(entry.getIndex(), entry.getData().toString());
+        }
+
+        int term = (int) replicatedLogImpl.lastTerm();
+        int lastIndex = (int) entries.get(entries.size() - 1).getIndex();
+        entries.clear();
+        replicatedLogImpl.setSnapshotTerm(term);
+        replicatedLogImpl.setSnapshotIndex(lastIndex);
+
+        return map;
+
+    }
+    class MockAbstractReplicatedLogImpl extends AbstractReplicatedLogImpl {
+        @Override
+        public void appendAndPersist(ReplicatedLogEntry replicatedLogEntry) {
+        }
+
+        @Override
+        public void removeFromAndPersist(long index) {
+        }
+
+        public void setSnapshotIndex(long snapshotIndex) {
+            this.snapshotIndex = snapshotIndex;
+        }
+
+        public void setSnapshotTerm(long snapshotTerm) {
+            this.snapshotTerm = snapshotTerm;
+        }
+
+        public List<ReplicatedLogEntry> getEntriesTill(int index) {
+            return journal.subList(0, index);
+        }
+    }
+}
index 2e200cba275d9d4265f56da69ee36e61acd0db76..70671a6a21ab112b339a07b6ab37b4c56c176b47 100644 (file)
@@ -177,7 +177,10 @@ public class MockRaftActorContext implements RaftActorContext {
         this.peerAddresses = peerAddresses;
     }
 
-
+    @Override
+    public ConfigParams getConfigParams() {
+        return new DefaultConfigParamsImpl();
+    }
 
     public static class SimpleReplicatedLog implements ReplicatedLog {
         private final List<ReplicatedLogEntry> log = new ArrayList<>();
@@ -245,6 +248,23 @@ public class MockRaftActorContext implements RaftActorContext {
             return entries;
         }
 
+        @Override public List<ReplicatedLogEntry> getFrom(long index, int max) {
+            if(index >= log.size() || index < 0){
+                return Collections.EMPTY_LIST;
+            }
+            List<ReplicatedLogEntry> entries = new ArrayList<>();
+            int maxIndex = (int) index + max;
+            if(maxIndex > log.size()){
+                maxIndex = log.size();
+            }
+
+            for(int i=(int) index ; i < maxIndex ; i++) {
+                entries.add(get(i));
+            }
+            return entries;
+
+        }
+
         @Override public long size() {
             return log.size();
         }
index c76368370506af15ab4b7b567672514514e41690..d478b175550ba223a778fcf4121f36b9b41fbc1f 100644 (file)
@@ -6,6 +6,7 @@ import akka.testkit.JavaTestKit;
 import junit.framework.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftState;
@@ -80,12 +81,12 @@ public class CandidateTest extends AbstractRaftActorBehaviorTest {
     public void testThatAnElectionTimeoutIsTriggered(){
         new JavaTestKit(getSystem()) {{
 
-            new Within(duration("1 seconds")) {
+            new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
                 protected void run() {
 
                     Candidate candidate = new Candidate(createActorContext(getTestActor()));
 
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "ElectionTimeout") {
+                    final Boolean out = new ExpectMsg<Boolean>(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6), "ElectionTimeout") {
                         // do not put code outside this method, will run afterwards
                         protected Boolean match(Object in) {
                             if (in instanceof ElectionTimeout) {
index c015d950c42055799bdd5826f0cca1aaf398f357..c5a81aa1c9225ea03fa548bf1950d5e73a7e3329 100644 (file)
@@ -5,6 +5,7 @@ import akka.actor.Props;
 import akka.testkit.JavaTestKit;
 import junit.framework.Assert;
 import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftState;
@@ -41,12 +42,12 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
     public void testThatAnElectionTimeoutIsTriggered(){
         new JavaTestKit(getSystem()) {{
 
-            new Within(duration("1 seconds")) {
+            new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
                 protected void run() {
 
                     Follower follower = new Follower(createActorContext(getTestActor()));
 
-                    final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "ElectionTimeout") {
+                    final Boolean out = new ExpectMsg<Boolean>(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6), "ElectionTimeout") {
                         // do not put code outside this method, will run afterwards
                         protected Boolean match(Object in) {
                             if (in instanceof ElectionTimeout) {
index cc85d4337b93d5b1a2322af009052b7c26091bd8..b0c93734e09dba7f964701f4875f10a6f69d297f 100644 (file)
@@ -9,11 +9,12 @@ package org.opendaylight.controller.md.sal.binding.api;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncReadTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 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;
+import com.google.common.util.concurrent.CheckedFuture;
 
 /**
  * A transaction that provides read access to a logical data store.
@@ -33,14 +34,17 @@ public interface ReadTransaction extends AsyncReadTransaction<InstanceIdentifier
      * @param path
      *            Path which uniquely identifies subtree which client want to
      *            read
-     * @return Listenable Future which contains read result
+     * @return a CheckFuture containing the result of the read. The Future blocks until the
+     *         commit operation is complete. Once complete:
      *         <ul>
-     *         <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 ListenbleFuture#get()} returns {@link Optional#absent()}.
+     *         <li>If the data at the supplied path exists, the Future returns an Optional object
+     *         containing the data.</li>
+     *         <li>If the data at the supplied path does not exist, the Future returns
+     *         Optional#absent().</li>
+     *         <li>If the read of the data fails, the Future will fail with a
+     *         {@link ReadFailedException} or an exception derived from ReadFailedException.</li>
      *         </ul>
      */
-    <T extends DataObject> ListenableFuture<Optional<T>> read(LogicalDatastoreType store, InstanceIdentifier<T> path);
+    <T extends DataObject> CheckedFuture<Optional<T>,ReadFailedException> read(
+            LogicalDatastoreType store, InstanceIdentifier<T> path);
 }
index 823a4d9f322fe0b76726e7773bea0267132d45a5..b0c2d742e214046be839cca263dbc0652005aa9b 100644 (file)
@@ -23,7 +23,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
@@ -74,7 +74,7 @@ public final class RuntimeMappingModule extends
         }
 
         final RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(SingletonHolder.CLASS_POOL);
-        bundleContext.registerService(SchemaServiceListener.class, service, new Hashtable<String,String>());
+        bundleContext.registerService(SchemaContextListener.class, service, new Hashtable<String,String>());
         return service;
     }
 
index 15e4a466cf688d67154d8a504cca0c5383d7feea..e632e6336aaf959808a28f9ecc209432c504b4eb 100644 (file)
@@ -41,7 +41,6 @@ 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;
 
@@ -58,14 +57,14 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     private final BindingToNormalizedNodeCodec codec;
     private BindingIndependentConnector connector;
     private ProviderSession context;
-    private final ListenerRegistration<SchemaServiceListener> schemaListenerRegistration;
+    private final ListenerRegistration<SchemaContextListener> schemaListenerRegistration;
 
     protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
             final BindingIndependentMappingService mappingService,final SchemaService schemaService) {
         this.domDataBroker = domDataBroker;
         this.mappingService = mappingService;
         this.codec = new BindingToNormalizedNodeCodec(mappingService);
-        this.schemaListenerRegistration = schemaService.registerSchemaServiceListener(this);
+        this.schemaListenerRegistration = schemaService.registerSchemaContextListener(this);
     }
 
     protected BindingToNormalizedNodeCodec getCodec() {
@@ -98,6 +97,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     }
 
     protected Map<InstanceIdentifier<?>, DataObject> toBinding(
+            InstanceIdentifier<?> path,
             final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
         Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
 
@@ -108,6 +108,11 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
                 if (potential.isPresent()) {
                     Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
                     newMap.put(binding.getKey(), binding.getValue());
+                } else if (entry.getKey().getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                    DataObject bindingDataObject = getCodec().toBinding(path, entry.getValue());
+                    if (bindingDataObject != null) {
+                        newMap.put(path, bindingDataObject);
+                    }
                 }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", entry, e);
@@ -149,7 +154,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         }
     }
 
-    protected Set<InstanceIdentifier<?>> toBinding(
+    protected Set<InstanceIdentifier<?>> toBinding(InstanceIdentifier<?> path,
             final Set<YangInstanceIdentifier> normalized) {
         Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
         for (YangInstanceIdentifier normalizedPath : normalized) {
@@ -158,6 +163,8 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
                 if (potential.isPresent()) {
                     InstanceIdentifier<? extends DataObject> binding = potential.get();
                     hashSet.add(binding);
+                } else if (normalizedPath.getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                    hashSet.add(path);
                 }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", normalizedPath, e);
@@ -220,7 +227,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
             if (createdCache == null) {
-                createdCache = Collections.unmodifiableMap(toBinding(domEvent.getCreatedData()));
+                createdCache = Collections.unmodifiableMap(toBinding(path, domEvent.getCreatedData()));
             }
             return createdCache;
         }
@@ -228,7 +235,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
             if (updatedCache == null) {
-                updatedCache = Collections.unmodifiableMap(toBinding(domEvent.getUpdatedData()));
+                updatedCache = Collections.unmodifiableMap(toBinding(path, domEvent.getUpdatedData()));
             }
             return updatedCache;
 
@@ -237,7 +244,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Set<InstanceIdentifier<?>> getRemovedPaths() {
             if (removedCache == null) {
-                removedCache = Collections.unmodifiableSet(toBinding(domEvent.getRemovedPaths()));
+                removedCache = Collections.unmodifiableSet(toBinding(path, domEvent.getRemovedPaths()));
             }
             return removedCache;
         }
@@ -245,7 +252,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
             if (originalCache == null) {
-                originalCache = Collections.unmodifiableMap(toBinding(domEvent.getOriginalData()));
+                originalCache = Collections.unmodifiableMap(toBinding(path, domEvent.getOriginalData()));
             }
             return originalCache;
 
index e52fcdce23a075dfbc06a79401868d7d88ee3873..96a3f1cc3b7ead386165e1d530d6c2e7b0cccb15 100644 (file)
@@ -9,17 +9,19 @@ package org.opendaylight.controller.md.sal.binding.impl;
 
 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.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
 import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
 
 
 abstract class AbstractForwardedTransaction<T extends AsyncTransaction<YangInstanceIdentifier, NormalizedNode<?, ?>>>
@@ -54,8 +56,13 @@ abstract class AbstractForwardedTransaction<T extends AsyncTransaction<YangInsta
         return codec;
     }
 
-    protected final <T extends DataObject> ListenableFuture<Optional<T>> doRead(final DOMDataReadTransaction readTx,
-            final LogicalDatastoreType store, final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T> path) {
-        return Futures.transform(readTx.read(store, codec.toNormalized(path)), codec.deserializeFunction(path));
+    protected final <T extends DataObject> CheckedFuture<Optional<T>,ReadFailedException> doRead(
+            final DOMDataReadTransaction readTx, final LogicalDatastoreType store,
+            final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T> path) {
+
+        return MappingCheckedFuture.create(
+                    Futures.transform(readTx.read(store, codec.toNormalized(path)),
+                                      codec.deserializeFunction(path)),
+                    ReadFailedException.MAPPER);
     }
 }
index bb942047f23d807aa7b000dd4bcd03862a9f7683..fd0945f1a6c7a8d2ebe6ea7e16b1ad978544893b 100644 (file)
@@ -9,12 +9,13 @@ 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.common.api.data.ReadFailedException;
 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;
+import com.google.common.util.concurrent.CheckedFuture;
 
 class BindingDataReadTransactionImpl extends AbstractForwardedTransaction<DOMDataReadOnlyTransaction> implements
         ReadOnlyTransaction {
@@ -25,8 +26,8 @@ class BindingDataReadTransactionImpl extends AbstractForwardedTransaction<DOMDat
     }
 
     @Override
-    public <T extends DataObject> ListenableFuture<Optional<T>> read(final LogicalDatastoreType store,
-            final InstanceIdentifier<T> path) {
+    public <T extends DataObject> CheckedFuture<Optional<T>,ReadFailedException> read(
+            final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
         return doRead(getDelegate(),store, path);
     }
 
index c8b9d9347a2c79e099f90f72b372482dfdc20c10..a1da029c24760395527f63e1d8238ba941ea6bb9 100644 (file)
@@ -9,12 +9,13 @@ 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.common.api.data.ReadFailedException;
 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;
+import com.google.common.util.concurrent.CheckedFuture;
 
 class BindingDataReadWriteTransactionImpl extends
         BindingDataWriteTransactionImpl<DOMDataReadWriteTransaction> implements ReadWriteTransaction {
@@ -25,8 +26,8 @@ class BindingDataReadWriteTransactionImpl extends
     }
 
     @Override
-    public <T extends DataObject> ListenableFuture<Optional<T>> read(final LogicalDatastoreType store,
-            final InstanceIdentifier<T> path) {
+    public <T extends DataObject> CheckedFuture<Optional<T>,ReadFailedException> read(
+            final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
         return doRead(getDelegate(), store, path);
     }
 }
\ No newline at end of file
index df09f78620a11bcce20f04034e6a7b7cf144780f..05651bfabe5c521d66c25a219fb096b5d9ef0ecb 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.binding.impl;
 
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executors;
 
 import org.opendaylight.controller.md.sal.binding.util.AbstractBindingSalProviderInstance;
 import org.opendaylight.controller.sal.binding.api.mount.MountProviderInstance;
@@ -20,6 +21,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 
 public class MountPointManagerImpl implements MountProviderService {
 
@@ -82,7 +84,7 @@ public class MountPointManagerImpl implements MountProviderService {
         RpcProviderRegistryImpl rpcRegistry = new RpcProviderRegistryImpl("mount");
         NotificationBrokerImpl notificationBroker = new NotificationBrokerImpl(getNotificationExecutor());
         DataBrokerImpl dataBroker = new DataBrokerImpl();
-        dataBroker.setExecutor(getDataCommitExecutor());
+        dataBroker.setExecutor(MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
         BindingMountPointImpl mountInstance = new BindingMountPointImpl(path, rpcRegistry, notificationBroker,
                 dataBroker);
         mountPoints.putIfAbsent(path, mountInstance);
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java
new file mode 100644 (file)
index 0000000..60d56db
--- /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.md.sal.binding.impl.test;
+
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertNotContains;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.USES_ONE_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.USES_TWO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ * This testsuite tries to replicate bug 1333 and tests regresion of it
+ * using test-model with similar construction as one reported.
+ *
+ *
+ * See  https://bugs.opendaylight.org/show_bug.cgi?id=1333 for Bug Description
+ *
+ */
+public class Bug1333DataChangeListenerTest extends AbstractDataChangeListenerTest{
+
+    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+
+    private static final InstanceIdentifier<?> AUGMENT_WILDCARD = TOP_PATH.child(TopLevelList.class).augmentation(
+            TreeComplexUsesAugment.class);
+
+    public void writeTopWithListItem(final LogicalDatastoreType store) {
+        ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+        Top topItem = top(topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
+        tx.put(store, TOP_PATH, topItem);
+        assertCommit(tx.submit());
+    }
+
+    public void deleteItem(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+        tx.delete(store, path);
+        assertCommit(tx.submit());
+    }
+
+    @Test
+    public void writeTopWithListItemAugmentedListenTopSubtree() {
+        TestListener listener = createListener(CONFIGURATION,TOP_PATH, DataChangeScope.SUBTREE);
+        listener.startCapture();
+
+        writeTopWithListItem(CONFIGURATION);
+
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+
+        assertContains(event.getCreatedData(), TOP_PATH);
+        assertContains(event.getCreatedData(), path(TOP_FOO_KEY));
+        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_ONE_KEY));
+        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void writeTopWithListItemAugmentedListenAugmentSubtreeWildcarded() {
+        TestListener listener = createListener(CONFIGURATION,AUGMENT_WILDCARD, DataChangeScope.SUBTREE);
+        listener.startCapture();
+        writeTopWithListItem(CONFIGURATION);
+
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+
+        /*
+         * Event should not contain parent nodes
+         */
+        assertNotContains(event.getCreatedData(), TOP_PATH, path(TOP_FOO_KEY));
+
+        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_ONE_KEY));
+        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void deleteAugmentChildListenTopSubtree() {
+        writeTopWithListItem(CONFIGURATION);
+        TestListener listener = createListener(CONFIGURATION, TOP_PATH, DataChangeScope.SUBTREE);
+        InstanceIdentifier<?> deletePath = path(TOP_FOO_KEY,USES_ONE_KEY);
+        deleteItem(CONFIGURATION,deletePath);
+
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+
+
+        assertEmpty(event.getCreatedData());
+
+        assertContains(event.getRemovedPaths(), deletePath);
+
+        assertContains(event.getUpdatedData(), TOP_PATH);
+        assertContains(event.getUpdatedData(), path(TOP_FOO_KEY));
+        assertContains(event.getUpdatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+
+        assertNotContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+    }
+
+    @Test
+    public void deleteAugmentChildListenAugmentSubtreeWildcarded() {
+        writeTopWithListItem(CONFIGURATION);
+
+        TestListener listener = createListener(CONFIGURATION, AUGMENT_WILDCARD, DataChangeScope.SUBTREE);
+        InstanceIdentifier<?> deletePath = path(TOP_FOO_KEY,USES_ONE_KEY);
+        deleteItem(CONFIGURATION,deletePath);
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+
+        assertEmpty(event.getCreatedData());
+
+        assertContains(event.getUpdatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+
+        /*
+         * Event should not contain parent nodes
+         */
+        assertNotContains(event.getUpdatedData(), TOP_PATH, path(TOP_FOO_KEY));
+
+        assertContains(event.getRemovedPaths(), deletePath);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java
new file mode 100644 (file)
index 0000000..6b5c825
--- /dev/null
@@ -0,0 +1,135 @@
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+
+public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
+    private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
+    private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
+    private static final InstanceIdentifier<TreeLeafOnlyUsesAugment> SIMPLE_AUGMENT =
+            TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeLeafOnlyUsesAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> COMPLEX_AUGMENT =
+            TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeComplexUsesAugment.class);
+    private static final ListViaUsesKey LIST_VIA_USES_KEY =
+            new ListViaUsesKey("list key");
+    private static final ListViaUsesKey LIST_VIA_USES_KEY_MOD =
+            new ListViaUsesKey("list key modified");
+
+    @Test
+    public void leafOnlyAugmentationCreatedTest() {
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getCreatedData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getOriginalData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void leafOnlyAugmentationUpdatedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf changed"));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getUpdatedData(), SIMPLE_AUGMENT);
+        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getCreatedData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void leafOnlyAugmentationDeletedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT);
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getRemovedPaths(), SIMPLE_AUGMENT);
+        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getCreatedData());
+        assertEmpty(event.getUpdatedData());
+    }
+
+    @Test
+    public void complexAugmentationCreatedTest() {
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT);
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getOriginalData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void complexAugmentationUpdatedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY_MOD));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getUpdatedData(), COMPLEX_AUGMENT);
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY_MOD));
+        assertContains(event.getRemovedPaths(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+        assertContains(event.getOriginalData(), COMPLEX_AUGMENT);
+        assertContains(event.getOriginalData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+    }
+}
index 79aa6b634b8b91136c2b7177992fcc028326ce6c..e0f6f3546f528a2e72621447b8110dc9e377be71 100644 (file)
@@ -47,13 +47,13 @@ public class DataBrokerTestCustomizer {
 
     public DOMStore createConfigurationDatastore() {
         InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG", MoreExecutors.sameThreadExecutor());
-        schemaService.registerSchemaServiceListener(store);
+        schemaService.registerSchemaContextListener(store);
         return store;
     }
 
     public DOMStore createOperationalDatastore() {
         InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", MoreExecutors.sameThreadExecutor());
-        schemaService.registerSchemaServiceListener(store);
+        schemaService.registerSchemaContextListener(store);
         return store;
     }
 
index e82c9d385d6592c55982f5a5e59fc3a5249ee749..deb4a8aecacfbcffe47a2cee869c7d117c68f801 100644 (file)
@@ -144,8 +144,8 @@ public class BindingTestContext implements AutoCloseable {
 
         biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker,mockSchemaService);
 
-        mockSchemaService.registerSchemaServiceListener(configStore);
-        mockSchemaService.registerSchemaServiceListener(operStore);
+        mockSchemaService.registerSchemaContextListener(configStore);
+        mockSchemaService.registerSchemaContextListener(operStore);
         biDataLegacyBroker = biCompatibleBroker;
     }
 
@@ -246,7 +246,7 @@ public class BindingTestContext implements AutoCloseable {
     public void startBindingToDomMappingService() {
         checkState(classPool != null, "ClassPool needs to be present");
         mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
-        mockSchemaService.registerSchemaServiceListener(mappingServiceImpl);
+        mockSchemaService.registerSchemaContextListener(mappingServiceImpl);
     }
 
     private void updateYangSchema(final ImmutableSet<YangModuleInfo> moduleInfos) {
index c8acbcd994352d80c85d51c15035fb706af9251d..63a4ffb23a3930d4830ea3e300c168578172c39c 100644 (file)
@@ -13,14 +13,14 @@ 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;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 
 @SuppressWarnings("deprecation")
 public final class MockSchemaService implements SchemaService, SchemaContextProvider {
 
     private SchemaContext schemaContext;
 
-    ListenerRegistry<SchemaServiceListener> listeners = ListenerRegistry.create();
+    ListenerRegistry<SchemaContextListener> listeners = ListenerRegistry.create();
 
     @Override
     public void addModule(final Module module) {
@@ -38,8 +38,8 @@ public final class MockSchemaService implements SchemaService, SchemaContextProv
     }
 
     @Override
-    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(
-            final SchemaServiceListener listener) {
+    public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
+            final SchemaContextListener listener) {
         return listeners.register(listener);
     }
 
@@ -55,8 +55,8 @@ public final class MockSchemaService implements SchemaService, SchemaContextProv
 
     public synchronized void changeSchema(final SchemaContext newContext) {
         schemaContext = newContext;
-        for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+        for (ListenerRegistration<SchemaContextListener> listener : listeners) {
             listener.getInstance().onGlobalContextUpdated(schemaContext);
         }
     }
-}
\ No newline at end of file
+}
index 42d5cfff65e755e29ef2f9198fb6478eabf783d6..7a66c411962285efe2de6514b862f10670b9e296 100644 (file)
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-      <scope>test</scope>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java
deleted file mode 100644 (file)
index 34a71ac..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.test.bugfix;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-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.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-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.CompositeNode;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-@SuppressWarnings("deprecation")
-public class DOMCodecBug01Test extends AbstractDataServiceTest {
-
-    private static final long FLOW_ID = 1234;
-    private static final String NODE_ID = "node:1";
-
-    private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
-
-    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
-            .child(Node.class, NODE_KEY).toInstance();
-
-    private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
-
-    private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
-
-    private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
-    InstanceIdentifier.builder(Flows.class) //
-            .child(Flow.class, FLOW_KEY) //
-            .toInstance();
-
-
-
-    /**
-     *
-     * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=
-     *
-     * Cannot compile CoDec for
-     * org.opendaylight.yang.gen.v1.urn.opendaylight.flow
-     * .config.rev130819.flows.Flow
-     *
-     * When invoking following code in the consumer, user got an
-     * IllegalStateException during creation of mapping between Java DTOs and
-     * data-dom.
-     *
-     * Exception was compilation error which was caused by incorect generation
-     * of code.
-     *
-     * Reported by Depthi V V
-     *
-     * @deprecated This test tests indirect generation, which should be tested
-     *    different way. the test creates conflicting transactions
-     *    and assumes correct commit - to test codec generation
-     *
-     */
-    @Test
-    @Ignore
-    @Deprecated
-    public void testIndirectGeneration() throws Exception {
-
-        ExecutorService basePool = Executors.newFixedThreadPool(2);
-        ListeningExecutorService listenablePool = MoreExecutors.listeningDecorator(basePool);
-
-        createFlow();
-
-        Object lock = new Object();
-        CreateFlowTask task1 = new CreateFlowTask(lock);
-        CreateFlowTask task2 = new CreateFlowTask(lock);
-        CreateFlowTask task3 = new CreateFlowTask(lock);
-
-        ListenableFuture<Void> task1Future = listenablePool.submit(task1);
-        ListenableFuture<Void> task2Future = listenablePool.submit(task2);
-        ListenableFuture<Void> task3Future = listenablePool.submit(task3);
-
-
-        @SuppressWarnings("unchecked")
-        ListenableFuture<List<Void>> compositeFuture = Futures.allAsList(task1Future,task2Future,task3Future);
-
-        Thread.sleep(500);
-        //lock.notifyAll();
-        compositeFuture.get();
-
-        verifyDataAreStoredProperly();
-
-        DataModificationTransaction modification2 = baDataService.beginTransaction();
-        modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
-
-        DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
-        assertNotNull(originalData);
-        RpcResult<TransactionStatus> ret2 = modification2.commit().get();
-
-        assertNotNull(ret2);
-        assertEquals(TransactionStatus.COMMITED, ret2.getResult());
-
-        // Data are not in the store.
-        assertNull(baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA));
-
-    }
-
-    private void createFlow() throws Exception {
-
-        DataModificationTransaction modification = baDataService.beginTransaction();
-
-        FlowBuilder flow = new FlowBuilder();
-        MatchBuilder match = new MatchBuilder();
-        VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
-        VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
-        VlanId vlanId = new VlanId(10);
-        vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build());
-        match.setVlanMatch(vlanBuilder.build());
-
-        flow.setKey(FLOW_KEY);
-        flow.setMatch(match.build());
-        flow.setNode(NODE_REF);
-        InstructionsBuilder instructions = new InstructionsBuilder();
-        InstructionBuilder instruction = new InstructionBuilder();
-
-        instruction.setOrder(10);
-        ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
-        List<Action> actionList = new ArrayList<>();
-        PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
-        popMplsAction.setEthernetType(34);
-        actionList.add(new ActionBuilder().setAction(new PopMplsActionCaseBuilder().setPopMplsAction(popMplsAction.build()).build()).setOrder(10).build());
-
-        applyActions.setAction(actionList );
-
-        instruction.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions.build()).build());
-
-
-        List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
-        instructions.setInstruction(instructionList );
-
-        flow.setInstructions(instructions.build());
-        modification.putConfigurationData(FLOW_INSTANCE_ID_BA, flow.build());
-        RpcResult<TransactionStatus> ret = modification.commit().get();
-        assertNotNull(ret);
-        assertEquals(TransactionStatus.COMMITED, ret.getResult());
-    }
-
-    private void createFlow2() throws Exception {
-        DataModificationTransaction modification = baDataService.beginTransaction();
-        long id = 123;
-        FlowKey key = new FlowKey(id, new NodeRef(NODE_INSTANCE_ID_BA));
-        InstanceIdentifier<?> path1;
-        FlowBuilder flow = new FlowBuilder();
-        flow.setKey(key);
-        MatchBuilder match = new MatchBuilder();
-        match.setLayer4Match(new TcpMatchBuilder().build());
-        flow.setMatch(match.build());
-
-        path1 = InstanceIdentifier.builder(Flows.class).child(Flow.class, key).toInstance();
-       // DataObject cls = (DataObject) modification.readConfigurationData(path1);
-        modification.putConfigurationData(path1, flow.build());
-        modification.commit();
-
-    }
-
-    private class CreateFlowTask implements Callable<Void> {
-
-        public CreateFlowTask(final Object startSync) {
-        }
-
-        @Override
-        public Void call() {
-            try {
-                //startSyncObj          ect.wait();
-                //Thread.sleep(500);
-                createFlow();
-                createFlow2();
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-            return null;
-        }
-    }
-
-    private void verifyDataAreStoredProperly() {
-        CompositeNode biFlows = biDataService.readConfigurationData(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.of(Flows.QNAME));
-        assertNotNull(biFlows);
-        CompositeNode biFlow = biFlows.getFirstCompositeByName(Flow.QNAME);
-        assertNotNull(biFlow);
-    }
-
-
-}
index b8bb891e790f7e905edc071c04e61608d4f277c1..1912462cf0aa5d081ec56166d16b6256e69f7be8 100644 (file)
@@ -8,12 +8,6 @@
   </parent>
   <artifactId>sal-binding-it</artifactId>
 
-  <properties>
-    <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>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-all</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>object-cache-guava</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-manager</artifactId>
       <groupId>org.slf4j</groupId>
       <artifactId>log4j-over-slf4j</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-      <scope>provided</scope>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
             </lifecycleMappingMetadata>
           </configuration>
         </plugin>
-        <plugin>
-          <groupId>org.jacoco</groupId>
-          <artifactId>jacoco-maven-plugin</artifactId>
-          <version>${jacoco.version}</version>
-          <configuration>
-            <destFile>../sal-binding-broker/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>
     </pluginManagement>
     <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <reuseForks>false</reuseForks>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.jacoco</groupId>
-        <artifactId>jacoco-maven-plugin</artifactId>
-        <configuration>
-          <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>
-            <goals>
-              <goal>report</goal>
-            </goals>
-            <phase>test</phase>
-          </execution>
-        </executions>
-      </plugin>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
index c389618f2eb829f2dedb12ec58b0b365f7654ff0..83a69969b7b8c8bd0be90111227bda05cd61fd58 100644 (file)
@@ -30,6 +30,8 @@ public class TestHelper {
                 mavenBundle(YANGTOOLS, "util").versionAsInProject(), // //
                 mavenBundle(YANGTOOLS, "yang-binding").versionAsInProject(), // //
                 mavenBundle(YANGTOOLS, "yang-common").versionAsInProject(), // //
+                mavenBundle(YANGTOOLS, "object-cache-api").versionAsInProject(), // //
+                mavenBundle(YANGTOOLS, "object-cache-guava").versionAsInProject(), // //
                 mavenBundle(CONTROLLER, "sal-common").versionAsInProject(), // //
                 mavenBundle(CONTROLLER, "sal-common-api").versionAsInProject(), // //
                 mavenBundle(CONTROLLER, "sal-common-impl").versionAsInProject(), // //
similarity index 77%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/README-FIRST
rename to opendaylight/md-sal/sal-clustering-commons/README-FIRST
index d0be2cbcbb02cdc4310f130aa25c8e4f25fd386b..4791979c171ba9de3ef2dbf217f99a1a01586c07 100644 (file)
@@ -24,5 +24,9 @@ machine
 
 6. !!!WARNING!!! - never edit the generated sources files of protocol buffer
 
-7. !!!NOTE!!! if you are planning to add new .proto file  option java_package should begin with
+7. !!!IMPORTANT!!! if you are planning to add new .proto file  option java_package should begin with
    org.opendaylight.controller.protobuff.messages to properly exclude from sonar.
+
+8. !!!IMPORTANT!!! for any new .proto file added you need to create corresponding version-compatibility-serialized-data
+   serialized test file under test/resources and a test case for one message in your .proto file.
+   Please follow the instruction in readme.txt in that folder
similarity index 98%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml
rename to opendaylight/md-sal/sal-clustering-commons/pom.xml
index 28e629a92c92fa7b165a390e12e2fd89a15e2ba5..6db4d3a094f43cb80c461418cfd56d54639dd5a2 100644 (file)
@@ -8,7 +8,7 @@
     <version>1.1-SNAPSHOT</version>
   </parent>
 
-  <artifactId>sal-protocolbuffer-encoding</artifactId>
+  <artifactId>sal-clustering-commons</artifactId>
 
   <packaging>bundle</packaging>
 
similarity index 93%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/run.sh
rename to opendaylight/md-sal/sal-clustering-commons/run.sh
index f0907db6648e974298bb399f0956e719cd6e1552..d3d0324fa029e193dd4b36fcec6d34818db07e17 100755 (executable)
@@ -30,7 +30,7 @@
 #   org.opendaylight.controller.protobuff.messages to properly exclude from sonar.
 ########################################################################################################
 
-protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto
+protoc --proto_path=src/main/resources --proto_path=../sal-akka-raft/src/main/resources --java_out=src/main/java src/main/resources/*.proto
 
 echo "Done generating Java source files."
 
@@ -1,3 +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.node;
 
 import com.google.common.base.Preconditions;
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
  *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse 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.node;
@@ -16,7 +18,7 @@ import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.IdentityrefType;
-import org.opendaylight.yangtools.yang.model.util.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
 import org.opendaylight.yangtools.yang.model.util.Leafref;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,7 +57,7 @@ public class NodeValueCodec {
                 return value;
             } else if(baseType instanceof IdentityrefType) {
                 return QNameFactory.create(value);
-            } else if(baseType instanceof InstanceIdentifier) {
+            } else if(baseType instanceof InstanceIdentifierType) {
                 return InstanceIdentifierUtils.fromSerializable(node.getInstanceIdentifierValue());
             } else {
                 logger.error("Could not figure out how to transform value " + value +  " for schemaType " + type);
@@ -1,3 +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.node;
 
 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
@@ -1,3 +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.node;
 
 import com.google.common.base.Preconditions;
@@ -1,3 +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.node.utils;
 
 import org.opendaylight.yangtools.yang.common.QName;
@@ -1,3 +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.node.utils;
 
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -1,3 +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.node.utils;
 
 import org.opendaylight.yangtools.yang.common.QName;
@@ -1,3 +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.node.utils;
 
 import org.opendaylight.yangtools.yang.common.QName;
@@ -1,3 +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.node.utils;
 
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -1,3 +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.node.utils;
 
 import com.google.common.base.Preconditions;
@@ -1,3 +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.node.utils;
 
 import com.google.common.base.Preconditions;
@@ -1,3 +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.node.utils;
 
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java
new file mode 100644 (file)
index 0000000..9e85ccb
--- /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.node.utils;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface NormalizedNodeVisitor {
+    public void visitNode(int level, String parentPath, NormalizedNode normalizedNode);
+}
@@ -1,3 +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.node.utils;
 
 public class PathUtils {
@@ -1,3 +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.node.utils;
 
 import org.opendaylight.yangtools.yang.common.QName;
@@ -1,3 +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.util;
 
 import com.google.common.base.Preconditions;
@@ -44,13 +54,6 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the terms of the Eclipse
- * Public License v1.0 which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
 /*
  *
  * <code>EncoderDecoderUtil</code> helps in wrapping the NormalizedNode into a SimpleNormalizedNode
@@ -1,3 +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.util;
 
 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
@@ -179,7 +179,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -195,7 +195,7 @@ public final class NormalizedNodeMessages {
         getNameBytes() {
       java.lang.Object ref = name_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         name_ = b;
@@ -222,7 +222,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -238,7 +238,7 @@ public final class NormalizedNodeMessages {
         getValueBytes() {
       java.lang.Object ref = value_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         value_ = b;
@@ -265,7 +265,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -281,7 +281,7 @@ public final class NormalizedNodeMessages {
         getTypeBytes() {
       java.lang.Object ref = type_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         type_ = b;
@@ -541,7 +541,7 @@ public final class NormalizedNodeMessages {
 
       public final boolean isInitialized() {
         if (!hasName()) {
-          
+
           return false;
         }
         return true;
@@ -595,7 +595,7 @@ public final class NormalizedNodeMessages {
           getNameBytes() {
         java.lang.Object ref = name_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           name_ = b;
@@ -669,7 +669,7 @@ public final class NormalizedNodeMessages {
           getValueBytes() {
         java.lang.Object ref = value_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           value_ = b;
@@ -743,7 +743,7 @@ public final class NormalizedNodeMessages {
           getTypeBytes() {
         java.lang.Object ref = type_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           type_ = b;
@@ -930,7 +930,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -946,7 +946,7 @@ public final class NormalizedNodeMessages {
         getValueBytes() {
       java.lang.Object ref = value_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         value_ = b;
@@ -1168,7 +1168,7 @@ public final class NormalizedNodeMessages {
 
       public final boolean isInitialized() {
         if (!hasValue()) {
-          
+
           return false;
         }
         return true;
@@ -1222,7 +1222,7 @@ public final class NormalizedNodeMessages {
           getValueBytes() {
         java.lang.Object ref = value_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           value_ = b;
@@ -1341,7 +1341,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
      */
-    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>
         getAttributesList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
@@ -1354,7 +1354,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
@@ -1504,7 +1504,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1520,7 +1520,7 @@ public final class NormalizedNodeMessages {
         getValueBytes() {
       java.lang.Object ref = value_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         value_ = b;
@@ -1555,7 +1555,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1575,7 +1575,7 @@ public final class NormalizedNodeMessages {
         getTypeBytes() {
       java.lang.Object ref = type_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         type_ = b;
@@ -1619,7 +1619,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList() {
       return attributes_;
     }
@@ -1948,7 +1948,7 @@ public final class NormalizedNodeMessages {
               attributesBuilder_ = null;
               attributes_ = other.attributes_;
               bitField0_ = (bitField0_ & ~0x00000008);
-              attributesBuilder_ = 
+              attributesBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getAttributesFieldBuilder() : null;
             } else {
@@ -1962,18 +1962,18 @@ public final class NormalizedNodeMessages {
 
       public final boolean isInitialized() {
         if (!hasValue()) {
-          
+
           return false;
         }
         if (hasNodeType()) {
           if (!getNodeType().isInitialized()) {
-            
+
             return false;
           }
         }
         for (int i = 0; i < getAttributesCount(); i++) {
           if (!getAttributes(i).isInitialized()) {
-            
+
             return false;
           }
         }
@@ -2028,7 +2028,7 @@ public final class NormalizedNodeMessages {
           getValueBytes() {
         java.lang.Object ref = value_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           value_ = b;
@@ -2114,7 +2114,7 @@ public final class NormalizedNodeMessages {
           getTypeBytes() {
         java.lang.Object ref = type_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           type_ = b;
@@ -2275,7 +2275,7 @@ public final class NormalizedNodeMessages {
        * <code>optional .org.opendaylight.controller.mdsal.QName nodeType = 3;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>
           getNodeTypeFieldBuilder() {
         if (nodeTypeBuilder_ == null) {
           nodeTypeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -2483,7 +2483,7 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
            getAttributesOrBuilderList() {
         if (attributesBuilder_ != null) {
           return attributesBuilder_.getMessageOrBuilderList();
@@ -2509,12 +2509,12 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;</code>
        */
-      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder>
            getAttributesBuilderList() {
         return getAttributesFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
           getAttributesFieldBuilder() {
         if (attributesBuilder_ == null) {
           attributesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -2546,7 +2546,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;</code>
      */
-    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument>
         getArgumentsList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;</code>
@@ -2559,7 +2559,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
         getArgumentsOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;</code>
@@ -2680,7 +2680,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
         getArgumentsOrBuilderList() {
       return arguments_;
     }
@@ -2933,7 +2933,7 @@ public final class NormalizedNodeMessages {
               argumentsBuilder_ = null;
               arguments_ = other.arguments_;
               bitField0_ = (bitField0_ & ~0x00000001);
-              argumentsBuilder_ = 
+              argumentsBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getArgumentsFieldBuilder() : null;
             } else {
@@ -2948,7 +2948,7 @@ public final class NormalizedNodeMessages {
       public final boolean isInitialized() {
         for (int i = 0; i < getArgumentsCount(); i++) {
           if (!getArguments(i).isInitialized()) {
-            
+
             return false;
           }
         }
@@ -3169,7 +3169,7 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
            getArgumentsOrBuilderList() {
         if (argumentsBuilder_ != null) {
           return argumentsBuilder_.getMessageOrBuilderList();
@@ -3195,12 +3195,12 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;</code>
        */
-      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder>
            getArgumentsBuilderList() {
         return getArgumentsFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
           getArgumentsFieldBuilder() {
         if (argumentsBuilder_ == null) {
           argumentsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -3262,7 +3262,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
      */
-    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute>
         getAttributesList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
@@ -3275,7 +3275,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
@@ -3287,7 +3287,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
      */
-    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node>
         getChildList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
@@ -3300,7 +3300,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
         getChildOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
@@ -3546,7 +3546,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -3562,7 +3562,7 @@ public final class NormalizedNodeMessages {
         getPathBytes() {
       java.lang.Object ref = path_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         path_ = b;
@@ -3589,7 +3589,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -3605,7 +3605,7 @@ public final class NormalizedNodeMessages {
         getTypeBytes() {
       java.lang.Object ref = type_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         type_ = b;
@@ -3627,7 +3627,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
         getAttributesOrBuilderList() {
       return attributes_;
     }
@@ -3663,7 +3663,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
         getChildOrBuilderList() {
       return child_;
     }
@@ -3704,7 +3704,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -3720,7 +3720,7 @@ public final class NormalizedNodeMessages {
         getValueBytes() {
       java.lang.Object ref = value_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         value_ = b;
@@ -3747,7 +3747,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -3763,7 +3763,7 @@ public final class NormalizedNodeMessages {
         getValueTypeBytes() {
       java.lang.Object ref = valueType_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         valueType_ = b;
@@ -4202,7 +4202,7 @@ public final class NormalizedNodeMessages {
               attributesBuilder_ = null;
               attributes_ = other.attributes_;
               bitField0_ = (bitField0_ & ~0x00000004);
-              attributesBuilder_ = 
+              attributesBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getAttributesFieldBuilder() : null;
             } else {
@@ -4228,7 +4228,7 @@ public final class NormalizedNodeMessages {
               childBuilder_ = null;
               child_ = other.child_;
               bitField0_ = (bitField0_ & ~0x00000008);
-              childBuilder_ = 
+              childBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getChildFieldBuilder() : null;
             } else {
@@ -4266,19 +4266,19 @@ public final class NormalizedNodeMessages {
       public final boolean isInitialized() {
         for (int i = 0; i < getAttributesCount(); i++) {
           if (!getAttributes(i).isInitialized()) {
-            
+
             return false;
           }
         }
         for (int i = 0; i < getChildCount(); i++) {
           if (!getChild(i).isInitialized()) {
-            
+
             return false;
           }
         }
         if (hasInstanceIdentifierValue()) {
           if (!getInstanceIdentifierValue().isInitialized()) {
-            
+
             return false;
           }
         }
@@ -4333,7 +4333,7 @@ public final class NormalizedNodeMessages {
           getPathBytes() {
         java.lang.Object ref = path_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           path_ = b;
@@ -4407,7 +4407,7 @@ public final class NormalizedNodeMessages {
           getTypeBytes() {
         java.lang.Object ref = type_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           type_ = b;
@@ -4647,7 +4647,7 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
            getAttributesOrBuilderList() {
         if (attributesBuilder_ != null) {
           return attributesBuilder_.getMessageOrBuilderList();
@@ -4673,12 +4673,12 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;</code>
        */
-      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder>
            getAttributesBuilderList() {
         return getAttributesFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
           getAttributesFieldBuilder() {
         if (attributesBuilder_ == null) {
           attributesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -4887,7 +4887,7 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
            getChildOrBuilderList() {
         if (childBuilder_ != null) {
           return childBuilder_.getMessageOrBuilderList();
@@ -4913,12 +4913,12 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Node child = 4;</code>
        */
-      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder>
            getChildBuilderList() {
         return getChildFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getChildFieldBuilder() {
         if (childBuilder_ == null) {
           childBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -4961,7 +4961,7 @@ public final class NormalizedNodeMessages {
           getValueBytes() {
         java.lang.Object ref = value_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           value_ = b;
@@ -5035,7 +5035,7 @@ public final class NormalizedNodeMessages {
           getValueTypeBytes() {
         java.lang.Object ref = valueType_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           valueType_ = b;
@@ -5277,7 +5277,7 @@ public final class NormalizedNodeMessages {
        * <code>optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierValueFieldBuilder() {
         if (instanceIdentifierValueBuilder_ == null) {
           instanceIdentifierValueBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -5459,7 +5459,7 @@ public final class NormalizedNodeMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -5475,7 +5475,7 @@ public final class NormalizedNodeMessages {
         getParentPathBytes() {
       java.lang.Object ref = parentPath_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         parentPath_ = b;
@@ -5751,12 +5751,12 @@ public final class NormalizedNodeMessages {
 
       public final boolean isInitialized() {
         if (!hasParentPath()) {
-          
+
           return false;
         }
         if (hasNormalizedNode()) {
           if (!getNormalizedNode().isInitialized()) {
-            
+
             return false;
           }
         }
@@ -5811,7 +5811,7 @@ public final class NormalizedNodeMessages {
           getParentPathBytes() {
         java.lang.Object ref = parentPath_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           parentPath_ = b;
@@ -5960,7 +5960,7 @@ public final class NormalizedNodeMessages {
        * <code>optional .org.opendaylight.controller.mdsal.Node normalizedNode = 2;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getNormalizedNodeFieldBuilder() {
         if (normalizedNodeBuilder_ == null) {
           normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6431,16 +6431,16 @@ public final class NormalizedNodeMessages {
 
       public final boolean isInitialized() {
         if (!hasInstanceIdentifierPath()) {
-          
+
           return false;
         }
         if (!getInstanceIdentifierPath().isInitialized()) {
-          
+
           return false;
         }
         if (hasNormalizedNode()) {
           if (!getNormalizedNode().isInitialized()) {
-            
+
             return false;
           }
         }
@@ -6570,7 +6570,7 @@ public final class NormalizedNodeMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPath = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierPathFieldBuilder() {
         if (instanceIdentifierPathBuilder_ == null) {
           instanceIdentifierPathBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6687,7 +6687,7 @@ public final class NormalizedNodeMessages {
        * <code>optional .org.opendaylight.controller.mdsal.Node normalizedNode = 2;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getNormalizedNodeFieldBuilder() {
         if (normalizedNodeBuilder_ == null) {
           normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6718,7 +6718,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;</code>
      */
-    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry>
         getMapEntriesList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;</code>
@@ -6731,7 +6731,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
         getMapEntriesOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;</code>
@@ -6852,7 +6852,7 @@ public final class NormalizedNodeMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
         getMapEntriesOrBuilderList() {
       return mapEntries_;
     }
@@ -7105,7 +7105,7 @@ public final class NormalizedNodeMessages {
               mapEntriesBuilder_ = null;
               mapEntries_ = other.mapEntries_;
               bitField0_ = (bitField0_ & ~0x00000001);
-              mapEntriesBuilder_ = 
+              mapEntriesBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getMapEntriesFieldBuilder() : null;
             } else {
@@ -7120,7 +7120,7 @@ public final class NormalizedNodeMessages {
       public final boolean isInitialized() {
         for (int i = 0; i < getMapEntriesCount(); i++) {
           if (!getMapEntries(i).isInitialized()) {
-            
+
             return false;
           }
         }
@@ -7341,7 +7341,7 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
            getMapEntriesOrBuilderList() {
         if (mapEntriesBuilder_ != null) {
           return mapEntriesBuilder_.getMessageOrBuilderList();
@@ -7367,12 +7367,12 @@ public final class NormalizedNodeMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;</code>
        */
-      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry.Builder>
            getMapEntriesBuilderList() {
         return getMapEntriesFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
           getMapEntriesFieldBuilder() {
         if (mapEntriesBuilder_ == null) {
           mapEntriesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -159,7 +159,7 @@ public final class SimpleNormalizedNodeMessage {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -175,7 +175,7 @@ public final class SimpleNormalizedNodeMessage {
         getNodeIdentifierBytes() {
       java.lang.Object ref = nodeIdentifier_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         nodeIdentifier_ = b;
@@ -202,7 +202,7 @@ public final class SimpleNormalizedNodeMessage {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -218,7 +218,7 @@ public final class SimpleNormalizedNodeMessage {
         getXmlStringBytes() {
       java.lang.Object ref = xmlString_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         xmlString_ = b;
@@ -463,11 +463,11 @@ public final class SimpleNormalizedNodeMessage {
 
       public final boolean isInitialized() {
         if (!hasNodeIdentifier()) {
-          
+
           return false;
         }
         if (!hasXmlString()) {
-          
+
           return false;
         }
         return true;
@@ -521,7 +521,7 @@ public final class SimpleNormalizedNodeMessage {
           getNodeIdentifierBytes() {
         java.lang.Object ref = nodeIdentifier_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           nodeIdentifier_ = b;
@@ -595,7 +595,7 @@ public final class SimpleNormalizedNodeMessage {
           getXmlStringBytes() {
         java.lang.Object ref = xmlString_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           xmlString_ = b;
@@ -85,7 +85,7 @@ public final class DataChangeListenerMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;</code>
      */
-    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier>
         getRemovedPathsList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;</code>
@@ -98,7 +98,7 @@ public final class DataChangeListenerMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
         getRemovedPathsOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;</code>
@@ -395,7 +395,7 @@ public final class DataChangeListenerMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
         getRemovedPathsOrBuilderList() {
       return removedPaths_;
     }
@@ -810,7 +810,7 @@ public final class DataChangeListenerMessages {
               removedPathsBuilder_ = null;
               removedPaths_ = other.removedPaths_;
               bitField0_ = (bitField0_ & ~0x00000020);
-              removedPathsBuilder_ = 
+              removedPathsBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getRemovedPathsFieldBuilder() : null;
             } else {
@@ -825,37 +825,37 @@ public final class DataChangeListenerMessages {
       public final boolean isInitialized() {
         if (hasOriginalSubTree()) {
           if (!getOriginalSubTree().isInitialized()) {
-            
+
             return false;
           }
         }
         if (hasUpdatedSubTree()) {
           if (!getUpdatedSubTree().isInitialized()) {
-            
+
             return false;
           }
         }
         if (hasOriginalData()) {
           if (!getOriginalData().isInitialized()) {
-            
+
             return false;
           }
         }
         if (hasUpdatedData()) {
           if (!getUpdatedData().isInitialized()) {
-            
+
             return false;
           }
         }
         if (hasCreatedData()) {
           if (!getCreatedData().isInitialized()) {
-            
+
             return false;
           }
         }
         for (int i = 0; i < getRemovedPathsCount(); i++) {
           if (!getRemovedPaths(i).isInitialized()) {
-            
+
             return false;
           }
         }
@@ -985,7 +985,7 @@ public final class DataChangeListenerMessages {
        * <code>optional .org.opendaylight.controller.mdsal.Node originalSubTree = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getOriginalSubTreeFieldBuilder() {
         if (originalSubTreeBuilder_ == null) {
           originalSubTreeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1102,7 +1102,7 @@ public final class DataChangeListenerMessages {
        * <code>optional .org.opendaylight.controller.mdsal.Node updatedSubTree = 2;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getUpdatedSubTreeFieldBuilder() {
         if (updatedSubTreeBuilder_ == null) {
           updatedSubTreeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1219,7 +1219,7 @@ public final class DataChangeListenerMessages {
        * <code>optional .org.opendaylight.controller.mdsal.NodeMap originalData = 3;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
           getOriginalDataFieldBuilder() {
         if (originalDataBuilder_ == null) {
           originalDataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1336,7 +1336,7 @@ public final class DataChangeListenerMessages {
        * <code>optional .org.opendaylight.controller.mdsal.NodeMap updatedData = 4;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
           getUpdatedDataFieldBuilder() {
         if (updatedDataBuilder_ == null) {
           updatedDataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1453,7 +1453,7 @@ public final class DataChangeListenerMessages {
        * <code>optional .org.opendaylight.controller.mdsal.NodeMap createdData = 5;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
           getCreatedDataFieldBuilder() {
         if (createdDataBuilder_ == null) {
           createdDataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1661,7 +1661,7 @@ public final class DataChangeListenerMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
            getRemovedPathsOrBuilderList() {
         if (removedPathsBuilder_ != null) {
           return removedPathsBuilder_.getMessageOrBuilderList();
@@ -1687,12 +1687,12 @@ public final class DataChangeListenerMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;</code>
        */
-      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder>
            getRemovedPathsBuilderList() {
         return getRemovedPathsFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getRemovedPathsFieldBuilder() {
         if (removedPathsBuilder_ == null) {
           removedPathsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -193,7 +193,7 @@ public final class PersistentMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -209,7 +209,7 @@ public final class PersistentMessages {
         getTypeBytes() {
       java.lang.Object ref = type_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         type_ = b;
@@ -541,20 +541,20 @@ public final class PersistentMessages {
 
       public final boolean isInitialized() {
         if (!hasType()) {
-          
+
           return false;
         }
         if (!hasPath()) {
-          
+
           return false;
         }
         if (!getPath().isInitialized()) {
-          
+
           return false;
         }
         if (hasData()) {
           if (!getData().isInitialized()) {
-            
+
             return false;
           }
         }
@@ -609,7 +609,7 @@ public final class PersistentMessages {
           getTypeBytes() {
         java.lang.Object ref = type_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           type_ = b;
@@ -758,7 +758,7 @@ public final class PersistentMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier path = 2;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getPathFieldBuilder() {
         if (pathBuilder_ == null) {
           pathBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -875,7 +875,7 @@ public final class PersistentMessages {
        * <code>optional .org.opendaylight.controller.mdsal.Node data = 3;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getDataFieldBuilder() {
         if (dataBuilder_ == null) {
           dataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -906,7 +906,7 @@ public final class PersistentMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Modification modification = 1;</code>
      */
-    java.util.List<org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification> 
+    java.util.List<org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification>
         getModificationList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Modification modification = 1;</code>
@@ -919,7 +919,7 @@ public final class PersistentMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Modification modification = 1;</code>
      */
-    java.util.List<? extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder> 
+    java.util.List<? extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
         getModificationOrBuilderList();
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Modification modification = 1;</code>
@@ -1040,7 +1040,7 @@ public final class PersistentMessages {
     /**
      * <code>repeated .org.opendaylight.controller.mdsal.Modification modification = 1;</code>
      */
-    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder> 
+    public java.util.List<? extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
         getModificationOrBuilderList() {
       return modification_;
     }
@@ -1293,7 +1293,7 @@ public final class PersistentMessages {
               modificationBuilder_ = null;
               modification_ = other.modification_;
               bitField0_ = (bitField0_ & ~0x00000001);
-              modificationBuilder_ = 
+              modificationBuilder_ =
                 com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                    getModificationFieldBuilder() : null;
             } else {
@@ -1308,7 +1308,7 @@ public final class PersistentMessages {
       public final boolean isInitialized() {
         for (int i = 0; i < getModificationCount(); i++) {
           if (!getModification(i).isInitialized()) {
-            
+
             return false;
           }
         }
@@ -1529,7 +1529,7 @@ public final class PersistentMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Modification modification = 1;</code>
        */
-      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder> 
+      public java.util.List<? extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
            getModificationOrBuilderList() {
         if (modificationBuilder_ != null) {
           return modificationBuilder_.getMessageOrBuilderList();
@@ -1555,12 +1555,12 @@ public final class PersistentMessages {
       /**
        * <code>repeated .org.opendaylight.controller.mdsal.Modification modification = 1;</code>
        */
-      public java.util.List<org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification.Builder> 
+      public java.util.List<org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification.Builder>
            getModificationBuilderList() {
         return getModificationFieldBuilder().getBuilderList();
       }
       private com.google.protobuf.RepeatedFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification.Builder, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification.Builder, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
           getModificationFieldBuilder() {
         if (modificationBuilder_ == null) {
           modificationBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -837,7 +837,7 @@ public final class ListenerRegistrationMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -853,7 +853,7 @@ public final class ListenerRegistrationMessages {
         getDataChangeListenerActorPathBytes() {
       java.lang.Object ref = dataChangeListenerActorPath_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         dataChangeListenerActorPath_ = b;
@@ -1146,19 +1146,19 @@ public final class ListenerRegistrationMessages {
 
       public final boolean isInitialized() {
         if (!hasInstanceIdentifierPath()) {
-          
+
           return false;
         }
         if (!hasDataChangeListenerActorPath()) {
-          
+
           return false;
         }
         if (!hasDataChangeScope()) {
-          
+
           return false;
         }
         if (!getInstanceIdentifierPath().isInitialized()) {
-          
+
           return false;
         }
         return true;
@@ -1287,7 +1287,7 @@ public final class ListenerRegistrationMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPath = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierPathFieldBuilder() {
         if (instanceIdentifierPathBuilder_ == null) {
           instanceIdentifierPathBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1329,7 +1329,7 @@ public final class ListenerRegistrationMessages {
           getDataChangeListenerActorPathBytes() {
         java.lang.Object ref = dataChangeListenerActorPath_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           dataChangeListenerActorPath_ = b;
@@ -1556,7 +1556,7 @@ public final class ListenerRegistrationMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1572,7 +1572,7 @@ public final class ListenerRegistrationMessages {
         getListenerRegistrationPathBytes() {
       java.lang.Object ref = listenerRegistrationPath_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         listenerRegistrationPath_ = b;
@@ -1801,7 +1801,7 @@ public final class ListenerRegistrationMessages {
 
       public final boolean isInitialized() {
         if (!hasListenerRegistrationPath()) {
-          
+
           return false;
         }
         return true;
@@ -1855,7 +1855,7 @@ public final class ListenerRegistrationMessages {
           getListenerRegistrationPathBytes() {
         java.lang.Object ref = listenerRegistrationPath_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           listenerRegistrationPath_ = b;
@@ -139,7 +139,7 @@ public final class ShardManagerMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -155,7 +155,7 @@ public final class ShardManagerMessages {
         getShardNameBytes() {
       java.lang.Object ref = shardName_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         shardName_ = b;
@@ -377,7 +377,7 @@ public final class ShardManagerMessages {
 
       public final boolean isInitialized() {
         if (!hasShardName()) {
-          
+
           return false;
         }
         return true;
@@ -431,7 +431,7 @@ public final class ShardManagerMessages {
           getShardNameBytes() {
         java.lang.Object ref = shardName_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           shardName_ = b;
@@ -618,7 +618,7 @@ public final class ShardManagerMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -634,7 +634,7 @@ public final class ShardManagerMessages {
         getPrimaryPathBytes() {
       java.lang.Object ref = primaryPath_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         primaryPath_ = b;
@@ -856,7 +856,7 @@ public final class ShardManagerMessages {
 
       public final boolean isInitialized() {
         if (!hasPrimaryPath()) {
-          
+
           return false;
         }
         return true;
@@ -910,7 +910,7 @@ public final class ShardManagerMessages {
           getPrimaryPathBytes() {
         java.lang.Object ref = primaryPath_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           primaryPath_ = b;
@@ -1097,7 +1097,7 @@ public final class ShardManagerMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1113,7 +1113,7 @@ public final class ShardManagerMessages {
         getShardNameBytes() {
       java.lang.Object ref = shardName_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         shardName_ = b;
@@ -1335,7 +1335,7 @@ public final class ShardManagerMessages {
 
       public final boolean isInitialized() {
         if (!hasShardName()) {
-          
+
           return false;
         }
         return true;
@@ -1389,7 +1389,7 @@ public final class ShardManagerMessages {
           getShardNameBytes() {
         java.lang.Object ref = shardName_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           shardName_ = b;
@@ -1066,7 +1066,7 @@ public final class ShardTransactionChainMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1082,7 +1082,7 @@ public final class ShardTransactionChainMessages {
         getTransactionChainPathBytes() {
       java.lang.Object ref = transactionChainPath_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         transactionChainPath_ = b;
@@ -1304,7 +1304,7 @@ public final class ShardTransactionChainMessages {
 
       public final boolean isInitialized() {
         if (!hasTransactionChainPath()) {
-          
+
           return false;
         }
         return true;
@@ -1358,7 +1358,7 @@ public final class ShardTransactionChainMessages {
           getTransactionChainPathBytes() {
         java.lang.Object ref = transactionChainPath_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           transactionChainPath_ = b;
@@ -643,6 +643,16 @@ public final class ShardTransactionMessages {
      */
     com.google.protobuf.ByteString
         getTransactionIdBytes();
+
+    // required int32 transactionType = 2;
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    boolean hasTransactionType();
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    int getTransactionType();
   }
   /**
    * Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransaction}
@@ -700,6 +710,11 @@ public final class ShardTransactionMessages {
               transactionId_ = input.readBytes();
               break;
             }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              transactionType_ = input.readInt32();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -757,7 +772,7 @@ public final class ShardTransactionMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -773,7 +788,7 @@ public final class ShardTransactionMessages {
         getTransactionIdBytes() {
       java.lang.Object ref = transactionId_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         transactionId_ = b;
@@ -783,8 +798,25 @@ public final class ShardTransactionMessages {
       }
     }
 
+    // required int32 transactionType = 2;
+    public static final int TRANSACTIONTYPE_FIELD_NUMBER = 2;
+    private int transactionType_;
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    public boolean hasTransactionType() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required int32 transactionType = 2;</code>
+     */
+    public int getTransactionType() {
+      return transactionType_;
+    }
+
     private void initFields() {
       transactionId_ = "";
+      transactionType_ = 0;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -795,6 +827,10 @@ public final class ShardTransactionMessages {
         memoizedIsInitialized = 0;
         return false;
       }
+      if (!hasTransactionType()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
       memoizedIsInitialized = 1;
       return true;
     }
@@ -805,6 +841,9 @@ public final class ShardTransactionMessages {
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         output.writeBytes(1, getTransactionIdBytes());
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt32(2, transactionType_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -818,6 +857,10 @@ public final class ShardTransactionMessages {
         size += com.google.protobuf.CodedOutputStream
           .computeBytesSize(1, getTransactionIdBytes());
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(2, transactionType_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -936,6 +979,8 @@ public final class ShardTransactionMessages {
         super.clear();
         transactionId_ = "";
         bitField0_ = (bitField0_ & ~0x00000001);
+        transactionType_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000002);
         return this;
       }
 
@@ -968,6 +1013,10 @@ public final class ShardTransactionMessages {
           to_bitField0_ |= 0x00000001;
         }
         result.transactionId_ = transactionId_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.transactionType_ = transactionType_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -989,13 +1038,20 @@ public final class ShardTransactionMessages {
           transactionId_ = other.transactionId_;
           onChanged();
         }
+        if (other.hasTransactionType()) {
+          setTransactionType(other.getTransactionType());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
         if (!hasTransactionId()) {
-          
+
+          return false;
+        }
+        if (!hasTransactionType()) {
+
           return false;
         }
         return true;
@@ -1049,7 +1105,7 @@ public final class ShardTransactionMessages {
           getTransactionIdBytes() {
         java.lang.Object ref = transactionId_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           transactionId_ = b;
@@ -1094,6 +1150,39 @@ public final class ShardTransactionMessages {
         return this;
       }
 
+      // required int32 transactionType = 2;
+      private int transactionType_ ;
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public boolean hasTransactionType() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public int getTransactionType() {
+        return transactionType_;
+      }
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public Builder setTransactionType(int value) {
+        bitField0_ |= 0x00000002;
+        transactionType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int32 transactionType = 2;</code>
+       */
+      public Builder clearTransactionType() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        transactionType_ = 0;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CreateTransaction)
     }
 
@@ -1256,7 +1345,7 @@ public final class ShardTransactionMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1272,7 +1361,7 @@ public final class ShardTransactionMessages {
         getTransactionActorPathBytes() {
       java.lang.Object ref = transactionActorPath_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         transactionActorPath_ = b;
@@ -1299,7 +1388,7 @@ public final class ShardTransactionMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -1315,7 +1404,7 @@ public final class ShardTransactionMessages {
         getTransactionIdBytes() {
       java.lang.Object ref = transactionId_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         transactionId_ = b;
@@ -1560,11 +1649,11 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasTransactionActorPath()) {
-          
+
           return false;
         }
         if (!hasTransactionId()) {
-          
+
           return false;
         }
         return true;
@@ -1618,7 +1707,7 @@ public final class ShardTransactionMessages {
           getTransactionActorPathBytes() {
         java.lang.Object ref = transactionActorPath_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           transactionActorPath_ = b;
@@ -1692,7 +1781,7 @@ public final class ShardTransactionMessages {
           getTransactionIdBytes() {
         java.lang.Object ref = transactionId_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           transactionId_ = b;
@@ -2188,7 +2277,7 @@ public final class ShardTransactionMessages {
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
-        com.google.protobuf.ByteString bs = 
+        com.google.protobuf.ByteString bs =
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
@@ -2204,7 +2293,7 @@ public final class ShardTransactionMessages {
         getActorPathBytes() {
       java.lang.Object ref = actorPath_;
       if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
+        com.google.protobuf.ByteString b =
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
         actorPath_ = b;
@@ -2426,7 +2515,7 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasActorPath()) {
-          
+
           return false;
         }
         return true;
@@ -2480,7 +2569,7 @@ public final class ShardTransactionMessages {
           getActorPathBytes() {
         java.lang.Object ref = actorPath_;
         if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString b =
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
           actorPath_ = b;
@@ -2902,11 +2991,11 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasInstanceIdentifierPathArguments()) {
-          
+
           return false;
         }
         if (!getInstanceIdentifierPathArguments().isInitialized()) {
-          
+
           return false;
         }
         return true;
@@ -3035,7 +3124,7 @@ public final class ShardTransactionMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierPathArgumentsFieldBuilder() {
         if (instanceIdentifierPathArgumentsBuilder_ == null) {
           instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -3734,11 +3823,11 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasInstanceIdentifierPathArguments()) {
-          
+
           return false;
         }
         if (!getInstanceIdentifierPathArguments().isInitialized()) {
-          
+
           return false;
         }
         return true;
@@ -3867,7 +3956,7 @@ public final class ShardTransactionMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierPathArgumentsFieldBuilder() {
         if (instanceIdentifierPathArgumentsBuilder_ == null) {
           instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -4256,7 +4345,7 @@ public final class ShardTransactionMessages {
       public final boolean isInitialized() {
         if (hasNormalizedNode()) {
           if (!getNormalizedNode().isInitialized()) {
-            
+
             return false;
           }
         }
@@ -4386,7 +4475,7 @@ public final class ShardTransactionMessages {
        * <code>optional .org.opendaylight.controller.mdsal.Node normalizedNode = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getNormalizedNodeFieldBuilder() {
         if (normalizedNodeBuilder_ == null) {
           normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -4859,19 +4948,19 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasInstanceIdentifierPathArguments()) {
-          
+
           return false;
         }
         if (!hasNormalizedNode()) {
-          
+
           return false;
         }
         if (!getInstanceIdentifierPathArguments().isInitialized()) {
-          
+
           return false;
         }
         if (!getNormalizedNode().isInitialized()) {
-          
+
           return false;
         }
         return true;
@@ -5000,7 +5089,7 @@ public final class ShardTransactionMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierPathArgumentsFieldBuilder() {
         if (instanceIdentifierPathArgumentsBuilder_ == null) {
           instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -5117,7 +5206,7 @@ public final class ShardTransactionMessages {
        * <code>required .org.opendaylight.controller.mdsal.Node normalizedNode = 2;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getNormalizedNodeFieldBuilder() {
         if (normalizedNodeBuilder_ == null) {
           normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -5899,19 +5988,19 @@ public final class ShardTransactionMessages {
 
       public final boolean isInitialized() {
         if (!hasInstanceIdentifierPathArguments()) {
-          
+
           return false;
         }
         if (!hasNormalizedNode()) {
-          
+
           return false;
         }
         if (!getInstanceIdentifierPathArguments().isInitialized()) {
-          
+
           return false;
         }
         if (!getNormalizedNode().isInitialized()) {
-          
+
           return false;
         }
         return true;
@@ -6040,7 +6129,7 @@ public final class ShardTransactionMessages {
        * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
           getInstanceIdentifierPathArgumentsFieldBuilder() {
         if (instanceIdentifierPathArgumentsBuilder_ == null) {
           instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6157,7 +6246,7 @@ public final class ShardTransactionMessages {
        * <code>required .org.opendaylight.controller.mdsal.Node normalizedNode = 2;</code>
        */
       private com.google.protobuf.SingleFieldBuilder<
-          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder> 
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
           getNormalizedNodeFieldBuilder() {
         if (normalizedNodeBuilder_ == null) {
           normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6571,32 +6660,33 @@ public final class ShardTransactionMessages {
     java.lang.String[] descriptorData = {
       "\n\026ShardTransaction.proto\022!org.opendaylig" +
       "ht.controller.mdsal\032\014Common.proto\"\022\n\020Clo" +
-      "seTransaction\"\027\n\025CloseTransactionReply\"*" +
+      "seTransaction\"\027\n\025CloseTransactionReply\"C" +
       "\n\021CreateTransaction\022\025\n\rtransactionId\030\001 \002" +
-      "(\t\"M\n\026CreateTransactionReply\022\034\n\024transact" +
-      "ionActorPath\030\001 \002(\t\022\025\n\rtransactionId\030\002 \002(" +
-      "\t\"\022\n\020ReadyTransaction\"*\n\025ReadyTransactio" +
-      "nReply\022\021\n\tactorPath\030\001 \002(\t\"l\n\nDeleteData\022" +
-      "^\n\037instanceIdentifierPathArguments\030\001 \002(\013" +
-      "25.org.opendaylight.controller.mdsal.Ins",
-      "tanceIdentifier\"\021\n\017DeleteDataReply\"j\n\010Re" +
-      "adData\022^\n\037instanceIdentifierPathArgument" +
-      "s\030\001 \002(\01325.org.opendaylight.controller.md" +
-      "sal.InstanceIdentifier\"P\n\rReadDataReply\022" +
-      "?\n\016normalizedNode\030\001 \001(\0132\'.org.opendaylig" +
-      "ht.controller.mdsal.Node\"\254\001\n\tWriteData\022^" +
-      "\n\037instanceIdentifierPathArguments\030\001 \002(\0132" +
-      "5.org.opendaylight.controller.mdsal.Inst" +
-      "anceIdentifier\022?\n\016normalizedNode\030\002 \002(\0132\'" +
-      ".org.opendaylight.controller.mdsal.Node\"",
-      "\020\n\016WriteDataReply\"\254\001\n\tMergeData\022^\n\037insta" +
+      "(\t\022\027\n\017transactionType\030\002 \002(\005\"M\n\026CreateTra" +
+      "nsactionReply\022\034\n\024transactionActorPath\030\001 " +
+      "\002(\t\022\025\n\rtransactionId\030\002 \002(\t\"\022\n\020ReadyTrans" +
+      "action\"*\n\025ReadyTransactionReply\022\021\n\tactor" +
+      "Path\030\001 \002(\t\"l\n\nDeleteData\022^\n\037instanceIden" +
+      "tifierPathArguments\030\001 \002(\01325.org.opendayl",
+      "ight.controller.mdsal.InstanceIdentifier" +
+      "\"\021\n\017DeleteDataReply\"j\n\010ReadData\022^\n\037insta" +
       "nceIdentifierPathArguments\030\001 \002(\01325.org.o" +
       "pendaylight.controller.mdsal.InstanceIde" +
-      "ntifier\022?\n\016normalizedNode\030\002 \002(\0132\'.org.op" +
-      "endaylight.controller.mdsal.Node\"\020\n\016Merg" +
-      "eDataReplyBV\n:org.opendaylight.controlle" +
-      "r.protobuff.messages.transactionB\030ShardT" +
-      "ransactionMessages"
+      "ntifier\"P\n\rReadDataReply\022?\n\016normalizedNo" +
+      "de\030\001 \001(\0132\'.org.opendaylight.controller.m" +
+      "dsal.Node\"\254\001\n\tWriteData\022^\n\037instanceIdent" +
+      "ifierPathArguments\030\001 \002(\01325.org.opendayli" +
+      "ght.controller.mdsal.InstanceIdentifier\022" +
+      "?\n\016normalizedNode\030\002 \002(\0132\'.org.opendaylig",
+      "ht.controller.mdsal.Node\"\020\n\016WriteDataRep" +
+      "ly\"\254\001\n\tMergeData\022^\n\037instanceIdentifierPa" +
+      "thArguments\030\001 \002(\01325.org.opendaylight.con" +
+      "troller.mdsal.InstanceIdentifier\022?\n\016norm" +
+      "alizedNode\030\002 \002(\0132\'.org.opendaylight.cont" +
+      "roller.mdsal.Node\"\020\n\016MergeDataReplyBV\n:o" +
+      "rg.opendaylight.controller.protobuff.mes" +
+      "sages.transactionB\030ShardTransactionMessa" +
+      "ges"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -6620,7 +6710,7 @@ public final class ShardTransactionMessages {
           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[] { "TransactionId", });
+              new java.lang.String[] { "TransactionId", "TransactionType", });
           internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor =
             getDescriptor().getMessageTypes().get(3);
           internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_fieldAccessorTable = new
similarity index 96%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/ShardTransaction.proto
rename to opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto
index 9684b7d72f57679ad069f31320bf00f0e989380c..4177bd7a052c244385e75df38dcf0fa31523b67c 100644 (file)
@@ -14,6 +14,7 @@ message CloseTransactionReply{
 
 message CreateTransaction{
   required string transactionId = 1;
+  required int32  transactionType =2;
 }
 
 message CreateTransactionReply{
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java
new file mode 100644 (file)
index 0000000..1b85d46
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse 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.node;
+
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
+import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeGetter;
+import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Container;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+public class NormalizedNodeToNodeCodecTest {
+
+
+
+  private SchemaContext schemaContext;
+
+  @Before
+  public void setUp() {
+    schemaContext = TestModel.createTestContext();
+    assertNotNull("Schema context must not be null.", schemaContext);
+  }
+
+  private YangInstanceIdentifier instanceIdentifierFromString(String s) {
+
+    String[] ids = s.split("/");
+
+    List<YangInstanceIdentifier.PathArgument> pathArguments = new ArrayList<>();
+    for (String nodeId : ids) {
+      if (!"".equals(nodeId)) {
+        pathArguments.add(NodeIdentifierFactory.getArgument(nodeId));
+      }
+    }
+    final YangInstanceIdentifier instanceIdentifier =
+        YangInstanceIdentifier.create(pathArguments);
+    return instanceIdentifier;
+  }
+
+
+  @Test
+  public void testNormalizeNodeAttributesToProtoBuffNode() {
+    final NormalizedNode<?, ?> documentOne = TestModel.createTestContainer();
+    String id =
+        "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test"
+            + "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)outer-list"
+            + "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)outer-list[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=2}]"
+            + "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id";
+
+    NormalizedNodeGetter normalizedNodeGetter = new NormalizedNodeGetter(id);
+    new NormalizedNodeNavigator(normalizedNodeGetter).navigate(
+        YangInstanceIdentifier.builder().build().toString(), documentOne);
+
+    // Validate the value of id can be retrieved from the normalized node
+    NormalizedNode output = normalizedNodeGetter.getOutput();
+    assertNotNull(output);
+
+
+    NormalizedNodeToNodeCodec codec =
+        new NormalizedNodeToNodeCodec(schemaContext);
+    Container container =
+        codec.encode(instanceIdentifierFromString(id), output);
+
+    assertNotNull(container);
+    assertEquals(id, container.getParentPath() + "/"
+        + container.getNormalizedNode().getPath());
+
+    // Decode the normalized node from the ProtocolBuffer form
+    // first get the node representation of normalized node
+    final Node node = container.getNormalizedNode();
+
+    NormalizedNode<?, ?> normalizedNode =
+        codec.decode(instanceIdentifierFromString(id), node);
+
+    assertEquals(normalizedNode.getValue().toString(), output.getValue()
+        .toString());
+  }
+
+  @Test
+  public void testThatANormalizedNodeToProtoBuffNodeEncodeDecode()
+      throws Exception {
+    final NormalizedNode<?, ?> documentOne = TestModel.createTestContainer();
+
+    final NormalizedNodeToNodeCodec normalizedNodeToNodeCodec =
+        new NormalizedNodeToNodeCodec(schemaContext);
+
+    Container container =
+        normalizedNodeToNodeCodec.encode(YangInstanceIdentifier.builder()
+            .build(), documentOne);
+
+
+    final NormalizedNode<?, ?> decode =
+        normalizedNodeToNodeCodec
+            .decode(
+                instanceIdentifierFromString("/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test"),
+                container.getNormalizedNode());
+    assertNotNull(decode != null);
+
+    // let us ensure that the return decode normalized node encode returns same container
+    Container containerResult =
+        normalizedNodeToNodeCodec.encode(YangInstanceIdentifier.builder()
+            .build(), decode);
+
+    assertEquals(container.getParentPath(), containerResult.getParentPath());
+    assertEquals(container.getNormalizedNode().getChildCount(), container
+        .getNormalizedNode().getChildCount());
+
+    Assert.assertEquals(containerResult.getNormalizedNode().getChildCount(),
+        container.getNormalizedNode().getChildCount());
+
+    // check first level children are proper
+    List<Node> childrenResult =
+        containerResult.getNormalizedNode().getChildList();
+    List<Node> childrenOriginal = container.getNormalizedNode().getChildList();
+
+    System.out.println("-------------------------------------------------");
+
+    System.out.println(childrenOriginal.toString());
+
+    System.out.println("-------------------------------------------------");
+
+    System.out.println(childrenResult.toString());
+
+    boolean bFound;
+    for (Node resultChild : childrenResult) {
+      bFound = false;
+      for (Node originalChild : childrenOriginal) {
+        if (originalChild.getPath().equals(resultChild.getPath())
+            && resultChild.getType().equals(resultChild.getType())) {
+          bFound = true;
+          break;
+        }
+      }
+      Assert.assertTrue(bFound);
+    }
+
+  }
+
+  @Test
+  public void addAugmentations() {
+    String stringId =
+        "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test"
+            + "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)augmented-list"
+            + "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)augmented-list[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=1}]";
+
+    YangInstanceIdentifier identifier = instanceIdentifierFromString(stringId);
+
+    MapEntryNode uno = TestModel.createAugmentedListEntry(1, "Uno");
+
+    NormalizedNodeToNodeCodec codec =
+        new NormalizedNodeToNodeCodec(schemaContext);
+
+    Container encode = codec.encode(identifier, uno);
+
+    System.out.println(encode.getNormalizedNode());
+
+    codec.decode(identifier, encode.getNormalizedNode());
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java
new file mode 100644 (file)
index 0000000..4da7d8c
--- /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.node.utils;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class NodeIdentifierFactoryTest {
+
+  @Test
+  public void validateAugmentationIdentifier() {
+    YangInstanceIdentifier.PathArgument argument =
+        NodeIdentifierFactory
+            .getArgument("AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}");
+
+    Assert
+        .assertTrue(argument instanceof YangInstanceIdentifier.AugmentationIdentifier);
+
+
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java
new file mode 100644 (file)
index 0000000..136748e
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse 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.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+public class InstanceIdentifierUtilsTest {
+
+  private static QName TEST_QNAME =
+      QName
+          .create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test");
+  private static QName NODE_WITH_VALUE_QNAME =
+      QName
+          .create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)value");
+  private static QName NODE_WITH_PREDICATES_QNAME =
+      QName
+          .create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)pred");
+  private static QName NAME_QNAME =
+      QName
+          .create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)name");
+
+  @Test
+  public void testSerializationOfNodeIdentifier() {
+    YangInstanceIdentifier.PathArgument p1 =
+        new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME);
+
+    List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
+
+    arguments.add(p1);
+
+    YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
+
+    NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
+        InstanceIdentifierUtils.toSerializable(expected);
+
+    YangInstanceIdentifier actual =
+        InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
+
+
+    Assert.assertEquals(expected.getLastPathArgument(),
+        actual.getLastPathArgument());
+
+
+  }
+
+  @Test
+  public void testSerializationOfNodeWithValue() {
+
+    withValue((short) 1);
+    withValue((long) 2);
+    withValue(3);
+    withValue(true);
+
+  }
+
+  private void withValue(Object value) {
+    YangInstanceIdentifier.PathArgument p1 =
+        new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME);
+
+    YangInstanceIdentifier.PathArgument p2 =
+        new YangInstanceIdentifier.NodeWithValue(NODE_WITH_VALUE_QNAME, value);
+
+
+    List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
+
+    arguments.add(p1);
+    arguments.add(p2);
+
+    YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
+
+    NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
+        InstanceIdentifierUtils.toSerializable(expected);
+
+    YangInstanceIdentifier actual =
+        InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
+
+
+    Assert.assertEquals(expected.getLastPathArgument(),
+        actual.getLastPathArgument());
+  }
+
+
+  @Test
+  public void testSerializationOfNodeIdentifierWithPredicates() {
+
+    withPredicates((short) 1);
+    withPredicates((long) 2);
+    withPredicates(3);
+    withPredicates(true);
+
+  }
+
+  private void withPredicates(Object value) {
+    YangInstanceIdentifier.PathArgument p1 =
+        new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME);
+
+    YangInstanceIdentifier.PathArgument p2 =
+        new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+            NODE_WITH_PREDICATES_QNAME, NAME_QNAME, value);
+
+
+    List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
+
+    arguments.add(p1);
+    arguments.add(p2);
+
+    YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
+
+    NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
+        InstanceIdentifierUtils.toSerializable(expected);
+
+    YangInstanceIdentifier actual =
+        InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
+
+
+    Assert.assertEquals(expected.getLastPathArgument(),
+        actual.getLastPathArgument());
+  }
+
+  @Test
+  public void testAugmentationIdentifier() {
+    YangInstanceIdentifier.PathArgument p1 =
+        new YangInstanceIdentifier.AugmentationIdentifier(new HashSet(
+            Arrays.asList(TEST_QNAME)));
+
+    List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
+
+    arguments.add(p1);
+
+    YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
+
+    NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
+        InstanceIdentifierUtils.toSerializable(expected);
+
+    YangInstanceIdentifier actual =
+        InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
+
+
+    Assert.assertEquals(expected.getLastPathArgument(),
+        actual.getLastPathArgument());
+
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java
new file mode 100644 (file)
index 0000000..853b3e2
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse 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.util;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.common.SimpleNormalizedNodeMessage;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer.DomFromNormalizedNodeSerializerFactory;
+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.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Two of the testcases in the yangtools/yang-data-impl are leveraged (with modification) to create
+ * the serialization of NormalizedNode using the ProtocolBuffer
+ *
+ * @syedbahm
+ *
+ */
+
+
+public class NormalizedNodeXmlConverterTest {
+  private static final Logger logger = LoggerFactory
+      .getLogger(NormalizedNodeXmlConverterTest.class);
+  public static final String NAMESPACE =
+      "urn:opendaylight:params:xml:ns:yang:controller:test";
+  private static Date revision;
+  private ContainerNode expectedNode;
+  private ContainerSchemaNode containerNode;
+  private String xmlPath;
+
+  static {
+    try {
+      revision = new SimpleDateFormat("yyyy-MM-dd").parse("2014-03-13");
+    } catch (ParseException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public static DataSchemaNode getSchemaNode(final SchemaContext context,
+      final String moduleName, final String childNodeName) {
+    for (Module module : context.getModules()) {
+      if (module.getName().equals(moduleName)) {
+        DataSchemaNode found =
+            findChildNode(module.getChildNodes(), childNodeName);
+        Preconditions.checkState(found != null, "Unable to find %s",
+            childNodeName);
+        return found;
+      }
+    }
+    throw new IllegalStateException("Unable to find child node "
+        + childNodeName);
+  }
+
+  static DataSchemaNode findChildNode(
+      final Collection<DataSchemaNode> children, final String name) {
+    List<DataNodeContainer> containers = Lists.newArrayList();
+
+    for (DataSchemaNode dataSchemaNode : children) {
+      if (dataSchemaNode.getQName().getLocalName().equals(name)) {
+        return dataSchemaNode;
+      }
+      if (dataSchemaNode instanceof DataNodeContainer) {
+        containers.add((DataNodeContainer) dataSchemaNode);
+      } else if (dataSchemaNode instanceof ChoiceNode) {
+        containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
+      }
+    }
+
+    for (DataNodeContainer container : containers) {
+      DataSchemaNode retVal = findChildNode(container.getChildNodes(), name);
+      if (retVal != null) {
+        return retVal;
+      }
+    }
+
+    return null;
+  }
+
+  public static YangInstanceIdentifier.NodeIdentifier getNodeIdentifier(
+      final String localName) {
+    return new YangInstanceIdentifier.NodeIdentifier(QName.create(
+        URI.create(NAMESPACE), revision, localName));
+  }
+
+  public static YangInstanceIdentifier.AugmentationIdentifier getAugmentIdentifier(
+      final String... childNames) {
+    Set<QName> qn = Sets.newHashSet();
+
+    for (String childName : childNames) {
+      qn.add(getNodeIdentifier(childName).getNodeType());
+    }
+
+    return new YangInstanceIdentifier.AugmentationIdentifier(qn);
+  }
+
+
+  public static ContainerNode augmentChoiceExpectedNode() {
+
+    DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> b =
+        Builders.containerBuilder();
+    b.withNodeIdentifier(getNodeIdentifier("container"));
+
+    b.withChild(Builders
+        .choiceBuilder()
+        .withNodeIdentifier(getNodeIdentifier("ch2"))
+        .withChild(
+            Builders.leafBuilder()
+                .withNodeIdentifier(getNodeIdentifier("c2Leaf")).withValue("2")
+                .build())
+        .withChild(
+            Builders
+                .choiceBuilder()
+                .withNodeIdentifier(getNodeIdentifier("c2DeepChoice"))
+                .withChild(
+                    Builders
+                        .leafBuilder()
+                        .withNodeIdentifier(
+                            getNodeIdentifier("c2DeepChoiceCase1Leaf2"))
+                        .withValue("2").build()).build()).build());
+
+    b.withChild(Builders
+        .choiceBuilder()
+        .withNodeIdentifier(getNodeIdentifier("ch3"))
+        .withChild(
+            Builders.leafBuilder()
+                .withNodeIdentifier(getNodeIdentifier("c3Leaf")).withValue("3")
+                .build()).build());
+
+    b.withChild(Builders
+        .augmentationBuilder()
+        .withNodeIdentifier(getAugmentIdentifier("augLeaf"))
+        .withChild(
+            Builders.leafBuilder()
+                .withNodeIdentifier(getNodeIdentifier("augLeaf"))
+                .withValue("augment").build()).build());
+
+    b.withChild(Builders
+        .augmentationBuilder()
+        .withNodeIdentifier(getAugmentIdentifier("ch"))
+        .withChild(
+            Builders
+                .choiceBuilder()
+                .withNodeIdentifier(getNodeIdentifier("ch"))
+                .withChild(
+                    Builders.leafBuilder()
+                        .withNodeIdentifier(getNodeIdentifier("c1Leaf"))
+                        .withValue("1").build())
+                .withChild(
+                    Builders
+                        .augmentationBuilder()
+                        .withNodeIdentifier(
+                            getAugmentIdentifier("c1Leaf_AnotherAugment",
+                                "deepChoice"))
+                        .withChild(
+                            Builders
+                                .leafBuilder()
+                                .withNodeIdentifier(
+                                    getNodeIdentifier("c1Leaf_AnotherAugment"))
+                                .withValue("1").build())
+                        .withChild(
+                            Builders
+                                .choiceBuilder()
+                                .withNodeIdentifier(
+                                    getNodeIdentifier("deepChoice"))
+                                .withChild(
+                                    Builders
+                                        .leafBuilder()
+                                        .withNodeIdentifier(
+                                            getNodeIdentifier("deepLeafc1"))
+                                        .withValue("1").build()).build())
+                        .build()).build()).build());
+
+    return b.build();
+  }
+
+
+
+  public void init(final String yangPath, final String xmlPath,
+      final ContainerNode expectedNode) throws Exception {
+    SchemaContext schema = parseTestSchema(yangPath);
+    this.xmlPath = xmlPath;
+    this.containerNode =
+        (ContainerSchemaNode) getSchemaNode(schema, "test", "container");
+    this.expectedNode = expectedNode;
+  }
+
+  SchemaContext parseTestSchema(final String yangPath) throws Exception {
+
+    YangParserImpl yangParserImpl = new YangParserImpl();
+    InputStream stream =
+        NormalizedNodeXmlConverterTest.class.getResourceAsStream(yangPath);
+    ArrayList<InputStream> al = new ArrayList<InputStream>();
+    al.add(stream);
+    Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(al);
+    return yangParserImpl.resolveSchemaContext(modules);
+
+  }
+
+
+  @Test
+  public void testConversionWithAugmentChoice() throws Exception {
+    init("/augment_choice.yang", "/augment_choice.xml",
+        augmentChoiceExpectedNode());
+    Document doc = loadDocument(xmlPath);
+
+    ContainerNode built =
+        DomToNormalizedNodeParserFactory
+            .getInstance(DomUtils.defaultValueCodecProvider())
+            .getContainerNodeParser()
+            .parse(Collections.singletonList(doc.getDocumentElement()),
+                containerNode);
+
+    if (expectedNode != null) {
+      junit.framework.Assert.assertEquals(expectedNode, built);
+    }
+
+    logger.info("{}", built);
+
+    Iterable<Element> els =
+        DomFromNormalizedNodeSerializerFactory
+            .getInstance(XmlDocumentUtils.getDocument(),
+                DomUtils.defaultValueCodecProvider())
+            .getContainerNodeSerializer().serialize(containerNode, built);
+
+    Element el = els.iterator().next();
+
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+
+    System.out.println(toString(doc.getDocumentElement()));
+    System.out.println(toString(el));
+
+    new Diff(XMLUnit.buildControlDocument(toString(doc.getDocumentElement())),
+        XMLUnit.buildTestDocument(toString(el))).similar();
+  }
+
+  private static ContainerNode listLeafListWithAttributes() {
+    DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> b =
+        Builders.containerBuilder();
+    b.withNodeIdentifier(getNodeIdentifier("container"));
+
+    CollectionNodeBuilder<MapEntryNode, MapNode> listBuilder =
+        Builders.mapBuilder().withNodeIdentifier(getNodeIdentifier("list"));
+
+    Map<QName, Object> predicates = Maps.newHashMap();
+    predicates.put(getNodeIdentifier("uint32InList").getNodeType(), 3L);
+
+    DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> list1Builder =
+        Builders.mapEntryBuilder().withNodeIdentifier(
+            new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                getNodeIdentifier("list").getNodeType(), predicates));
+    NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>> uint32InListBuilder =
+        Builders.leafBuilder().withNodeIdentifier(
+            getNodeIdentifier("uint32InList"));
+
+    list1Builder.withChild(uint32InListBuilder.withValue(3L).build());
+
+    listBuilder.withChild(list1Builder.build());
+    b.withChild(listBuilder.build());
+
+    NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>> booleanBuilder =
+        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("boolean"));
+    booleanBuilder.withValue(false);
+    b.withChild(booleanBuilder.build());
+
+    ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListBuilder =
+        Builders.leafSetBuilder().withNodeIdentifier(
+            getNodeIdentifier("leafList"));
+
+    NormalizedNodeBuilder<YangInstanceIdentifier.NodeWithValue, Object, LeafSetEntryNode<Object>> leafList1Builder =
+        Builders.leafSetEntryBuilder().withNodeIdentifier(
+            new YangInstanceIdentifier.NodeWithValue(getNodeIdentifier(
+                "leafList").getNodeType(), "a"));
+
+    leafList1Builder.withValue("a");
+
+    leafListBuilder.withChild(leafList1Builder.build());
+    b.withChild(leafListBuilder.build());
+
+    return b.build();
+  }
+
+
+  @Test
+  public void testConversionWithAttributes() throws Exception {
+    init("/test.yang", "/simple_xml_with_attributes.xml",
+        listLeafListWithAttributes());
+    Document doc = loadDocument(xmlPath);
+
+    ContainerNode built =
+        DomToNormalizedNodeParserFactory
+            .getInstance(DomUtils.defaultValueCodecProvider())
+            .getContainerNodeParser()
+            .parse(Collections.singletonList(doc.getDocumentElement()),
+                containerNode);
+
+    if (expectedNode != null) {
+      junit.framework.Assert.assertEquals(expectedNode, built);
+    }
+
+    logger.info("{}", built);
+
+    Iterable<Element> els =
+        DomFromNormalizedNodeSerializerFactory
+            .getInstance(XmlDocumentUtils.getDocument(),
+                DomUtils.defaultValueCodecProvider())
+            .getContainerNodeSerializer().serialize(containerNode, built);
+
+    Element el = els.iterator().next();
+
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+
+    System.out.println(toString(doc.getDocumentElement()));
+    System.out.println(toString(el));
+
+    new Diff(XMLUnit.buildControlDocument(toString(doc.getDocumentElement())),
+        XMLUnit.buildTestDocument(toString(el))).similar();
+  }
+
+
+  private Document loadDocument(final String xmlPath) throws Exception {
+    InputStream resourceAsStream =
+        NormalizedNodeXmlConverterTest.class.getResourceAsStream(xmlPath);
+
+    Document currentConfigElement = readXmlToDocument(resourceAsStream);
+    Preconditions.checkNotNull(currentConfigElement);
+    return currentConfigElement;
+  }
+
+  private static final DocumentBuilderFactory BUILDERFACTORY;
+
+  static {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setNamespaceAware(true);
+    factory.setCoalescing(true);
+    factory.setIgnoringElementContentWhitespace(true);
+    factory.setIgnoringComments(true);
+    BUILDERFACTORY = factory;
+  }
+
+  private Document readXmlToDocument(final InputStream xmlContent)
+      throws IOException, SAXException {
+    DocumentBuilder dBuilder;
+    try {
+      dBuilder = BUILDERFACTORY.newDocumentBuilder();
+    } catch (ParserConfigurationException e) {
+      throw new RuntimeException("Failed to parse XML document", e);
+    }
+    Document doc = dBuilder.parse(xmlContent);
+
+    doc.getDocumentElement().normalize();
+    return doc;
+  }
+
+  public static String toString(final Element xml) {
+    try {
+      Transformer transformer =
+          TransformerFactory.newInstance().newTransformer();
+      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+
+      StreamResult result = new StreamResult(new StringWriter());
+      DOMSource source = new DOMSource(xml);
+      transformer.transform(source, result);
+
+      return result.getWriter().toString();
+    } catch (IllegalArgumentException | TransformerFactoryConfigurationError
+        | TransformerException e) {
+      throw new RuntimeException("Unable to serialize xml element " + xml, e);
+    }
+  }
+
+  @Test
+  public void testConversionToNormalizedXml() throws Exception {
+    SimpleNormalizedNodeMessage.NormalizedNodeXml nnXml =
+        EncoderDecoderUtil.encode(parseTestSchema("/augment_choice.yang"),
+            augmentChoiceExpectedNode());
+    Document expectedDoc = loadDocument("/augment_choice.xml");
+    Document convertedDoc =
+        EncoderDecoderUtil.factory.newDocumentBuilder().parse(
+            new ByteArrayInputStream(nnXml.getXmlString().getBytes("utf-8")));
+    System.out.println(toString(convertedDoc.getDocumentElement()));
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    new Diff(XMLUnit.buildControlDocument(toString(expectedDoc
+        .getDocumentElement())),
+        XMLUnit.buildTestDocument(toString(convertedDoc.getDocumentElement())))
+        .similar();
+    System.out.println(toString(expectedDoc.getDocumentElement()));
+
+  }
+
+
+  @Test
+  public void testConversionFromXmlToNormalizedNode() throws Exception {
+    SimpleNormalizedNodeMessage.NormalizedNodeXml nnXml =
+        EncoderDecoderUtil.encode(parseTestSchema("/test.yang"),
+            listLeafListWithAttributes());
+    Document expectedDoc = loadDocument("/simple_xml_with_attributes.xml");
+    Document convertedDoc =
+        EncoderDecoderUtil.factory.newDocumentBuilder().parse(
+            new ByteArrayInputStream(nnXml.getXmlString().getBytes("utf-8")));
+    System.out.println(toString(convertedDoc.getDocumentElement()));
+    XMLUnit.setIgnoreWhitespace(true);
+    XMLUnit.setIgnoreComments(true);
+    new Diff(XMLUnit.buildControlDocument(toString(expectedDoc
+        .getDocumentElement())),
+        XMLUnit.buildTestDocument(toString(convertedDoc.getDocumentElement())))
+        .similar();
+    System.out.println(toString(expectedDoc.getDocumentElement()));
+
+    // now we will try to convert xml back to normalize node.
+    ContainerNode cn =
+        (ContainerNode) EncoderDecoderUtil.decode(
+            parseTestSchema("/test.yang"), nnXml);
+    junit.framework.Assert.assertEquals(listLeafListWithAttributes(), cn);
+
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java
new file mode 100644 (file)
index 0000000..3eeb06f
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse 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.util;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.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.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+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.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+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;
+
+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 AUG_NAME_QNAME = QName.create(
+      "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:aug",
+      "2014-03-13", "name");
+
+  public static final QName AUG_CONT_QNAME = QName.create(
+      "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:aug",
+      "2014-03-13", "cont");
+
+
+  public static final QName DESC_QNAME = QName.create(TEST_QNAME, "desc");
+  public static final QName POINTER_QNAME = QName.create(TEST_QNAME, "pointer");
+  public static final QName SOME_REF_QNAME = QName.create(TEST_QNAME,
+      "some-ref");
+  public static final QName MYIDENTITY_QNAME = QName.create(TEST_QNAME,
+      "myidentity");
+  public static final QName SWITCH_FEATURES_QNAME = QName.create(TEST_QNAME,
+      "switch-features");
+
+  public static final QName AUGMENTED_LIST_QNAME = QName.create(TEST_QNAME,
+      "augmented-list");
+
+  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";
+  private static final String DATASTORE_AUG_YANG =
+      "/odl-datastore-augmentation.yang";
+  private static final String DATASTORE_TEST_NOTIFICATION_YANG =
+      "/odl-datastore-test-notification.yang";
+
+
+  public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier
+      .of(TEST_QNAME);
+  public static final YangInstanceIdentifier DESC_PATH = YangInstanceIdentifier
+      .builder(TEST_PATH).node(DESC_QNAME).build();
+  public static final YangInstanceIdentifier OUTER_LIST_PATH =
+      YangInstanceIdentifier.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");
+
+  private static final Integer ONE_ID = 1;
+  private static final Integer TWO_ID = 2;
+  private static final String TWO_ONE_NAME = "one";
+  private static final String TWO_TWO_NAME = "two";
+  private static final String DESC = "Hello there";
+
+  // Family specific constants
+  public static final QName FAMILY_QNAME =
+      QName
+          .create(
+              "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:notification-test",
+              "2014-04-17", "family");
+  public static final QName CHILDREN_QNAME = QName.create(FAMILY_QNAME,
+      "children");
+  public static final QName GRAND_CHILDREN_QNAME = QName.create(FAMILY_QNAME,
+      "grand-children");
+  public static final QName CHILD_NUMBER_QNAME = QName.create(FAMILY_QNAME,
+      "child-number");
+  public static final QName CHILD_NAME_QNAME = QName.create(FAMILY_QNAME,
+      "child-name");
+  public static final QName GRAND_CHILD_NUMBER_QNAME = QName.create(
+      FAMILY_QNAME, "grand-child-number");
+  public static final QName GRAND_CHILD_NAME_QNAME = QName.create(FAMILY_QNAME,
+      "grand-child-name");
+
+  public static final YangInstanceIdentifier FAMILY_PATH =
+      YangInstanceIdentifier.of(FAMILY_QNAME);
+  public static final YangInstanceIdentifier FAMILY_DESC_PATH =
+      YangInstanceIdentifier.builder(FAMILY_PATH).node(DESC_QNAME).build();
+  public static final YangInstanceIdentifier CHILDREN_PATH =
+      YangInstanceIdentifier.builder(FAMILY_PATH).node(CHILDREN_QNAME).build();
+
+  private static final Integer FIRST_CHILD_ID = 1;
+  private static final Integer SECOND_CHILD_ID = 2;
+
+  private static final String FIRST_CHILD_NAME = "first child";
+  private static final String SECOND_CHILD_NAME = "second child";
+
+  private static final Integer FIRST_GRAND_CHILD_ID = 1;
+  private static final Integer SECOND_GRAND_CHILD_ID = 2;
+
+  private static final String FIRST_GRAND_CHILD_NAME = "first grand child";
+  private static final String SECOND_GRAND_CHILD_NAME = "second grand child";
+
+  // first child
+  private static final YangInstanceIdentifier CHILDREN_1_PATH =
+      YangInstanceIdentifier.builder(CHILDREN_PATH)
+          .nodeWithKey(CHILDREN_QNAME, CHILD_NUMBER_QNAME, FIRST_CHILD_ID) //
+          .build();
+  private static final YangInstanceIdentifier CHILDREN_1_NAME_PATH =
+      YangInstanceIdentifier.builder(CHILDREN_PATH)
+          .nodeWithKey(CHILDREN_QNAME, CHILD_NAME_QNAME, FIRST_CHILD_NAME) //
+          .build();
+
+  private static final YangInstanceIdentifier CHILDREN_2_PATH =
+      YangInstanceIdentifier.builder(CHILDREN_PATH)
+          .nodeWithKey(CHILDREN_QNAME, CHILD_NUMBER_QNAME, SECOND_CHILD_ID) //
+          .build();
+  private static final YangInstanceIdentifier CHILDREN_2_NAME_PATH =
+      YangInstanceIdentifier.builder(CHILDREN_PATH)
+          .nodeWithKey(CHILDREN_QNAME, CHILD_NAME_QNAME, SECOND_CHILD_NAME) //
+          .build();
+
+
+  private static final YangInstanceIdentifier GRAND_CHILD_1_PATH =
+      YangInstanceIdentifier
+          .builder(CHILDREN_1_PATH)
+          .node(GRAND_CHILDREN_QNAME)
+          //
+          .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
+              FIRST_GRAND_CHILD_ID) //
+          .build();
+
+  private static final YangInstanceIdentifier GRAND_CHILD_1_NAME_PATH =
+      YangInstanceIdentifier
+          .builder(CHILDREN_1_PATH)
+          .node(GRAND_CHILDREN_QNAME)
+          //
+          .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NAME_QNAME,
+              FIRST_GRAND_CHILD_NAME) //
+          .build();
+
+  private static final YangInstanceIdentifier GRAND_CHILD_2_PATH =
+      YangInstanceIdentifier
+          .builder(CHILDREN_2_PATH)
+          .node(GRAND_CHILDREN_QNAME)
+          //
+          .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
+              SECOND_GRAND_CHILD_ID) //
+          .build();
+
+  private static final YangInstanceIdentifier GRAND_CHILD_2_NAME_PATH =
+      YangInstanceIdentifier
+          .builder(CHILDREN_2_PATH)
+          .node(GRAND_CHILDREN_QNAME)
+          //
+          .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NAME_QNAME,
+              SECOND_GRAND_CHILD_NAME) //
+          .build();
+
+  private static final YangInstanceIdentifier DESC_PATH_ID =
+      YangInstanceIdentifier.builder(DESC_PATH).build();
+  private static final YangInstanceIdentifier OUTER_LIST_1_PATH =
+      YangInstanceIdentifier.builder(OUTER_LIST_PATH)
+          .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, ONE_ID) //
+          .build();
+
+  private static final YangInstanceIdentifier OUTER_LIST_2_PATH =
+      YangInstanceIdentifier.builder(OUTER_LIST_PATH)
+          .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
+          .build();
+
+  private static final YangInstanceIdentifier TWO_TWO_PATH =
+      YangInstanceIdentifier.builder(OUTER_LIST_2_PATH).node(INNER_LIST_QNAME) //
+          .nodeWithKey(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME) //
+          .build();
+
+  private static final YangInstanceIdentifier TWO_TWO_VALUE_PATH =
+      YangInstanceIdentifier.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();
+
+  public static final InputStream getDatastoreTestInputStream() {
+    return getInputStream(DATASTORE_TEST_YANG);
+  }
+
+  public static final InputStream getDatastoreAugInputStream() {
+    return getInputStream(DATASTORE_AUG_YANG);
+  }
+
+  public static final InputStream getDatastoreTestNotificationInputStream() {
+    return getInputStream(DATASTORE_TEST_NOTIFICATION_YANG);
+  }
+
+  private static InputStream getInputStream(final String resourceName) {
+    return TestModel.class.getResourceAsStream(resourceName);
+  }
+
+  public static SchemaContext createTestContext() {
+    List<InputStream> inputStreams = new ArrayList<>();
+    inputStreams.add(getDatastoreTestInputStream());
+    inputStreams.add(getDatastoreAugInputStream());
+    inputStreams.add(getDatastoreTestNotificationInputStream());
+
+    YangParserImpl parser = new YangParserImpl();
+    Set<Module> modules = parser.parseYangModelsFromStreams(inputStreams);
+    return parser.resolveSchemaContext(modules);
+  }
+
+  /**
+   * Returns a test document
+   * <p/>
+   *
+   * <pre>
+   * test
+   *     outer-list
+   *          id 1
+   *     outer-list
+   *          id 2
+   *          inner-list
+   *                  name "one"
+   *          inner-list
+   *                  name "two"
+   *
+   * </pre>
+   *
+   * @return
+   */
+  public static NormalizedNode<?, ?> createDocumentOne(
+      SchemaContext schemaContext) {
+    return ImmutableContainerNodeBuilder
+        .create()
+        .withNodeIdentifier(
+            new YangInstanceIdentifier.NodeIdentifier(schemaContext.getQName()))
+        .withChild(createTestContainer()).build();
+
+  }
+
+  public static ContainerNode createTestContainer() {
+
+
+    // Create a list of shoes
+    // This is to test leaf list entry
+    final LeafSetEntryNode<Object> nike =
+        ImmutableLeafSetEntryNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeWithValue(QName.create(
+                    TEST_QNAME, "shoe"), "nike")).withValue("nike").build();
+
+    final LeafSetEntryNode<Object> puma =
+        ImmutableLeafSetEntryNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeWithValue(QName.create(
+                    TEST_QNAME, "shoe"), "puma")).withValue("puma").build();
+
+    final LeafSetNode<Object> shoes =
+        ImmutableLeafSetNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(QName.create(
+                    TEST_QNAME, "shoe"))).withChild(nike).withChild(puma)
+            .build();
+
+
+    // Test a leaf-list where each entry contains an identity
+    final LeafSetEntryNode<Object> cap1 =
+        ImmutableLeafSetEntryNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeWithValue(QName.create(
+                    TEST_QNAME, "capability"), DESC_QNAME))
+            .withValue(DESC_QNAME).build();
+
+    final LeafSetNode<Object> capabilities =
+        ImmutableLeafSetNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(QName.create(
+                    TEST_QNAME, "capability"))).withChild(cap1).build();
+
+    ContainerNode switchFeatures =
+        ImmutableContainerNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(SWITCH_FEATURES_QNAME))
+            .withChild(capabilities).build();
+
+    // Create a leaf list with numbers
+    final LeafSetEntryNode<Object> five =
+        ImmutableLeafSetEntryNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                (new YangInstanceIdentifier.NodeWithValue(QName.create(
+                    TEST_QNAME, "number"), 5))).withValue(5).build();
+    final LeafSetEntryNode<Object> fifteen =
+        ImmutableLeafSetEntryNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                (new YangInstanceIdentifier.NodeWithValue(QName.create(
+                    TEST_QNAME, "number"), 15))).withValue(15).build();
+    final LeafSetNode<Object> numbers =
+        ImmutableLeafSetNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(QName.create(
+                    TEST_QNAME, "number"))).withChild(five).withChild(fifteen)
+            .build();
+
+
+    // Create augmentations
+    MapEntryNode mapEntry = createAugmentedListEntry(1, "First Test");
+
+
+    // Create the document
+    return ImmutableContainerNodeBuilder
+        .create()
+        .withNodeIdentifier(
+            new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME))
+        .withChild(ImmutableNodes.leafNode(DESC_QNAME, DESC))
+        .withChild(ImmutableNodes.leafNode(POINTER_QNAME, "pointer"))
+        .withChild(
+            ImmutableNodes.leafNode(SOME_REF_QNAME, YangInstanceIdentifier
+                .builder().build()))
+        .withChild(ImmutableNodes.leafNode(MYIDENTITY_QNAME, DESC_QNAME))
+
+        // .withChild(augmentationNode)
+        .withChild(shoes)
+        .withChild(numbers)
+        .withChild(switchFeatures)
+        .withChild(
+            mapNodeBuilder(AUGMENTED_LIST_QNAME).withChild(mapEntry).build())
+        .withChild(
+            mapNodeBuilder(OUTER_LIST_QNAME)
+                .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
+                .withChild(BAR_NODE).build()).build();
+
+  }
+
+  public static MapEntryNode createAugmentedListEntry(int id, String name) {
+
+    Set<QName> childAugmentations = new HashSet<>();
+    childAugmentations.add(AUG_CONT_QNAME);
+
+    ContainerNode augCont =
+        ImmutableContainerNodeBuilder
+            .create()
+            .withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(AUG_CONT_QNAME))
+            .withChild(ImmutableNodes.leafNode(AUG_NAME_QNAME, name)).build();
+
+
+    final YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier =
+        new YangInstanceIdentifier.AugmentationIdentifier(childAugmentations);
+
+    final AugmentationNode augmentationNode =
+        Builders.augmentationBuilder()
+            .withNodeIdentifier(augmentationIdentifier).withChild(augCont)
+            .build();
+
+    return ImmutableMapEntryNodeBuilder
+        .create()
+        .withNodeIdentifier(
+            new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                AUGMENTED_LIST_QNAME, ID_QNAME, id))
+        .withChild(ImmutableNodes.leafNode(ID_QNAME, id))
+        .withChild(augmentationNode).build();
+  }
+
+
+  public static ContainerNode createFamily() {
+    final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> familyContainerBuilder =
+        ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+            new YangInstanceIdentifier.NodeIdentifier(FAMILY_QNAME));
+
+    final CollectionNodeBuilder<MapEntryNode, MapNode> childrenBuilder =
+        mapNodeBuilder(CHILDREN_QNAME);
+
+    final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> firstChildBuilder =
+        mapEntryBuilder(CHILDREN_QNAME, CHILD_NUMBER_QNAME, FIRST_CHILD_ID);
+    final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> secondChildBuilder =
+        mapEntryBuilder(CHILDREN_QNAME, CHILD_NUMBER_QNAME, SECOND_CHILD_ID);
+
+    final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> firstGrandChildBuilder =
+        mapEntryBuilder(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
+            FIRST_GRAND_CHILD_ID);
+    final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> secondGrandChildBuilder =
+        mapEntryBuilder(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
+            SECOND_GRAND_CHILD_ID);
+
+    firstGrandChildBuilder
+        .withChild(
+            ImmutableNodes.leafNode(GRAND_CHILD_NUMBER_QNAME,
+                FIRST_GRAND_CHILD_ID)).withChild(
+            ImmutableNodes.leafNode(GRAND_CHILD_NAME_QNAME,
+                FIRST_GRAND_CHILD_NAME));
+
+    secondGrandChildBuilder.withChild(
+        ImmutableNodes
+            .leafNode(GRAND_CHILD_NUMBER_QNAME, SECOND_GRAND_CHILD_ID))
+        .withChild(
+            ImmutableNodes.leafNode(GRAND_CHILD_NAME_QNAME,
+                SECOND_GRAND_CHILD_NAME));
+
+    firstChildBuilder
+        .withChild(ImmutableNodes.leafNode(CHILD_NUMBER_QNAME, FIRST_CHILD_ID))
+        .withChild(ImmutableNodes.leafNode(CHILD_NAME_QNAME, FIRST_CHILD_NAME))
+        .withChild(
+            mapNodeBuilder(GRAND_CHILDREN_QNAME).withChild(
+                firstGrandChildBuilder.build()).build());
+
+
+    secondChildBuilder
+        .withChild(ImmutableNodes.leafNode(CHILD_NUMBER_QNAME, SECOND_CHILD_ID))
+        .withChild(ImmutableNodes.leafNode(CHILD_NAME_QNAME, SECOND_CHILD_NAME))
+        .withChild(
+            mapNodeBuilder(GRAND_CHILDREN_QNAME).withChild(
+                firstGrandChildBuilder.build()).build());
+
+    childrenBuilder.withChild(firstChildBuilder.build());
+    childrenBuilder.withChild(secondChildBuilder.build());
+
+    return familyContainerBuilder.withChild(childrenBuilder.build()).build();
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/AbstractMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/AbstractMessagesTest.java
new file mode 100644 (file)
index 0000000..c6c4afd
--- /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.protobuff.messages;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+/**
+ * @author: syedbahm Date: 7/31/14
+ */
+public abstract class AbstractMessagesTest {
+  public final String VERSION_COMPATIBILTY_TEST_DATA_PATH = "."
+      + File.separator + "src" + File.separator + "test" + File.separator
+      + "resources" + File.separator + "version-compatibility-serialized-data";
+  private File file;
+  private File testDataFile;
+
+  protected AbstractMessagesTest() {
+    init();
+  }
+
+  protected void init() {
+    file = new File(getTestFileName());
+    testDataFile =
+        new File(VERSION_COMPATIBILTY_TEST_DATA_PATH + File.separator
+            + getTestFileName() + "Data");
+  }
+
+
+
+  abstract public void verifySerialization() throws Exception;
+
+
+  protected void writeToFile(
+      com.google.protobuf.GeneratedMessage.Builder<?> builder) throws Exception {
+
+    FileOutputStream output = new FileOutputStream(file);
+    builder.build().writeTo(output);
+    output.close();;
+
+  }
+
+  protected com.google.protobuf.GeneratedMessage readFromFile(
+      com.google.protobuf.Parser<?> parser) throws Exception {
+    com.google.protobuf.GeneratedMessage message =
+        (com.google.protobuf.GeneratedMessage) parser
+            .parseFrom(new FileInputStream(file));
+
+    /*Note: we will delete only the test file -- comment below if you want to capture the
+       version-compatibility-serialized-data test data file.The file will be generated at root of the
+       sal-protocolbuffer-encoding
+       and you need to move it to test/resources/version-compatbility-serialized-data folder renaming the file to include suffix <TestFileName>"Data"
+    */
+     file.delete();
+    return message;
+  }
+
+  protected com.google.protobuf.GeneratedMessage readFromTestDataFile(
+      com.google.protobuf.Parser<?> parser) throws Exception {
+    return (com.google.protobuf.GeneratedMessage) parser
+        .parseFrom(new FileInputStream(testDataFile));
+  }
+
+
+  public abstract String getTestFileName();
+
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessagesTest.java
new file mode 100644 (file)
index 0000000..a01ccb8
--- /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.protobuff.messages.cohort3pc;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the cohort.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+
+public class ThreePhaseCommitCohortMessagesTest extends AbstractMessagesTest {
+
+
+  @Test
+  public void verifySerialization() throws Exception {
+
+
+
+    ThreePhaseCommitCohortMessages.CanCommitTransactionReply.Builder builder =
+        ThreePhaseCommitCohortMessages.CanCommitTransactionReply.newBuilder();
+    builder.setCanCommit(true);
+
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+    // Here we will read from the just serialized data
+
+    ThreePhaseCommitCohortMessages.CanCommitTransactionReply newCanCommitTransactionReply =
+        (ThreePhaseCommitCohortMessages.CanCommitTransactionReply) readFromFile(ThreePhaseCommitCohortMessages.CanCommitTransactionReply.PARSER);
+
+    Assert.assertTrue(newCanCommitTransactionReply.getCanCommit());
+
+
+    // Here we will read the same from our test-data file and check we got back what we had saved
+    // earlier
+    ThreePhaseCommitCohortMessages.CanCommitTransactionReply originalCanCommitTransactionReply =
+        (ThreePhaseCommitCohortMessages.CanCommitTransactionReply) readFromTestDataFile(ThreePhaseCommitCohortMessages.CanCommitTransactionReply.PARSER);
+
+    Assert.assertEquals(newCanCommitTransactionReply.getCanCommit(),
+        originalCanCommitTransactionReply.getCanCommit());
+
+  }
+
+  @Override
+  public String getTestFileName() {
+    return ThreePhaseCommitCohortMessagesTest.class.getSimpleName();
+  }
+
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessagesTest.java
new file mode 100644 (file)
index 0000000..c68ecea
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.protobuff.messages.common;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the common.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+public class NormalizedNodeMessagesTest extends AbstractMessagesTest {
+
+  @Override
+  @Test
+  public void verifySerialization() throws Exception {
+    NormalizedNodeMessages.Attribute.Builder builder =
+        NormalizedNodeMessages.Attribute.newBuilder();
+    builder.setName("test");
+    builder.setType("fake");
+    builder.setValue("testValue");
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+    NormalizedNodeMessages.Attribute attributeNew =
+        (NormalizedNodeMessages.Attribute) readFromFile(NormalizedNodeMessages.Attribute.PARSER);
+    Assert.assertEquals("test", attributeNew.getName());
+    Assert.assertEquals("fake", attributeNew.getType());
+    Assert.assertEquals("testValue", attributeNew.getValue());
+
+    NormalizedNodeMessages.Attribute attributeOriginal =
+        (NormalizedNodeMessages.Attribute) readFromTestDataFile(NormalizedNodeMessages.Attribute.PARSER);
+    Assert.assertEquals(attributeNew.getName(), attributeOriginal.getName());
+  }
+
+  @Override
+  public String getTestFileName() {
+    return NormalizedNodeMessagesTest.class.getSimpleName();
+  }
+
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessagesTest.java
new file mode 100644 (file)
index 0000000..e933928
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.protobuff.messages.datachange.notification;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the DataChangeListener.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+public class DataChangeListenerMessagesTest extends AbstractMessagesTest {
+
+  private final String namespace = "urn:protobuff", revision = "2014-07-31",
+      localName = "test";
+
+  @Override
+  @Test
+  public void verifySerialization() throws Exception {
+    NormalizedNodeMessages.InstanceIdentifier.Builder instanceIdentifierBuilder =
+        NormalizedNodeMessages.InstanceIdentifier.newBuilder();
+    NormalizedNodeMessages.PathArgument.Builder pathArgument =
+        NormalizedNodeMessages.PathArgument.newBuilder();
+    pathArgument.setNodeType(NormalizedNodeMessages.QName.newBuilder()
+        .setValue(QName.create(namespace, revision, localName).toString())
+        .build());
+    pathArgument.setValue("test");
+    instanceIdentifierBuilder.addArguments(pathArgument.build());
+
+    NormalizedNodeMessages.InstanceIdentifier expectedOne =
+        instanceIdentifierBuilder.build();
+    DataChangeListenerMessages.DataChanged.Builder builder =
+        DataChangeListenerMessages.DataChanged.newBuilder();
+    builder.addRemovedPaths(expectedOne);
+
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+    DataChangeListenerMessages.DataChanged dataChangedNew =
+        (DataChangeListenerMessages.DataChanged) readFromFile(DataChangeListenerMessages.DataChanged.PARSER);
+    Assert.assertEquals(expectedOne.getArgumentsCount(), dataChangedNew
+        .getRemovedPaths(0).getArgumentsCount());
+    Assert.assertEquals(expectedOne.getArguments(0).getType(), dataChangedNew
+        .getRemovedPaths(0).getArguments(0).getType());
+
+    DataChangeListenerMessages.DataChanged dataChangedOriginal =
+        (DataChangeListenerMessages.DataChanged) readFromTestDataFile(DataChangeListenerMessages.DataChanged.PARSER);
+    Assert.assertEquals(dataChangedNew.getRemovedPathsCount(),
+        dataChangedOriginal.getRemovedPathsCount());
+    Assert.assertEquals(dataChangedNew.getRemovedPaths(0).getArguments(0)
+        .getValue(), dataChangedOriginal.getRemovedPaths(0).getArguments(0)
+        .getValue());
+
+  }
+
+  @Override
+  public String getTestFileName() {
+    return DataChangeListenerMessages.class.getSimpleName();
+  }
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessagesTest.java
new file mode 100644 (file)
index 0000000..a8ade30
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.protobuff.messages.persistent;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the peristent.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+public class PersistentMessagesTest extends AbstractMessagesTest {
+
+  private final String namespace = "urn:protobuff", revision = "2014-07-31",
+      localName = "test";
+
+  @Override
+  @Test
+  public void verifySerialization() throws Exception {
+    NormalizedNodeMessages.InstanceIdentifier.Builder instanceIdentifierBuilder =
+        NormalizedNodeMessages.InstanceIdentifier.newBuilder();
+    NormalizedNodeMessages.PathArgument.Builder pathArgument =
+        NormalizedNodeMessages.PathArgument.newBuilder();
+    pathArgument.setNodeType(NormalizedNodeMessages.QName.newBuilder()
+        .setValue(QName.create(namespace, revision, localName).toString())
+        .build());
+    pathArgument.setValue("test");
+    instanceIdentifierBuilder.addArguments(pathArgument.build());
+    NormalizedNodeMessages.InstanceIdentifier expectedOne =
+        instanceIdentifierBuilder.build();
+
+    PersistentMessages.Modification.Builder builder =
+        PersistentMessages.Modification.newBuilder();
+    builder.setType("test");
+    builder.setPath(expectedOne);
+
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+    PersistentMessages.Modification modificationNew =
+        (PersistentMessages.Modification) readFromFile(PersistentMessages.Modification.PARSER);
+    Assert.assertEquals("test", modificationNew.getType());
+    Assert.assertEquals(expectedOne.getArguments(0).getValue(), modificationNew
+        .getPath().getArguments(0).getValue());
+    Assert.assertEquals(expectedOne.getArguments(0).getType(), modificationNew
+        .getPath().getArguments(0).getType());
+
+    // we will compare with the serialized data that we had shipped
+    PersistentMessages.Modification modificationOriginal =
+        (PersistentMessages.Modification) readFromTestDataFile(PersistentMessages.Modification.PARSER);
+    Assert.assertEquals(modificationOriginal.getPath().getArguments(0)
+        .getValue(), modificationNew.getPath().getArguments(0).getValue());
+    Assert.assertEquals(modificationOriginal.getPath().getArguments(0)
+        .getType(), modificationNew.getPath().getArguments(0).getType());
+
+
+  }
+
+  @Override
+  public String getTestFileName() {
+    return PersistentMessagesTest.class.getSimpleName();
+  }
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessagesTest.java
new file mode 100644 (file)
index 0000000..1d50872
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.protobuff.messages.registration;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the ListenerRegistration.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+public class ListenerRegistrationMessagesTest extends AbstractMessagesTest {
+
+  @Override
+  @Test
+  public void verifySerialization() throws Exception {
+    String testListenerRegistrationPath =
+        "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:notification-test?revision=2014-04-15)family";
+    ListenerRegistrationMessages.RegisterChangeListenerReply.Builder builder =
+        ListenerRegistrationMessages.RegisterChangeListenerReply.newBuilder();
+    builder.setListenerRegistrationPath(testListenerRegistrationPath);
+
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+    ListenerRegistrationMessages.RegisterChangeListenerReply rclrNew =
+        (ListenerRegistrationMessages.RegisterChangeListenerReply) readFromFile(ListenerRegistrationMessages.RegisterChangeListenerReply.PARSER);
+    Assert.assertEquals(testListenerRegistrationPath,
+        rclrNew.getListenerRegistrationPath());
+
+    ListenerRegistrationMessages.RegisterChangeListenerReply rclrOriginal =
+        (ListenerRegistrationMessages.RegisterChangeListenerReply) readFromTestDataFile(ListenerRegistrationMessages.RegisterChangeListenerReply.PARSER);
+    Assert.assertEquals(rclrOriginal.getListenerRegistrationPath(),
+        rclrNew.getListenerRegistrationPath());
+
+  }
+
+  @Override
+  public String getTestFileName() {
+    return ListenerRegistrationMessages.class.getSimpleName();
+  }
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessagesTest.java
new file mode 100644 (file)
index 0000000..45dcd12
--- /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.protobuff.messages.shard;
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the ShardManager.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+
+public class ShardManagerMessagesTest extends AbstractMessagesTest {
+
+  @Test
+  public void verifySerialization() throws Exception {
+    ShardManagerMessages.FindPrimary.Builder builder =
+        ShardManagerMessages.FindPrimary.newBuilder();
+    builder.setShardName("Inventory");
+
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+
+    // Here we will read the same and check we got back what we had saved
+    ShardManagerMessages.FindPrimary findPrimaryNew =
+        (ShardManagerMessages.FindPrimary) readFromFile(ShardManagerMessages.FindPrimary.PARSER);
+
+    Assert.assertEquals("Inventory", findPrimaryNew.getShardName());
+
+    // Here we compare with the version we had shipped to catch any protobuff compiler version
+    // changes
+    ShardManagerMessages.FindPrimary findPrimaryOriginal =
+        (ShardManagerMessages.FindPrimary) readFromTestDataFile(ShardManagerMessages.FindPrimary.PARSER);
+
+    Assert.assertEquals(findPrimaryNew.getShardName(),
+        findPrimaryOriginal.getShardName());
+
+  }
+
+  @Override
+  public String getTestFileName() {
+    return ShardManagerMessagesTest.class.getSimpleName();
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessagesTest.java
new file mode 100644 (file)
index 0000000..c0e91ab
--- /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.protobuff.messages.transaction;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the ShardTransactionChain.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+
+public class ShardTransactionChainMessagesTest extends AbstractMessagesTest {
+
+  @Override
+  @Test
+  public void verifySerialization() throws Exception {
+    String testTransactionChainPath =
+        "/actor/path";
+
+    ShardTransactionChainMessages.CreateTransactionChainReply.Builder builder =
+        ShardTransactionChainMessages.CreateTransactionChainReply.newBuilder();
+    builder.setTransactionChainPath(testTransactionChainPath);
+
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+    // Here we will read the same and check we got back what we had saved
+    ShardTransactionChainMessages.CreateTransactionChainReply replyNew =
+        (ShardTransactionChainMessages.CreateTransactionChainReply) readFromFile(ShardTransactionChainMessages.CreateTransactionChainReply.PARSER);
+
+    Assert.assertEquals(replyNew.getTransactionChainPath(),testTransactionChainPath);
+
+    // the following will compare with the version we had shipped
+    ShardTransactionChainMessages.CreateTransactionChainReply replyOriginal =
+        (ShardTransactionChainMessages.CreateTransactionChainReply) readFromTestDataFile(ShardTransactionChainMessages.CreateTransactionChainReply.PARSER);
+
+
+    Assert.assertEquals(replyOriginal.getTransactionChainPath(),
+        replyNew.getTransactionChainPath());
+
+  }
+
+  @Override
+  public String getTestFileName() {
+    return ShardTransactionChainMessagesTest.class.getSimpleName();
+  }
+
+
+
+}
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java b/opendaylight/md-sal/sal-clustering-commons/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java
new file mode 100644 (file)
index 0000000..6b538da
--- /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.protobuff.messages.transaction;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.protobuff.messages.AbstractMessagesTest;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * This test case is present to ensure that if others have used proper version of protocol buffer
+ * for the ShardTransaction.proto messages
+ *
+ * If a different version of protocol buffer and there is change in serializaiton format
+ * this test would break as we are comparing with protocol buffer 2.5 generated
+ * serialized data.
+ *
+ * @author: syedbahm
+ *
+ */
+
+
+public class ShardTransactionMessagesTest extends AbstractMessagesTest {
+
+  private final String namespace = "urn:protobuff", revision = "2014-07-31",
+      localName = "test";
+
+  @Test
+  public void verifySerialization() throws Exception {
+    NormalizedNodeMessages.InstanceIdentifier.Builder instanceIdentifierBuilder =
+        NormalizedNodeMessages.InstanceIdentifier.newBuilder();
+    NormalizedNodeMessages.PathArgument.Builder pathArgument =
+        NormalizedNodeMessages.PathArgument.newBuilder();
+    pathArgument.setNodeType(NormalizedNodeMessages.QName.newBuilder()
+        .setValue(QName.create(namespace, revision, localName).toString())
+        .build());
+    pathArgument.setValue("test");
+    instanceIdentifierBuilder.addArguments(pathArgument.build());
+    ShardTransactionMessages.ReadData.Builder builder =
+        ShardTransactionMessages.ReadData.newBuilder();
+    NormalizedNodeMessages.InstanceIdentifier expectedOne =
+        instanceIdentifierBuilder.build();
+    builder.setInstanceIdentifierPathArguments(expectedOne);
+
+    writeToFile((com.google.protobuf.GeneratedMessage.Builder<?>) builder);
+
+    // Here we will read the same and check we got back what we had saved
+    ShardTransactionMessages.ReadData readDataNew =
+        (ShardTransactionMessages.ReadData) readFromFile(ShardTransactionMessages.ReadData.PARSER);
+
+
+    Assert.assertEquals(expectedOne.getArgumentsCount(), readDataNew
+        .getInstanceIdentifierPathArguments().getArgumentsCount());
+    Assert.assertEquals(expectedOne.getArguments(0), readDataNew
+        .getInstanceIdentifierPathArguments().getArguments(0));
+
+
+    // the following will compare with the version we had shipped
+    ShardTransactionMessages.ReadData readDataOriginal =
+        (ShardTransactionMessages.ReadData) readFromTestDataFile(ShardTransactionMessages.ReadData.PARSER);
+
+
+    Assert.assertEquals(readDataNew.getInstanceIdentifierPathArguments()
+        .getArguments(0), readDataOriginal.getInstanceIdentifierPathArguments()
+        .getArguments(0));
+
+  }
+
+  @Override
+  public String getTestFileName() {
+    return ShardTransactionMessagesTest.class.getSimpleName();
+  }
+
+
+
+}
similarity index 54%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/augment_choice.xml
rename to opendaylight/md-sal/sal-clustering-commons/src/test/resources/augment_choice.xml
index c5a581cecca69b69b739a0d60d820334aaa16c0d..7de3d077b4af59c33a7e54bc8ec4aeea0d6d23f5 100644 (file)
@@ -1,3 +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
+  ~  */
+  -->
+
 <container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
 
     <c2Leaf>2</c2Leaf>
similarity index 51%
rename from opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/resources/simple_xml_with_attributes.xml
rename to opendaylight/md-sal/sal-clustering-commons/src/test/resources/simple_xml_with_attributes.xml
index 0316d7a4a82ad8259fdbcb5b40790a5ec435b086..934d876747c6e8a83f00fcb890437d98cdaaf839 100644 (file)
@@ -1,3 +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
+  ~  */
+  -->
+
 <container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test" name="test" xmlns:foo="http://www.foo.com/"
            foo:baz="baz">
 
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/DataChangeListenerMessagesData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/DataChangeListenerMessagesData
new file mode 100644 (file)
index 0000000..883bcad
--- /dev/null
@@ -0,0 +1,4 @@
+23
+1
+\ 4test\1a)
+'(urn:protobuff?revision=2014-07-31)test
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ListenerRegistrationMessagesData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ListenerRegistrationMessagesData
new file mode 100644 (file)
index 0000000..1718a01
--- /dev/null
@@ -0,0 +1,2 @@
+
+m(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:notification-test?revision=2014-04-15)family
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/NormalizedNodeMessagesTestData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/NormalizedNodeMessagesTestData
new file mode 100644 (file)
index 0000000..c4ec377
--- /dev/null
@@ -0,0 +1,2 @@
+
+\ 4test\12 testValue\1a\ 4fake
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/PersistentMessagesTestData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/PersistentMessagesTestData
new file mode 100644 (file)
index 0000000..efb8e15
--- /dev/null
@@ -0,0 +1,5 @@
+
+\ 4test\123
+1
+\ 4test\1a)
+'(urn:protobuff?revision=2014-07-31)test
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardManagerMessagesTestData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardManagerMessagesTestData
new file mode 100644 (file)
index 0000000..82eea07
--- /dev/null
@@ -0,0 +1,2 @@
+
+       Inventory
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionChainMessagesTestData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionChainMessagesTestData
new file mode 100644 (file)
index 0000000..577d9c4
--- /dev/null
@@ -0,0 +1,2 @@
+
+\v/actor/path
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionMessagesTestData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ShardTransactionMessagesTestData
new file mode 100644 (file)
index 0000000..db43fa4
--- /dev/null
@@ -0,0 +1,5 @@
+
+3
+1
+\ 4test\1a)
+'(urn:protobuff?revision=2014-07-31)test
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ThreePhaseCommitCohortMessagesTestData b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/ThreePhaseCommitCohortMessagesTestData
new file mode 100644 (file)
index 0000000..e19a122
--- /dev/null
@@ -0,0 +1 @@
+\b\ 1
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/readme.txt b/opendaylight/md-sal/sal-clustering-commons/src/test/resources/version-compatibility-serialized-data/readme.txt
new file mode 100644 (file)
index 0000000..06a561e
--- /dev/null
@@ -0,0 +1,18 @@
+This directory contains one serialized test data file for one of the messages in each .proto file.
+These files are utilized as part of the  test cases, mostly to fail the test cases in case some engineer has used
+a different version of protocol buffer than what we ship with (Protocol Buffer 2.5.0) to generate the messages source f
+file.
+
+1. If you see protocolbuffer version/invalid message exception in the test case
+  1. ensure you are using the right version of protocol buffer/protoc compiler i.e protocol
+
+2. If you have knowingly updated an existing .proto message than please update the corresponding version-compatibility-serialized-data
+file. You can get the file by commenting out the test file deletion in AbstractMessagesTest look for comments
+
+ /* we will delete only the test file -- comment below if you want to capture the
+       version-compatibility-serialized-data test data file.The file will be generated at root of the sal-protocolbuffer-encoding
+       and you need to move it to version-compatbility-serialized-data folder renaming the file to include suffix <TestFileName>"Data"
+  */
+
+3. If you are creating a new .proto file -- Follow an existing test case e.g. ThreePhaseCommitCohortMessagesTest to
+   check how the test case is created and create the corresponding serialized test data file in version-compatibility-serialized-data
diff --git a/opendaylight/md-sal/sal-clustering-config/pom.xml b/opendaylight/md-sal/sal-clustering-config/pom.xml
new file mode 100644 (file)
index 0000000..d726823
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>sal-parent</artifactId>
+    <version>1.1-SNAPSHOT</version>
+  </parent>
+  <artifactId>sal-clustering-config</artifactId>
+  <description>Configuration files for md-sal clustering</description>
+  <packaging>jar</packaging>
+  <build>
+    <plugins>
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/initial/*.conf</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/05-clustering.xml.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/05-clustering.xml.conf
new file mode 100644 (file)
index 0000000..7891ee2
--- /dev/null
@@ -0,0 +1,85 @@
+<?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: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>distributed-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>distributed-operational-store-service</name>
+                    </operational-data-store>
+                </module>
+
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-operational-datastore-provider</type>
+                    <name>distributed-operational-store-module</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:config:distributed-datastore-provider">prefix:distributed-config-datastore-provider</type>
+                    <name>distributed-config-store-module</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:config:remote-rpc-connector">prefix:remote-rpc-connector</type>
+                    <name>remote-rpc-connector</name>
+                    <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:remote-rpc-connector">
+                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+                        <name>dom-broker</name>
+                    </dom-broker>
+                </module>
+
+            </modules>
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+                <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>distributed-config-store-service</name>
+                        <provider>/modules/module[type='distributed-config-datastore-provider'][name='distributed-config-store-module']</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>distributed-operational-store-service</name>
+                        <provider>/modules/module[type='distributed-operational-datastore-provider'][name='distributed-operational-store-module']</provider>
+                    </instance>
+                </service>
+
+            </services>
+        </data>
+    </configuration>
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
+    </required-capabilities>
+</snapshot>
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf
new file mode 100644 (file)
index 0000000..9749ae2
--- /dev/null
@@ -0,0 +1,55 @@
+
+odl-cluster-data {
+  akka {
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "<CHANGE_ME>"
+        port = 2550
+           maximum-frame-size = 2097152
+           send-buffer-size = 52428800
+           receive-buffer-size = 52428800
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-data@<CHANGE_ME>:2550"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
+
+odl-cluster-rpc {
+  akka {
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "<CHANGE_ME>"
+        port = 2551
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@<CHANGE_ME>:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/module-shards.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/module-shards.conf
new file mode 100644 (file)
index 0000000..8449abb
--- /dev/null
@@ -0,0 +1,70 @@
+# This file describes which shards live on which members
+# The format for a module-shards is as follows,
+# {
+#    name = "<friendly_name_of_the_module>"
+#    shards = [
+#        {
+#            name="<any_name_that_is_unique_for_the_module>"
+#            replicas = [
+#                "<name_of_member_on_which_to_run>"
+#            ]
+#     ]
+# }
+#
+# For Helium we support only one shard per module. Beyond Helium
+# we will support more than 1
+# The replicas section is a collection of member names. This information
+# will be used to decide on which members replicas of a particular shard will be
+# located. Once replication is integrated with the distributed data store then
+# this section can have multiple entries.
+#
+#
+
+
+module-shards = [
+    {
+        name = "default"
+        shards = [
+            {
+                name="default"
+                replicas = [
+                    "member-1"
+                ]
+            }
+        ]
+    },
+    {
+        name = "topology"
+        shards = [
+            {
+                name="topology"
+                replicas = [
+                    "member-1"
+                ]
+            }
+        ]
+    },
+    {
+        name = "inventory"
+        shards = [
+            {
+                name="inventory"
+                replicas = [
+                    "member-1"
+                ]
+            }
+        ]
+    },
+         {
+             name = "toaster"
+             shards = [
+                 {
+                     name="toaster"
+                     replicas = [
+                         "member-1"
+                     ]
+                 }
+             ]
+         }
+
+]
diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/modules.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/modules.conf
new file mode 100644 (file)
index 0000000..68347ee
--- /dev/null
@@ -0,0 +1,32 @@
+# This file should describe all the modules that need to be placed in a separate shard
+# The format of the configuration is as follows
+# {
+#    name = "<friendly_name_of_module>"
+#    namespace = "<the yang namespace of the module>"
+#    shard-strategy = "module"
+# }
+#
+# Note that at this time the only shard-strategy we support is module which basically
+# will put all the data of a single module in two shards (one for config and one for
+# operational data)
+
+modules = [
+    {
+        name = "inventory"
+        namespace = "urn:opendaylight:inventory"
+        shard-strategy = "module"
+    },
+
+    {
+        name = "topology"
+        namespace = "urn:TBD:params:xml:ns:yang:network-topology"
+        shard-strategy = "module"
+    },
+
+    {
+        name = "toaster"
+        namespace = "http://netconfcentral.org/ns/toaster"
+        shard-strategy = "module"
+    }
+
+]
index 3449c5488e475a45a27b10f4cefd0471ccf4b09f..e46fe1fe78405d912ae8c12ebcfde944abdc4bc8 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>concepts</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>util</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-common</artifactId>
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/ReadFailedException.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/ReadFailedException.java
new file mode 100644 (file)
index 0000000..b0a7807
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.md.sal.common.api.data;
+
+import org.opendaylight.yangtools.util.concurrent.ExceptionMapper;
+import org.opendaylight.yangtools.yang.common.OperationFailedException;
+import org.opendaylight.yangtools.yang.common.RpcError;
+
+/**
+ * An exception for a failed read.
+ */
+public class ReadFailedException extends OperationFailedException {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final ExceptionMapper<ReadFailedException> MAPPER =
+            new ExceptionMapper<ReadFailedException>("read", ReadFailedException.class) {
+                @Override
+                protected ReadFailedException newWithCause(String message, Throwable cause) {
+                    return new ReadFailedException(message, cause);
+                }
+    };
+
+    public ReadFailedException(String message, RpcError... errors) {
+        super(message, errors);
+    }
+
+    public ReadFailedException(String message, Throwable cause, RpcError... errors) {
+        super(message, cause, errors);
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionCommitDeadlockException.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionCommitDeadlockException.java
new file mode 100644 (file)
index 0000000..60313bf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.api.data;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+
+import com.google.common.base.Function;
+
+/**
+ * A type of TransactionCommitFailedException that indicates a situation that would result in a
+ * threading deadlock. This can occur if a caller that submits a write transaction tries to perform
+ * a blocking call via one of the <code>get</code> methods on the returned ListenableFuture. Callers
+ * should process the commit result asynchronously (via Futures#addCallback) to ensure deadlock
+ * won't occur.
+ *
+ * @author Thomas Pantelis
+ */
+public class TransactionCommitDeadlockException extends TransactionCommitFailedException {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String DEADLOCK_MESSAGE =
+            "An attempt to block on a ListenableFuture via a get method from a write " +
+            "transaction submit was detected that would result in deadlock. The commit " +
+            "result must be obtained asynchronously, e.g. via Futures#addCallback, to avoid deadlock.";
+
+    public static Function<Void, Exception> DEADLOCK_EXECUTOR_FUNCTION = new Function<Void, Exception>() {
+        @Override
+        public Exception apply(Void notUsed) {
+            return new TransactionCommitDeadlockException( DEADLOCK_MESSAGE,
+                    RpcResultBuilder.newError(ErrorType.APPLICATION, "lock-denied", DEADLOCK_MESSAGE));
+        }
+    };
+
+    public TransactionCommitDeadlockException(String message, final RpcError... errors) {
+        super(message, errors);
+    }
+}
index 18a857e1d5c4bd0816674a6af99070c2a9dc1e76..7ac76e47b15048bbabfe70f49ed1c19fa48deb12 100644 (file)
@@ -7,14 +7,8 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-import java.util.Arrays;
-import java.util.List;
-
+import org.opendaylight.yangtools.yang.common.OperationFailedException;
 import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-
-import com.google.common.collect.ImmutableList;
 
 /**
  *
@@ -24,41 +18,16 @@ import com.google.common.collect.ImmutableList;
  * failed.
  *
  */
-public class TransactionCommitFailedException extends Exception {
+public class TransactionCommitFailedException extends OperationFailedException {
 
     private static final long serialVersionUID = 1L;
 
-    private final List<RpcError> errorList;
-
     public TransactionCommitFailedException(final String message, final RpcError... errors) {
         this(message, null, errors);
     }
 
     public TransactionCommitFailedException(final String message, final Throwable cause,
                                             final RpcError... errors) {
-        super(message, cause);
-
-        if( errors != null && errors.length > 0 ) {
-            errorList = ImmutableList.<RpcError>builder().addAll( Arrays.asList( errors ) ).build();
-        }
-        else {
-            // Add a default RpcError.
-            errorList = ImmutableList.of(RpcResultBuilder.newError(ErrorType.APPLICATION, null,
-                    getMessage(), null, null, getCause()));
-        }
-    }
-
-    /**
-     * Returns additional error information about this exception.
-     *
-     * @return a List of RpcErrors. There is always at least one RpcError.
-     */
-    public List<RpcError> getErrorList() {
-        return errorList;
-    }
-
-    @Override
-    public String getMessage() {
-        return new StringBuilder( super.getMessage() ).append(", errors: ").append( errorList ).toString();
+        super(message, cause, errors);
     }
 }
index 9108f8603b2c5fd42fea75ccdf06ec7a860d4cbf..e42c86a993f14dc1362b6c7ac96e1f2a16f81b0a 100644 (file)
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-api</artifactId>
diff --git a/opendaylight/md-sal/sal-distributed-datastore/client.conf b/opendaylight/md-sal/sal-distributed-datastore/client.conf
new file mode 100644 (file)
index 0000000..90bfb4c
--- /dev/null
@@ -0,0 +1,36 @@
+ODLCluster{
+  akka {
+    actor {
+      serialize-messages = on
+
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+                  "com.google.protobuf.GeneratedMessage" = proto
+                  "com.google.protobuf.GeneratedMessage$GeneratedExtension" = proto
+                  "com.google.protobuf.FieldSet" = proto
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2552
+       maximum-frame-size = 2097152
+       send-buffer-size = 52428800
+       receive-buffer-size = 52428800
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster@127.0.0.1:2550"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
index 94c895dab385a92e3f547099ac83010cb7e517ec..848d425bf9d8a712d42a873b564a1657b9d95953 100644 (file)
 
     <dependency>
         <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-protocolbuffer-encoding</artifactId>
+        <artifactId>sal-clustering-commons</artifactId>
         <version>1.1-SNAPSHOT</version>
     </dependency>
 
             <Private-Package></Private-Package>
             <Import-Package>!*snappy;!org.jboss.*;*</Import-Package>
             <Embed-Dependency>
-                sal-protocolbuffer-encoding;
+                sal-clustering-commons;
                 sal-akka-raft;
                 !sal*;
                 !*config-api*;
diff --git a/opendaylight/md-sal/sal-distributed-datastore/server.conf b/opendaylight/md-sal/sal-distributed-datastore/server.conf
new file mode 100644 (file)
index 0000000..6209adf
--- /dev/null
@@ -0,0 +1,37 @@
+
+ODLCluster{
+  akka {
+    actor {
+      serialize-messages = on
+
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+                  "com.google.protobuf.GeneratedMessage" = proto
+                  "com.google.protobuf.GeneratedMessage$GeneratedExtension" = proto
+                  "com.google.protobuf.FieldSet" = proto
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2550
+       maximum-frame-size = 2097152
+       send-buffer-size = 52428800
+       receive-buffer-size = 52428800
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster@127.0.0.1:2550"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
index baf04fe43b771fddc1c009d11aed056dea6bbe24..15c0548761ecd96afee865025fc573d5a2d38c6e 100644 (file)
@@ -20,8 +20,8 @@ public class ActorSystemFactory {
 
         @Nullable @Override public ActorSystem apply(@Nullable Void aVoid) {
                 ActorSystem system =
-                    ActorSystem.create("opendaylight-cluster", ConfigFactory
-                        .load().getConfig("ODLCluster"));
+                    ActorSystem.create("opendaylight-cluster-data", ConfigFactory
+                        .load().getConfig("odl-cluster-data"));
                 system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
                 return system;
         }
index 955e4bbf220cc458cd20638967a91c849dab6909..abc69f18975aeb671713e955e11498f1c7d55050 100644 (file)
@@ -10,7 +10,8 @@ package org.opendaylight.controller.cluster.datastore;
 
 import com.google.common.base.Preconditions;
 import com.google.protobuf.GeneratedMessage;
-import org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.UnknownFieldSet;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
 import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
 import org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages;
@@ -43,7 +44,28 @@ public class CompositeModificationPayload extends Payload implements
         PersistentMessages.CompositeModification modification = payload
             .getExtension(
                 org.opendaylight.controller.mdsal.CompositeModificationPayload.modification);
-        payload.getExtension(KeyValueMessages.value);
+
+
+
+        // The extension was put in the unknown field.
+        // This is because extensions need to be registered
+        // see org.opendaylight.controller.mdsal.CompositeModificationPayload.registerAllExtensions
+        // also see https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/ExtensionRegistry
+        // If that is not done then on the other end the extension shows up as an unknown field
+        // Need to figure out a better way to do this
+        if(payload.getUnknownFields().hasField(2)){
+            UnknownFieldSet.Field field =
+                payload.getUnknownFields().getField(2);
+
+            try {
+                modification =
+                    PersistentMessages.CompositeModification
+                        .parseFrom(field.getLengthDelimitedList().get(0));
+            } catch (InvalidProtocolBufferException e) {
+
+            }
+        }
+
         return new CompositeModificationPayload(modification);
     }
 
index 3af6f56a2c78fe40ddd9cfa60ac5fe7bd60348c9..cdf04dd093e95676b6ce9d635125abc8aa2b602e 100644 (file)
@@ -12,6 +12,7 @@ import akka.actor.Props;
 import akka.japi.Creator;
 import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
 import org.opendaylight.controller.cluster.datastore.messages.DataChangedReply;
+import org.opendaylight.controller.cluster.datastore.messages.EnableNotification;
 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.YangInstanceIdentifier;
@@ -22,6 +23,7 @@ public class DataChangeListener extends AbstractUntypedActor {
     private final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener;
     private final SchemaContext schemaContext;
     private final YangInstanceIdentifier pathId;
+    private boolean notificationsEnabled = false;
 
     public DataChangeListener(SchemaContext schemaContext,
                               AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener, YangInstanceIdentifier pathId) {
@@ -31,16 +33,31 @@ public class DataChangeListener extends AbstractUntypedActor {
     }
 
     @Override public void handleReceive(Object message) throws Exception {
-        if(message.getClass().equals(DataChanged.SERIALIZABLE_CLASS)){
-            DataChanged reply = DataChanged.fromSerialize(schemaContext,message, pathId);
-            AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>>
-                change = reply.getChange();
-            this.listener.onDataChanged(change);
-
-            if(getSender() != null){
-                getSender().tell(new DataChangedReply().toSerializable(), getSelf());
-            }
+        if(message instanceof DataChanged){
+            dataChanged(message);
+        } else if(message instanceof EnableNotification){
+            enableNotification((EnableNotification) message);
+        }
+    }
+
+    private void enableNotification(EnableNotification message) {
+        notificationsEnabled = message.isEnabled();
+    }
+
+    public void dataChanged(Object message) {
+
+        // Do nothing if notifications are not enabled
+        if(!notificationsEnabled){
+            return;
+        }
+
+        DataChanged reply = (DataChanged) message;
+        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>>
+            change = reply.getChange();
+        this.listener.onDataChanged(change);
 
+        if(getSender() != null){
+            getSender().tell(new DataChangedReply(), getSelf());
         }
     }
 
index cd9c330268e1316f2f76296bc4736bc3e7c8487f..a4ca4562685d4f4b3dc717588d0e35ede957d466 100644 (file)
@@ -30,6 +30,6 @@ public class DataChangeListenerProxy implements AsyncDataChangeListener<YangInst
 
     @Override public void onDataChanged(
         AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
-        dataChangeListenerActor.tell(new DataChanged(schemaContext,change).toSerializable(), null);
+        dataChangeListenerActor.tell(new DataChanged(schemaContext,change), null);
     }
 }
index 2ef8e5f449f8df564ae42943c6597224b832bcb4..479af79748033342041f32fe5221e68f78bf1c2f 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
 import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
@@ -30,7 +32,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 /**
@@ -41,6 +42,7 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
     private static final Logger
         LOG = LoggerFactory.getLogger(DistributedDataStore.class);
 
+    private static final int DEFAULT_EXECUTOR_POOL_SIZE = 10;
 
     private final String type;
     private final ActorContext actorContext;
@@ -55,10 +57,10 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
      * This is typically used when we need to make a request to an actor and
      * wait for it's response and the consumer needs to be provided a Future.
      *
-     * FIXME : Make the thread pool configurable
+     * FIXME : Make the thread pool size configurable.
      */
-    private final ExecutorService executor =
-        Executors.newFixedThreadPool(10);
+    private final ListeningExecutorService executor =
+        MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(DEFAULT_EXECUTOR_POOL_SIZE));
 
     public DistributedDataStore(ActorSystem actorSystem, String type, ClusterWrapper cluster, Configuration configuration) {
         this(new ActorContext(actorSystem, actorSystem
@@ -82,18 +84,29 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener, Au
 
         String shardName = ShardStrategyFactory.getStrategy(path).findShard(path);
 
-        Object result = actorContext.executeShardOperation(shardName,
+        Object result = actorContext.executeLocalShardOperation(shardName,
             new RegisterChangeListener(path, dataChangeListenerActor.path(),
-                scope).toSerializable(),
+                scope),
             ActorContext.ASK_DURATION
         );
 
-        RegisterChangeListenerReply reply = RegisterChangeListenerReply.fromSerializable(actorContext.getActorSystem(),result);
-        return new DataChangeListenerRegistrationProxy(actorContext.actorSelection(reply.getListenerRegistrationPath()), listener, dataChangeListenerActor);
+        if (result != null) {
+            RegisterChangeListenerReply reply = (RegisterChangeListenerReply) result;
+            return new DataChangeListenerRegistrationProxy(actorContext
+                .actorSelection(reply.getListenerRegistrationPath()), listener,
+                dataChangeListenerActor);
+        }
+
+        LOG.debug(
+            "No local shard for shardName {} was found so returning a noop registration",
+            shardName);
+        return new NoOpDataChangeListenerRegistration(listener);
     }
 
 
 
+
+
     @Override
     public DOMStoreTransactionChain createTransactionChain() {
         return new TransactionChainProxy(actorContext, executor, schemaContext);
index 692d1b4954007b33e285b271ebb61952f0bcb0ed..6d87271f00d54fcdbf6ca70c27843248b0bbc1b9 100644 (file)
@@ -20,7 +20,7 @@ public class DistributedDataStoreFactory {
             new DistributedDataStore(actorSystem, name, new ClusterWrapperImpl(actorSystem),config );
        ShardStrategyFactory.setConfiguration(config);
         schemaService
-            .registerSchemaServiceListener(dataStore);
+            .registerSchemaContextListener(dataStore);
         return dataStore;
 
     }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/NoOpDataChangeListenerRegistration.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/NoOpDataChangeListenerRegistration.java
new file mode 100644 (file)
index 0000000..14af31e
--- /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 org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * When a consumer registers a data change listener and no local shard is
+ * available to register that listener with then we return an instance of
+ * NoOpDataChangeListenerRegistration
+ *
+ * <p>
+ *
+ * The NoOpDataChangeListenerRegistration as it's name suggests does
+ * nothing when an operation is invoked on it
+ */
+public class NoOpDataChangeListenerRegistration
+    implements ListenerRegistration {
+
+    private final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>
+        listener;
+
+    public <L extends AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> NoOpDataChangeListenerRegistration(
+        AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener) {
+
+        this.listener = listener;
+    }
+
+    @Override
+    public AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> getInstance() {
+        return listener;
+    }
+
+    @Override public void close() {
+
+    }
+}
index 999d0f8bafca9639baa70ea7c893656f87704ae7..10dbbc84d873ee54b5421643c00b046043e58114 100644 (file)
@@ -15,6 +15,7 @@ import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import akka.japi.Creator;
 import akka.serialization.Serialization;
+import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
@@ -25,6 +26,7 @@ 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.EnableNotification;
 import org.opendaylight.controller.cluster.datastore.messages.ForwardedCommitTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolved;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
@@ -32,6 +34,8 @@ import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeList
 import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
 import org.opendaylight.controller.cluster.datastore.modification.Modification;
 import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.RaftActor;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
@@ -41,11 +45,15 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import scala.concurrent.duration.FiniteDuration;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A Shard represents a portion of the logical data tree <br/>
@@ -55,6 +63,8 @@ import java.util.concurrent.Executors;
  */
 public class Shard extends RaftActor {
 
+    private static final ConfigParams configParams = new ShardConfigParams();
+
     public static final String DEFAULT_NAME = "default";
 
     private final ListeningExecutorService storeExecutor =
@@ -74,12 +84,14 @@ public class Shard extends RaftActor {
 
     private final String name;
 
-    private SchemaContext schemaContext;
+    private volatile SchemaContext schemaContext;
 
     private final ShardStats shardMBean;
 
+    private final List<ActorSelection> dataChangeListeners = new ArrayList<>();
+
     private Shard(String name, Map<String, String> peerAddresses) {
-        super(name, peerAddresses);
+        super(name, peerAddresses, Optional.of(configParams));
 
         this.name = name;
 
@@ -116,8 +128,8 @@ public class Shard extends RaftActor {
             } else if(getLeader() != null){
                 getLeader().forward(message, getContext());
             }
-        } else if (message.getClass().equals(RegisterChangeListener.SERIALIZABLE_CLASS)) {
-            registerChangeListener(RegisterChangeListener.fromSerializable(getContext().system(), message));
+        } else if (message instanceof RegisterChangeListener) {
+            registerChangeListener((RegisterChangeListener) message);
         } else if (message instanceof UpdateSchemaContext) {
             updateSchemaContext((UpdateSchemaContext) message);
         } else if (message instanceof ForwardedCommitTransaction) {
@@ -136,13 +148,29 @@ public class Shard extends RaftActor {
         }
     }
 
+   private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,String transactionId){
+      if(createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_ONLY.ordinal()){
+        return getContext().actorOf(
+            ShardTransaction.props( store.newReadOnlyTransaction(), getSelf(), schemaContext), transactionId);
+
+      }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_WRITE.ordinal()){
+        return getContext().actorOf(
+            ShardTransaction.props( store.newReadWriteTransaction(), getSelf(), schemaContext), transactionId);
+
+
+      }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.WRITE_ONLY.ordinal()){
+        return getContext().actorOf(
+            ShardTransaction.props( store.newWriteOnlyTransaction(), getSelf(), schemaContext), transactionId);
+      }else{
+        throw new IllegalArgumentException ("CreateTransaction message has unidentified transaction type="+createTransaction.getTransactionType()) ;
+      }
+   }
+
     private void createTransaction(CreateTransaction createTransaction) {
-        DOMStoreReadWriteTransaction transaction =
-            store.newReadWriteTransaction();
+
         String transactionId = "shard-" + createTransaction.getTransactionId();
         LOG.info("Creating transaction : {} " , transactionId);
-        ActorRef transactionActor = getContext().actorOf(
-            ShardTransaction.props(transaction, getSelf(), schemaContext), transactionId);
+        ActorRef transactionActor = createTypedTransactionActor(createTransaction,transactionId);
 
         getSender()
             .tell(new CreateTransactionReply(Serialization.serializedActorPath(transactionActor), createTransaction.getTransactionId()).toSerializable(),
@@ -155,10 +183,23 @@ public class Shard extends RaftActor {
             modificationToCohort.remove(serialized);
         if (cohort == null) {
             LOG.error(
-                "Could not find cohort for modification : " + modification);
+                "Could not find cohort for modification : {}", modification);
             LOG.info("Writing modification using a new transaction");
-            modification.apply(store.newReadWriteTransaction());
-            return;
+            DOMStoreReadWriteTransaction transaction =
+                store.newReadWriteTransaction();
+            modification.apply(transaction);
+            DOMStoreThreePhaseCommitCohort commitCohort = transaction.ready();
+            ListenableFuture<Void> future =
+                commitCohort.preCommit();
+            try {
+                future.get();
+                future = commitCohort.commit();
+                future.get();
+            } catch (InterruptedException e) {
+                LOG.error("Failed to commit", e);
+            } catch (ExecutionException e) {
+                LOG.error("Failed to commit", e);
+            }
         }
 
         final ListenableFuture<Void> future = cohort.commit();
@@ -213,6 +254,16 @@ public class Shard extends RaftActor {
             .system().actorSelection(
                 registerChangeListener.getDataChangeListenerPath());
 
+
+        // Notify the listener if notifications should be enabled or not
+        // If this shard is the leader then it will enable notifications else
+        // it will not
+        dataChangeListenerPath.tell(new EnableNotification(isLeader()), getSelf());
+
+        // Now store a reference to the data change listener so it can be notified
+        // at a later point if notifications should be enabled or disabled
+        dataChangeListeners.add(dataChangeListenerPath);
+
         AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>
             listener = new DataChangeListenerProxy(schemaContext,dataChangeListenerPath);
 
@@ -227,7 +278,7 @@ public class Shard extends RaftActor {
         LOG.debug("registerDataChangeListener sending reply, listenerRegistrationPath = " + listenerRegistration.path().toString());
 
         getSender()
-            .tell(new RegisterChangeListenerReply(listenerRegistration.path()).toSerializable(),
+            .tell(new RegisterChangeListenerReply(listenerRegistration.path()),
                 getSelf());
     }
 
@@ -248,7 +299,14 @@ public class Shard extends RaftActor {
         if(data instanceof CompositeModificationPayload){
             Object modification =
                 ((CompositeModificationPayload) data).getModification();
-            commit(clientActor, modification);
+
+            if(modification != null){
+                commit(clientActor, modification);
+            } else {
+                LOG.error("modification is null - this is very unexpected");
+            }
+
+
         } else {
             LOG.error("Unknown state received {}", data);
         }
@@ -263,7 +321,29 @@ public class Shard extends RaftActor {
         throw new UnsupportedOperationException("applySnapshot");
     }
 
+    @Override protected void onStateChanged() {
+        for(ActorSelection dataChangeListener : dataChangeListeners){
+            dataChangeListener.tell(new EnableNotification(isLeader()), getSelf());
+        }
+
+        if(getLeaderId() != null){
+            shardMBean.setLeader(getLeaderId());
+        }
+
+        shardMBean.setRaftState(getRaftState().name());
+    }
+
     @Override public String persistenceId() {
         return this.name;
     }
+
+
+    private static class ShardConfigParams extends DefaultConfigParamsImpl {
+        public static final FiniteDuration HEART_BEAT_INTERVAL =
+            new FiniteDuration(500, TimeUnit.MILLISECONDS);
+
+        @Override public FiniteDuration getHeartBeatInterval() {
+            return HEART_BEAT_INTERVAL;
+        }
+    }
 }
index 5fbce4cd98900be65053939ca7a51d4f7a929a98..64c6821120f94f99a389c12700757a7b8c7266f5 100644 (file)
@@ -18,7 +18,10 @@ import akka.cluster.ClusterEvent;
 import akka.japi.Creator;
 import akka.japi.Function;
 import com.google.common.base.Preconditions;
+import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard;
 import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.LocalShardFound;
+import org.opendaylight.controller.cluster.datastore.messages.LocalShardNotFound;
 import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolved;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
@@ -31,35 +34,27 @@ import java.util.Map;
 
 /**
  * The ShardManager has the following jobs,
- * <p>
+ * <ul>
  * <li> Create all the local shard replicas that belong on this cluster member
+ * <li> Find the address of the local shard
  * <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>
+ * <li> Monitor the cluster members and store their addresses
+ * <ul>
  */
 public class ShardManager extends AbstractUntypedActor {
 
     // Stores a mapping between a member name and the address of the member
+    // Member names look like "member-1", "member-2" etc and are as specified
+    // in configuration
     private final Map<String, Address> memberNameToAddress = new HashMap<>();
 
+    // Stores a mapping between a shard name and it's corresponding information
+    // Shard names look like inventory, topology etc and are as specified in
+    // configuration
     private final Map<String, ShardInformation> localShards = new HashMap<>();
 
-
+    // The type of a ShardManager reflects the type of the datastore itself
+    // A data store could be of type config/operational
     private final String type;
 
     private final ClusterWrapper cluster;
@@ -102,7 +97,8 @@ public class ShardManager extends AbstractUntypedActor {
         if (message.getClass().equals(FindPrimary.SERIALIZABLE_CLASS)) {
             findPrimary(
                 FindPrimary.fromSerializable(message));
-
+        } else if(message instanceof FindLocalShard){
+            findLocalShard((FindLocalShard) message);
         } else if (message instanceof UpdateSchemaContext) {
             updateSchemaContext(message);
         } else if (message instanceof ClusterEvent.MemberUp){
@@ -117,6 +113,18 @@ public class ShardManager extends AbstractUntypedActor {
 
     }
 
+    private void findLocalShard(FindLocalShard message) {
+        ShardInformation shardInformation =
+            localShards.get(message.getShardName());
+
+        if(shardInformation != null){
+            getSender().tell(new LocalShardFound(shardInformation.getActor()), getSelf());
+            return;
+        }
+
+        getSender().tell(new LocalShardNotFound(message.getShardName()), getSelf());
+    }
+
     private void ignoreMessage(Object message){
         LOG.debug("Unhandled message : " + message);
     }
@@ -137,6 +145,11 @@ public class ShardManager extends AbstractUntypedActor {
         }
     }
 
+    /**
+     * Notifies all the local shards of a change in the schema context
+     *
+     * @param message
+     */
     private void updateSchemaContext(Object message) {
         for(ShardInformation info : localShards.values()){
             info.getActor().tell(message,getSelf());
@@ -180,10 +193,7 @@ public class ShardManager extends AbstractUntypedActor {
         getSender().tell(new PrimaryNotFound(shardName).toSerializable(), getSelf());
     }
 
-    private String
-
-
-    getShardActorPath(String shardName, String memberName) {
+    private String getShardActorPath(String shardName, String memberName) {
         Address address = memberNameToAddress.get(memberName);
         if(address != null) {
             return address.toString() + "/user/shardmanager-" + this.type + "/"
@@ -193,11 +203,23 @@ public class ShardManager extends AbstractUntypedActor {
         return null;
     }
 
+    /**
+     * Construct the name of the shard actor given the name of the member on
+     * which the shard resides and the name of the shard
+     *
+     * @param memberName
+     * @param shardName
+     * @return
+     */
     private String getShardActorName(String memberName, String shardName){
         return memberName + "-shard-" + shardName + "-" + this.type;
     }
 
-    // Create the shards that are local to this member
+    /**
+     * Create shards that are local to the member on which the ShardManager
+     * runs
+     *
+     */
     private void createLocalShards() {
         String memberName = this.cluster.getCurrentMemberName();
         List<String> memberShardNames =
@@ -214,6 +236,12 @@ public class ShardManager extends AbstractUntypedActor {
 
     }
 
+    /**
+     * Given the name of the shard find the addresses of all it's peers
+     *
+     * @param shardName
+     * @return
+     */
     private Map<String, String> getPeerAddresses(String shardName){
 
         Map<String, String> peerAddresses = new HashMap<>();
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java
new file mode 100644 (file)
index 0000000..f78935b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ *  This program and the accompanying materials are made available under the
+ *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ *  and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardReadTransaction extends ShardTransaction {
+  private final DOMStoreReadTransaction transaction;
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+
+  public ShardReadTransaction(DOMStoreReadTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(shardActor, schemaContext);
+    this.transaction = transaction;
+
+  }
+
+  public ShardReadTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(transactionChain, shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+    if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readData(transaction,ReadData.fromSerializable(message));
+    } else {
+      super.handleReceive(message);
+    }
+  }
+  protected void closeTransaction(CloseTransaction message) {
+    transaction.close();
+    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+    getSelf().tell(PoisonPill.getInstance(), getSelf());
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java
new file mode 100644 (file)
index 0000000..6733bcf
--- /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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+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.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardReadWriteTransaction extends ShardTransaction {
+  private final DOMStoreReadWriteTransaction transaction;
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+  public ShardReadWriteTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(transactionChain,  shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  public ShardReadWriteTransaction(DOMStoreReadWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super( shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+    if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readData(transaction,ReadData.fromSerializable(message));
+    }else if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      writeData(transaction, WriteData.fromSerializable(message, schemaContext));
+    } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      mergeData(transaction, MergeData.fromSerializable(message, schemaContext));
+    } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      deleteData(transaction,DeleteData.fromSerizalizable(message));
+    } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readyTransaction(transaction,new ReadyTransaction());
+    }else {
+      super.handleReceive(message);
+    }
+  }
+
+  protected void closeTransaction(CloseTransaction message) {
+    transaction.close();
+    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+    getSelf().tell(PoisonPill.getInstance(), getSelf());
+  }
+}
index 737f57bf5d7314536f5fc20b1cbc45167f1b6e97..3a916bda2c6e163d75c4d39a0c4d80b94b823fb2 100644 (file)
@@ -9,7 +9,6 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
-import akka.actor.PoisonPill;
 import akka.actor.Props;
 import akka.event.Logging;
 import akka.event.LoggingAdapter;
@@ -17,7 +16,6 @@ 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;
@@ -34,9 +32,11 @@ import org.opendaylight.controller.cluster.datastore.modification.ImmutableCompo
 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.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.controller.sal.core.spi.data.DOMStoreWriteTransaction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -65,170 +65,200 @@ import java.util.concurrent.ExecutionException;
  * <li> {@link org.opendaylight.controller.cluster.datastore.messages.CloseTransaction}
  * </p>
  */
-public class ShardTransaction extends AbstractUntypedActor {
-
-    private final ActorRef shardActor;
-    private final SchemaContext schemaContext;
-
-    // FIXME : see below
-    // If transactionChain is not null then this transaction is part of a
-    // transactionChain. Not really clear as to what that buys us
-    private final DOMStoreTransactionChain transactionChain;
-
-    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, SchemaContext schemaContext) {
-        this(null, transaction, shardActor, schemaContext);
-    }
-
-    public ShardTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadWriteTransaction transaction,
-        ActorRef shardActor, SchemaContext schemaContext) {
-        this.transactionChain = transactionChain;
-        this.transaction = transaction;
-        this.shardActor = shardActor;
-        this.schemaContext = schemaContext;
-    }
-
-
-
-    public static Props props(final DOMStoreReadWriteTransaction transaction,
-        final ActorRef shardActor, final SchemaContext schemaContext) {
-        return Props.create(new Creator<ShardTransaction>() {
-
-            @Override
-            public ShardTransaction create() throws Exception {
-                return new ShardTransaction(transaction, shardActor, schemaContext);
-            }
-        });
-    }
-
-    public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadWriteTransaction transaction,
-        final ActorRef shardActor, final SchemaContext schemaContext) {
-        return Props.create(new Creator<ShardTransaction>() {
-
-            @Override
-            public ShardTransaction create() throws Exception {
-                return new ShardTransaction(transactionChain, transaction, shardActor, schemaContext);
-            }
-        });
+public abstract class ShardTransaction extends AbstractUntypedActor {
+
+  private final ActorRef shardActor;
+  protected final SchemaContext schemaContext;
+
+  // FIXME : see below
+  // If transactionChain is not null then this transaction is part of a
+  // transactionChain. Not really clear as to what that buys us
+  private final DOMStoreTransactionChain transactionChain;
+
+
+  private final MutableCompositeModification modification =
+      new MutableCompositeModification();
+
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+
+  protected ShardTransaction(
+                          ActorRef shardActor, SchemaContext schemaContext) {
+    this(null,  shardActor, schemaContext);
+  }
+
+  protected ShardTransaction(DOMStoreTransactionChain transactionChain,
+                          ActorRef shardActor, SchemaContext schemaContext) {
+    this.transactionChain = transactionChain;
+    //this.transaction = transaction;
+    this.shardActor = shardActor;
+    this.schemaContext = schemaContext;
+  }
+
+
+
+  public static Props props(final DOMStoreReadTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadTransaction(transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadTransaction(transactionChain, transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreReadWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadWriteTransaction(transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardReadWriteTransaction(transactionChain, transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+
+  public static Props props(final DOMStoreWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardWriteTransaction(transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+  public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreWriteTransaction transaction,
+                            final ActorRef shardActor, final SchemaContext schemaContext) {
+    return Props.create(new Creator<ShardTransaction>() {
+
+      @Override
+      public ShardTransaction create() throws Exception {
+        return new ShardWriteTransaction(transactionChain, transaction, shardActor, schemaContext);
+      }
+    });
+  }
+
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+     if (message.getClass().equals(CloseTransaction.SERIALIZABLE_CLASS)) {
+      closeTransaction(new CloseTransaction());
+    } else if (message instanceof GetCompositedModification) {
+      // This is here for testing only
+      getSender().tell(new GetCompositeModificationReply(
+          new ImmutableCompositeModification(modification)), getSelf());
+    }else{
+      throw new Exception ("ShardTransaction:handleRecieve received an unknown message"+message);
     }
-
-
-    @Override
-    public void handleReceive(Object message) throws Exception {
-        if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            readData(ReadData.fromSerializable(message));
-        } else if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            writeData(WriteData.fromSerializable(message, schemaContext));
-        } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            mergeData(MergeData.fromSerializable(message, schemaContext));
-        } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            deleteData(DeleteData.fromSerizalizable(message));
-        } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
-            readyTransaction(new ReadyTransaction());
-        } else if (message.getClass().equals(CloseTransaction.SERIALIZABLE_CLASS)) {
-            closeTransaction(new CloseTransaction());
-        } else if (message instanceof GetCompositedModification) {
-            // This is here for testing only
-            getSender().tell(new GetCompositeModificationReply(
-                new ImmutableCompositeModification(modification)), getSelf());
-        }else{
-          throw new Exception ("Shard:handleRecieve received an unknown message"+message);
+  }
+
+  abstract protected  void closeTransaction(CloseTransaction message);
+
+  protected void readData(DOMStoreReadTransaction transaction,ReadData message) {
+    final ActorRef sender = getSender();
+    final ActorRef self = getSelf();
+    final YangInstanceIdentifier 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(schemaContext,optional.get()).toSerializable(), self);
+          } else {
+            sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
+          }
+        } catch (InterruptedException | ExecutionException e) {
+          log.error(e,
+              "An exception happened when reading data from path : "
+                  + path.toString());
         }
-    }
 
-    private void readData(ReadData message) {
-        final ActorRef sender = getSender();
-        final ActorRef self = getSelf();
-        final YangInstanceIdentifier 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(schemaContext,optional.get()).toSerializable(), self);
-                    } else {
-                        sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
-                    }
-                } catch (InterruptedException | ExecutionException e) {
-                    log.error(e,
-                        "An exception happened when reading data from path : "
-                            + path.toString());
-                }
-
-            }
-        }, getContext().dispatcher());
-    }
+      }
+    }, getContext().dispatcher());
+  }
 
 
-    private void writeData(WriteData message) {
-        modification.addModification(
-            new WriteModification(message.getPath(), message.getData(),schemaContext));
-        LOG.debug("writeData at path : " + message.getPath().toString());
-        transaction.write(message.getPath(), message.getData());
-        getSender().tell(new WriteDataReply().toSerializable(), getSelf());
-    }
+  protected void writeData(DOMStoreWriteTransaction transaction, WriteData message) {
+    modification.addModification(
+        new WriteModification(message.getPath(), message.getData(),schemaContext));
+    LOG.debug("writeData at path : " + message.getPath().toString());
+    transaction.write(message.getPath(), message.getData());
+    getSender().tell(new WriteDataReply().toSerializable(), getSelf());
+  }
 
-    private void mergeData(MergeData message) {
-        modification.addModification(
-            new MergeModification(message.getPath(), message.getData(), schemaContext));
-        LOG.debug("mergeData at path : " + message.getPath().toString());
-        transaction.merge(message.getPath(), message.getData());
-        getSender().tell(new MergeDataReply().toSerializable(), getSelf());
-    }
+  protected void mergeData(DOMStoreWriteTransaction transaction, MergeData message) {
+    modification.addModification(
+        new MergeModification(message.getPath(), message.getData(), schemaContext));
+    LOG.debug("mergeData at path : " + message.getPath().toString());
+    transaction.merge(message.getPath(), message.getData());
+    getSender().tell(new MergeDataReply().toSerializable(), getSelf());
+  }
 
-    private void deleteData(DeleteData message) {
-        modification.addModification(new DeleteModification(message.getPath()));
-        transaction.delete(message.getPath());
-        getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
-    }
+  protected void deleteData(DOMStoreWriteTransaction transaction, DeleteData message) {
+    modification.addModification(new DeleteModification(message.getPath()));
+    transaction.delete(message.getPath());
+    getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
+  }
 
-    private void readyTransaction(ReadyTransaction message) {
-        DOMStoreThreePhaseCommitCohort cohort = transaction.ready();
-        ActorRef cohortActor = getContext().actorOf(
-            ThreePhaseCommitCohort.props(cohort, shardActor, modification), "cohort");
-        getSender()
-            .tell(new ReadyTransactionReply(cohortActor.path()).toSerializable(), getSelf());
+  protected void readyTransaction(DOMStoreWriteTransaction transaction, ReadyTransaction message) {
+    DOMStoreThreePhaseCommitCohort cohort =  transaction.ready();
+    ActorRef cohortActor = getContext().actorOf(
+        ThreePhaseCommitCohort.props(cohort, shardActor, modification), "cohort");
+    getSender()
+        .tell(new ReadyTransactionReply(cohortActor.path()).toSerializable(), getSelf());
 
-    }
-
-    private void closeTransaction(CloseTransaction message) {
-        transaction.close();
-        getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
-        getSelf().tell(PoisonPill.getInstance(), getSelf());
-    }
+  }
 
 
-    // These classes are in here for test purposes only
+  // These classes are in here for test purposes only
 
 
-    static class GetCompositedModification {
+  static class GetCompositedModification {
 
-    }
+  }
 
 
-    static class GetCompositeModificationReply {
-        private final CompositeModification modification;
+  static class GetCompositeModificationReply {
+    private final CompositeModification modification;
 
 
-        GetCompositeModificationReply(CompositeModification modification) {
-            this.modification = modification;
-        }
+    GetCompositeModificationReply(CompositeModification modification) {
+      this.modification = modification;
+    }
 
 
-        public CompositeModification getModification() {
-            return modification;
-        }
+    public CompositeModification getModification() {
+      return modification;
     }
+  }
 }
index 50042411b17eeb0b0428963535008e8a777ca915..ce63f1107daafe31855c67c4eec4d676e94f384a 100644 (file)
@@ -15,7 +15,6 @@ import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionCh
 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;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -45,11 +44,27 @@ public class ShardTransactionChain extends AbstractUntypedActor {
         }
     }
 
+  private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,String transactionId){
+    if(createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_ONLY.ordinal()){
+      return getContext().actorOf(
+          ShardTransaction.props( chain.newReadOnlyTransaction(), getSelf(), schemaContext), transactionId);
+
+    }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_WRITE.ordinal()){
+      return getContext().actorOf(
+          ShardTransaction.props( chain.newReadWriteTransaction(), getSelf(), schemaContext), transactionId);
+
+
+    }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.WRITE_ONLY.ordinal()){
+      return getContext().actorOf(
+          ShardTransaction.props( chain.newWriteOnlyTransaction(), getSelf(), schemaContext), transactionId);
+    }else{
+      throw new IllegalArgumentException ("CreateTransaction message has unidentified transaction type="+createTransaction.getTransactionType()) ;
+    }
+  }
+
     private void createTransaction(CreateTransaction createTransaction) {
-        DOMStoreReadWriteTransaction transaction =
-            chain.newReadWriteTransaction();
-        ActorRef transactionActor = getContext().actorOf(ShardTransaction
-            .props(chain, transaction, getContext().parent(), schemaContext), "shard-" + createTransaction.getTransactionId());
+
+        ActorRef transactionActor = createTypedTransactionActor(createTransaction, "shard-" + createTransaction.getTransactionId());
         getSender()
             .tell(new CreateTransactionReply(transactionActor.path().toString(),createTransaction.getTransactionId()).toSerializable(),
                 getSelf());
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardWriteTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardWriteTransaction.java
new file mode 100644 (file)
index 0000000..2a5429b
--- /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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+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.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardWriteTransaction extends ShardTransaction {
+  private final DOMStoreWriteTransaction transaction;
+  private final LoggingAdapter log =
+      Logging.getLogger(getContext().system(), this);
+  public ShardWriteTransaction(DOMStoreWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super( shardActor, schemaContext);
+    this.transaction = transaction;
+
+  }
+
+  public ShardWriteTransaction(DOMStoreTransactionChain transactionChain, DOMStoreWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+    super(transactionChain, shardActor, schemaContext);
+    this.transaction = transaction;
+  }
+
+  @Override
+  public void handleReceive(Object message) throws Exception {
+    if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      writeData(transaction, WriteData.fromSerializable(message, schemaContext));
+    } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      mergeData(transaction, MergeData.fromSerializable(message, schemaContext));
+    } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      deleteData(transaction,DeleteData.fromSerizalizable(message));
+    } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+      readyTransaction(transaction,new ReadyTransaction());
+    }else {
+      super.handleReceive(message);
+    }
+  }
+
+  protected void closeTransaction(CloseTransaction message) {
+    transaction.close();
+    getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+    getSelf().tell(PoisonPill.getInstance(), getSelf());
+  }
+}
index b56dc9432f0b28067ca2daaba1cd95f936cb816e..915b13dd8bc234a6cbf898658b8e6479333b36c2 100644 (file)
@@ -10,8 +10,10 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorPath;
 import akka.actor.ActorSelection;
+
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListenableFutureTask;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
 import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException;
 import org.opendaylight.controller.cluster.datastore.messages.AbortTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.AbortTransactionReply;
@@ -29,7 +31,6 @@ import org.slf4j.LoggerFactory;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
 
 /**
  * ThreePhaseCommitCohortProxy represents a set of remote cohort proxies
@@ -42,14 +43,14 @@ public class ThreePhaseCommitCohortProxy implements
 
     private final ActorContext actorContext;
     private final List<ActorPath> cohortPaths;
-    private final ExecutorService executor;
+    private final ListeningExecutorService executor;
     private final String transactionId;
 
 
     public ThreePhaseCommitCohortProxy(ActorContext actorContext,
         List<ActorPath> cohortPaths,
         String transactionId,
-        ExecutorService executor) {
+        ListeningExecutorService executor) {
 
         this.actorContext = actorContext;
         this.cohortPaths = cohortPaths;
@@ -58,42 +59,37 @@ public class ThreePhaseCommitCohortProxy implements
     }
 
     @Override public ListenableFuture<Boolean> canCommit() {
-        Callable<Boolean> call = new Callable() {
-
-            @Override public Boolean call() throws Exception {
-            for(ActorPath actorPath : cohortPaths){
-                ActorSelection cohort = actorContext.actorSelection(actorPath);
-
-                try {
-                    Object response =
-                        actorContext.executeRemoteOperation(cohort,
-                            new CanCommitTransaction().toSerializable(),
-                            ActorContext.ASK_DURATION);
-
-                    if (response.getClass().equals(CanCommitTransactionReply.SERIALIZABLE_CLASS)) {
-                        CanCommitTransactionReply reply =
-                            CanCommitTransactionReply.fromSerializable(response);
-                        if (!reply.getCanCommit()) {
-                            return false;
+        Callable<Boolean> call = new Callable<Boolean>() {
+
+            @Override
+            public Boolean call() throws Exception {
+                for(ActorPath actorPath : cohortPaths){
+                    ActorSelection cohort = actorContext.actorSelection(actorPath);
+
+                    try {
+                        Object response =
+                                actorContext.executeRemoteOperation(cohort,
+                                        new CanCommitTransaction().toSerializable(),
+                                        ActorContext.ASK_DURATION);
+
+                        if (response.getClass().equals(CanCommitTransactionReply.SERIALIZABLE_CLASS)) {
+                            CanCommitTransactionReply reply =
+                                    CanCommitTransactionReply.fromSerializable(response);
+                            if (!reply.getCanCommit()) {
+                                return false;
+                            }
                         }
+                    } catch(RuntimeException e){
+                        LOG.error("Unexpected Exception", e);
+                        return false;
                     }
-                } catch(RuntimeException e){
-                    LOG.error("Unexpected Exception", e);
-                    return false;
                 }
 
-
-            }
-            return true;
+                return true;
             }
         };
 
-        ListenableFutureTask<Boolean>
-            future = ListenableFutureTask.create(call);
-
-        executor.submit(future);
-
-        return future;
+        return executor.submit(call);
     }
 
     @Override public ListenableFuture<Void> preCommit() {
@@ -138,13 +134,7 @@ public class ThreePhaseCommitCohortProxy implements
             }
         };
 
-        ListenableFutureTask<Void>
-            future = ListenableFutureTask.create(call);
-
-        executor.submit(future);
-
-        return future;
-
+        return executor.submit(call);
     }
 
     public List<ActorPath> getCohortPaths() {
index 2e8538d07768479e336bfbcc877778e3c4872277..5e9defa5b59c5db64033c1a92fbdb611766152a2 100644 (file)
@@ -15,17 +15,18 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import java.util.concurrent.ExecutorService;
+import com.google.common.util.concurrent.ListeningExecutorService;
 
 /**
  * TransactionChainProxy acts as a proxy for a DOMStoreTransactionChain created on a remote shard
  */
 public class TransactionChainProxy implements DOMStoreTransactionChain{
     private final ActorContext actorContext;
-    private final ExecutorService transactionExecutor;
+    private final ListeningExecutorService transactionExecutor;
     private final SchemaContext schemaContext;
 
-    public TransactionChainProxy(ActorContext actorContext, ExecutorService transactionExecutor, SchemaContext schemaContext) {
+    public TransactionChainProxy(ActorContext actorContext, ListeningExecutorService transactionExecutor,
+            SchemaContext schemaContext) {
         this.actorContext = actorContext;
         this.transactionExecutor = transactionExecutor;
         this.schemaContext = schemaContext;
index c85d32012fed9ee036a96b2e3663c061eabd0385..fa98905a66968b111372d4b893ef35bef6e32bd4 100644 (file)
@@ -13,9 +13,10 @@ import akka.actor.ActorRef;
 import akka.actor.ActorSelection;
 import akka.actor.Props;
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListenableFutureTask;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import org.opendaylight.controller.cluster.datastore.exceptions.PrimaryNotFoundException;
 import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
@@ -29,8 +30,10 @@ import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionRe
 import org.opendaylight.controller.cluster.datastore.messages.WriteData;
 import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -42,7 +45,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
@@ -74,13 +76,13 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
     private final ActorContext actorContext;
     private final Map<String, TransactionContext> remoteTransactionPaths = new HashMap<>();
     private final String identifier;
-    private final ExecutorService executor;
+    private final ListeningExecutorService executor;
     private final SchemaContext schemaContext;
 
     public TransactionProxy(
         ActorContext actorContext,
         TransactionType transactionType,
-        ExecutorService executor,
+        ListeningExecutorService executor,
         SchemaContext schemaContext
     ) {
 
@@ -94,7 +96,8 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
     }
 
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final YangInstanceIdentifier path) {
+    public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
+            final YangInstanceIdentifier path) {
 
         createTransactionIfMissing(actorContext, path);
 
@@ -177,7 +180,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
         try {
             Object response = actorContext.executeShardOperation(shardName,
-                new CreateTransaction(identifier).toSerializable(),
+                new CreateTransaction(identifier,this.transactionType.ordinal() ).toSerializable(),
                 ActorContext.ASK_DURATION);
             if (response.getClass()
                 .equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
@@ -196,8 +199,10 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
                 remoteTransactionPaths.put(shardName, transactionContext);
             }
-        } catch(TimeoutException e){
-            remoteTransactionPaths.put(shardName, new NoOpTransactionContext(shardName));
+        } catch(TimeoutException | PrimaryNotFoundException e){
+            LOG.error("Creating NoOpTransaction because of : {}", e.getMessage());
+            remoteTransactionPaths.put(shardName,
+                new NoOpTransactionContext(shardName));
         }
     }
 
@@ -214,7 +219,8 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
 
         void mergeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
 
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> readData(final YangInstanceIdentifier path);
+        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
+                final YangInstanceIdentifier path);
 
         void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
     }
@@ -266,9 +272,10 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
             getActor().tell(new MergeData(path, data, schemaContext).toSerializable(), null);
         }
 
-        @Override public ListenableFuture<Optional<NormalizedNode<?, ?>>> readData(final YangInstanceIdentifier path) {
+        @Override public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
+                final YangInstanceIdentifier path) {
 
-            Callable<Optional<NormalizedNode<?,?>>> call = new Callable() {
+            Callable<Optional<NormalizedNode<?,?>>> call = new Callable<Optional<NormalizedNode<?,?>>>() {
 
                 @Override public Optional<NormalizedNode<?,?>> call() throws Exception {
                     Object response = actorContext
@@ -279,20 +286,14 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
                         if(reply.getNormalizedNode() == null){
                             return Optional.absent();
                         }
-                        //FIXME : A cast should not be required here ???
-                        return (Optional<NormalizedNode<?, ?>>) Optional.of(reply.getNormalizedNode());
+                        return Optional.<NormalizedNode<?,?>>of(reply.getNormalizedNode());
                     }
 
                     return Optional.absent();
                 }
             };
 
-            ListenableFutureTask<Optional<NormalizedNode<?, ?>>>
-                future = ListenableFutureTask.create(call);
-
-            executor.submit(future);
-
-            return future;
+            return MappingCheckedFuture.create(executor.submit(call), ReadFailedException.MAPPER);
         }
 
         @Override public void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
@@ -342,10 +343,10 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         }
 
         @Override
-        public ListenableFuture<Optional<NormalizedNode<?, ?>>> readData(
+        public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
             YangInstanceIdentifier path) {
             LOG.error("readData called path = {}", path);
-            return Futures.immediateFuture(
+            return Futures.immediateCheckedFuture(
                 Optional.<NormalizedNode<?, ?>>absent());
         }
 
index 2da6aae85f619b517b5f1edcadfd1035b7ce5b9a..4eb6a8cef96319d0ca885112c3a0812ee06e5431 100644 (file)
@@ -9,6 +9,8 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
   private  Long committedTransactionsCount;
   private Long journalMessagesCount;
   final private String shardName;
+  private String leader;
+  private String raftState;
 
   ShardStats(String shardName){
     this.shardName = shardName;
@@ -33,6 +35,13 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
     return journalMessagesCount;
   }
 
+  @Override public String getLeader() {
+    return leader;
+  }
+
+  @Override public String getRaftState() {
+    return raftState;
+  }
 
   public Long incrementCommittedTransactionCount() {
     return committedTransactionsCount++;
@@ -49,6 +58,13 @@ public class ShardStats extends AbstractBaseMBean implements ShardStatsMBean {
 
   }
 
+  public void setLeader(String leader){
+    this.leader = leader;
+  }
+
+  public void setRaftState(String raftState){
+    this.raftState = raftState;
+  }
 
 
   @Override
index 795131fdbf6400f0b53c98f91d167bf31f45d493..b27ad86be987097b9bb9c37713a50116bfa5116e 100644 (file)
@@ -15,23 +15,28 @@ import org.opendaylight.controller.protobuff.messages.transaction.ShardTransacti
 public class CreateTransaction implements SerializableMessage {
   public static Class SERIALIZABLE_CLASS = ShardTransactionMessages.CreateTransaction.class;
   private final String transactionId;
+  private final int transactionType;
 
-  public CreateTransaction(String transactionId){
+  public CreateTransaction(String transactionId, int transactionType){
 
     this.transactionId = transactionId;
+    this.transactionType = transactionType;
   }
 
   public String getTransactionId() {
     return transactionId;
   }
 
+  public int getTransactionType() { return transactionType;}
+
   @Override
   public Object toSerializable() {
-    return  ShardTransactionMessages.CreateTransaction.newBuilder().setTransactionId(transactionId).build();
+    return  ShardTransactionMessages.CreateTransaction.newBuilder().setTransactionId(transactionId).setTransactionType(transactionType).build();
   }
 
   public static CreateTransaction fromSerializable(Object message){
-    return new CreateTransaction(((ShardTransactionMessages.CreateTransaction)message).getTransactionId());
+    ShardTransactionMessages.CreateTransaction createTransaction = (ShardTransactionMessages.CreateTransaction)message;
+    return new CreateTransaction(createTransaction.getTransactionId(),createTransaction.getTransactionType() );
   }
 
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/EnableNotification.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/EnableNotification.java
new file mode 100644 (file)
index 0000000..67dab7e
--- /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 EnableNotification {
+    private final boolean enabled;
+
+    public EnableNotification(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindLocalShard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/FindLocalShard.java
new file mode 100644 (file)
index 0000000..c415db6
--- /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.cluster.datastore.messages;
+
+/**
+ * FindLocalShard is a message that should be sent to the {@link org.opendaylight.controller.cluster.datastore.ShardManager}
+ * when we need to find a reference to a LocalShard
+ */
+public class FindLocalShard {
+    private final String shardName;
+
+    public FindLocalShard(String shardName) {
+        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/LocalShardFound.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/LocalShardFound.java
new file mode 100644 (file)
index 0000000..feea38f
--- /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 akka.actor.ActorRef;
+
+/**
+ * LocalShardFound is a message that is sent by the {@link org.opendaylight.controller.cluster.datastore.ShardManager}
+ * when it finds a shard with the specified name in it's local shard registry
+ */
+public class LocalShardFound {
+    private final ActorRef path;
+
+    public LocalShardFound(ActorRef path) {
+        this.path = path;
+    }
+
+    public ActorRef getPath() {
+        return path;
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/LocalShardNotFound.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/LocalShardNotFound.java
new file mode 100644 (file)
index 0000000..f6c6634
--- /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.messages;
+
+/**
+ * LocalShardNotFound is a message that is sent by the {@link org.opendaylight.controller.cluster.datastore.ShardManager}
+ * when it cannot locate a shard in it's local registry with the shardName specified
+ */
+public class LocalShardNotFound {
+    private final String shardName;
+
+    /**
+     *
+     * @param shardName the name of the shard that could not be found
+     */
+    public LocalShardNotFound(String shardName) {
+        this.shardName = shardName;
+    }
+
+    public String getShardName() {
+        return shardName;
+    }
+}
index 6f4b65a6f3c2db45baf5e1a9928d36928e252733..fc7ebd94dd481c909ba6e4d65d205e41cbfdebbf 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.controller.cluster.datastore.shardstrategy;
 import org.opendaylight.controller.cluster.datastore.Configuration;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
+import java.util.List;
+
 public class ModuleShardStrategy implements ShardStrategy {
 
     public static final String NAME = "module";
@@ -25,6 +27,11 @@ public class ModuleShardStrategy implements ShardStrategy {
     }
 
     @Override public String findShard(YangInstanceIdentifier path) {
-        return configuration.getShardNamesFromModuleName(moduleName).get(0);
+        List<String> shardNames =
+            configuration.getShardNamesFromModuleName(moduleName);
+        if(shardNames.size() == 0){
+            return DefaultShardStrategy.DEFAULT_SHARD;
+        }
+        return shardNames.get(0);
     }
 }
index 2df945edd5e9b9c16ed454e55859611afe8a66e0..9a05c381ea556aeccf10013952aab453282c3dba 100644 (file)
@@ -16,6 +16,9 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 public interface ShardStrategy {
   /**
    * Find the name of the shard in which the data pointed to by the specified path belongs in
+   * <p>
+   * Should return the name of the default shard DefaultShardStrategy.DEFAULT_SHARD
+   * if no matching shard was found
    *
    * @param path The location of the data in the logical tree
    * @return
index ac0893da5ad157c230fad2aab7401b27d0054751..4706c66e2594eae1384b465bf5d0b246c72d8223 100644 (file)
@@ -18,7 +18,9 @@ import org.opendaylight.controller.cluster.datastore.ClusterWrapper;
 import org.opendaylight.controller.cluster.datastore.Configuration;
 import org.opendaylight.controller.cluster.datastore.exceptions.PrimaryNotFoundException;
 import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException;
+import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard;
 import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.LocalShardFound;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
@@ -91,6 +93,29 @@ public class ActorContext {
         return actorSystem.actorSelection(path);
     }
 
+    /**
+     * Finds a local shard given it's shard name and return it's ActorRef
+     *
+     * @param shardName the name of the local shard that needs to be found
+     * @return a reference to a local shard actor which represents the shard
+     *         specified by the shardName
+     */
+    public ActorRef findLocalShard(String shardName) {
+        Object result = executeLocalOperation(shardManager,
+            new FindLocalShard(shardName), ASK_DURATION);
+
+        if (result instanceof LocalShardFound) {
+            LocalShardFound found = (LocalShardFound) result;
+
+            LOG.debug("Local shard found {}", found.getPath());
+
+            return found.getPath();
+        }
+
+        return null;
+    }
+
+
     public String findPrimaryPath(String shardName) {
         Object result = executeLocalOperation(shardManager,
             new FindPrimary(shardName).toSerializable(), ASK_DURATION);
@@ -170,6 +195,34 @@ public class ActorContext {
         return executeRemoteOperation(primary, message, duration);
     }
 
+    /**
+     * Execute an operation on the the local shard only
+     * <p>
+     *     This method first finds the address of the local shard if any. It then
+     *     executes the operation on it.
+     * </p>
+     *
+     * @param shardName the name of the shard on which the operation needs to be executed
+     * @param message the message that needs to be sent to the shard
+     * @param duration the time duration in which this operation should complete
+     * @return the message that was returned by the local actor on which the
+     *         the operation was executed. If a local shard was not found then
+     *         null is returned
+     * @throws org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException
+     *         if the operation does not complete in a specified time duration
+     */
+    public Object executeLocalShardOperation(String shardName, Object message,
+        FiniteDuration duration) {
+        ActorRef local = findLocalShard(shardName);
+
+        if(local != null) {
+            return executeLocalOperation(local, message, duration);
+        }
+
+        return null;
+    }
+
+
     public void shutdown() {
         shardManager.tell(PoisonPill.getInstance(), null);
         actorSystem.shutdown();
index 76914c2c84f020268377b2a5d191cf831bb96f6d..daac89c4c8adaef39047034138a8318e639f54c8 100644 (file)
@@ -1,15 +1,60 @@
-ODLCluster{
 
-actor {
-        serializers {
-          java = "akka.serialization.JavaSerializer"
-          proto = "akka.remote.serialization.ProtobufSerializer"
-        }
+odl-cluster-data {
+  akka {
+    cluster {
+        roles = [
+          "member-1"
+        ]
+    }
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2550
+           maximum-frame-size = 2097152
+           send-buffer-size = 52428800
+           receive-buffer-size = 52428800
+      }
+    }
 
-        serialization-bindings {
-            "com.google.protobuf.Message" = proto
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"]
 
-        }
+      auto-down-unreachable-after = 10s
     }
+  }
+}
+
+odl-cluster-rpc {
+  akka {
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
 
-}
\ No newline at end of file
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2551
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
index 05ef33f759009b480dd156dab49af8d7a3a674fd..e820703eeb5fa0e5e6806afc9145620716153ce4 100644 (file)
@@ -1,7 +1,7 @@
 modules = [
     {
         name = "inventory"
-        namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:people"
+        namespace = "urn:opendaylight:inventory"
         shard-strategy = "module"
     }
 ]
index 11ad559744a3923aebfbb07472771b98a4439ab0..6599bd8eeb0d0b0b54d9058086d836fb82aa214a 100644 (file)
@@ -12,6 +12,7 @@ import akka.actor.ActorPath;
 import akka.actor.ActorRef;
 import akka.actor.ActorSelection;
 import akka.actor.Props;
+import akka.event.Logging;
 import akka.testkit.JavaTestKit;
 import junit.framework.Assert;
 import org.junit.Test;
@@ -35,6 +36,8 @@ import scala.concurrent.duration.FiniteDuration;
 
 import java.util.Collections;
 
+import static junit.framework.Assert.assertEquals;
+
 public class BasicIntegrationTest extends AbstractActorTest {
 
     @Test
@@ -61,17 +64,24 @@ public class BasicIntegrationTest extends AbstractActorTest {
                         getRef());
 
 
-                    // Wait for Shard to become a Leader
-                    try {
-                        Thread.sleep(1000);
-                    } catch (InterruptedException e) {
-                        e.printStackTrace();
-                    }
+                    // Wait for a specific log message to show up
+                    final boolean result =
+                        new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                        ) {
+                            protected Boolean run() {
+                                return true;
+                            }
+                        }.from(shard.path().toString())
+                            .message("Switching from state Candidate to Leader")
+                            .occurrences(1).exec();
+
+                    assertEquals(true, result);
+
                     // 1. Create a TransactionChain
                     shard.tell(new CreateTransactionChain().toSerializable(), getRef());
 
                     final ActorSelection transactionChain =
-                        new ExpectMsg<ActorSelection>("CreateTransactionChainReply") {
+                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionChainReply") {
                             protected ActorSelection match(Object in) {
                                 if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)) {
                                     ActorPath transactionChainPath =
@@ -90,10 +100,10 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     System.out.println("Successfully created transaction chain");
 
                     // 2. Create a Transaction on the TransactionChain
-                    transactionChain.tell(new CreateTransaction("txn-1").toSerializable(), getRef());
+                    transactionChain.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.WRITE_ONLY.ordinal() ).toSerializable(), getRef());
 
                     final ActorSelection transaction =
-                        new ExpectMsg<ActorSelection>("CreateTransactionReply") {
+                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionReply") {
                             protected ActorSelection match(Object in) {
                                 if (CreateTransactionReply.SERIALIZABLE_CLASS.equals(in.getClass())) {
                                     CreateTransactionReply reply = CreateTransactionReply.fromSerializable(in);
@@ -115,7 +125,7 @@ public class BasicIntegrationTest extends AbstractActorTest {
                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
                         getRef());
 
-                    Boolean writeDone = new ExpectMsg<Boolean>("WriteDataReply") {
+                    Boolean writeDone = new ExpectMsg<Boolean>(duration("1 seconds"), "WriteDataReply") {
                         protected Boolean match(Object in) {
                             if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
                                 return true;
@@ -134,7 +144,7 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     transaction.tell(new ReadyTransaction().toSerializable(), getRef());
 
                     final ActorSelection cohort =
-                        new ExpectMsg<ActorSelection>("ReadyTransactionReply") {
+                        new ExpectMsg<ActorSelection>(duration("1 seconds"), "ReadyTransactionReply") {
                             protected ActorSelection match(Object in) {
                                 if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
                                     ActorPath cohortPath =
@@ -157,7 +167,7 @@ public class BasicIntegrationTest extends AbstractActorTest {
                     cohort.tell(new PreCommitTransaction().toSerializable(), getRef());
 
                     Boolean preCommitDone =
-                        new ExpectMsg<Boolean>("PreCommitTransactionReply") {
+                        new ExpectMsg<Boolean>(duration("1 seconds"), "PreCommitTransactionReply") {
                             protected Boolean match(Object in) {
                                 if (in.getClass().equals(PreCommitTransactionReply.SERIALIZABLE_CLASS)) {
                                     return true;
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java
new file mode 100644 (file)
index 0000000..400eab1
--- /dev/null
@@ -0,0 +1,84 @@
+package org.opendaylight.controller.cluster.datastore;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
+import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
+import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CompositeModificationPayloadTest {
+
+
+    private static final String SERIALIZE_OUT = "serialize.out";
+
+    @After
+    public void shutDown(){
+        File f = new File(SERIALIZE_OUT);
+        if(f.exists()){
+            f.delete();
+        }
+    }
+
+    @Test
+    public void testBasic() throws IOException {
+
+        List<ReplicatedLogEntry> entries = new ArrayList<>();
+
+        entries.add(0, new ReplicatedLogEntry() {
+            @Override public Payload getData() {
+                WriteModification writeModification =
+                    new WriteModification(TestModel.TEST_PATH, ImmutableNodes
+                        .containerNode(TestModel.TEST_QNAME),
+                        TestModel.createTestContext());
+
+                MutableCompositeModification compositeModification =
+                    new MutableCompositeModification();
+
+                compositeModification.addModification(writeModification);
+
+                return new CompositeModificationPayload(compositeModification.toSerializable());
+            }
+
+            @Override public long getTerm() {
+                return 1;
+            }
+
+            @Override public long getIndex() {
+                return 1;
+            }
+        });
+
+        AppendEntries appendEntries =
+            new AppendEntries(1, "member-1", 0, 100, entries, 1);
+
+        AppendEntriesMessages.AppendEntries o = (AppendEntriesMessages.AppendEntries) appendEntries.toSerializable();
+
+        o.writeDelimitedTo(new FileOutputStream(SERIALIZE_OUT));
+
+        AppendEntriesMessages.AppendEntries appendEntries2 =
+            AppendEntriesMessages.AppendEntries
+                .parseDelimitedFrom(new FileInputStream(SERIALIZE_OUT));
+
+        AppendEntries appendEntries1 = AppendEntries.fromSerializable(appendEntries2);
+
+        Payload data = appendEntries1.getEntries().get(0).getData();
+
+
+        Assert.assertTrue(((CompositeModificationPayload) data).getModification().toString().contains(TestModel.TEST_QNAME.getNamespace().toString()));
+
+    }
+
+}
index 8c1cbbbba07119884f804bd823fb7947cbcf389f..b2ee4a49fee1b40ee86730da0044f5f987b090a9 100644 (file)
@@ -94,7 +94,7 @@ public class DataChangeListenerProxyTest extends AbstractActorTest {
 
         Assert.assertEquals(1, listMessages.size());
 
-        Assert.assertTrue(listMessages.get(0).getClass().equals(DataChanged.SERIALIZABLE_CLASS));
+        Assert.assertTrue(listMessages.get(0).getClass().equals(DataChanged.class));
 
     }
 }
index 8413bac3a7b4e52ea5a3e718ea61775403787d53..920248521a297871f95c5312f1d34085900feced 100644 (file)
@@ -41,7 +41,7 @@ public class DataChangeListenerRegistrationTest extends AbstractActorTest {
 
           subject.tell(new CloseDataChangeListenerRegistration().toSerializable(), getRef());
 
-          final String out = new ExpectMsg<String>("match hint") {
+          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
             // do not put code outside this method, will run afterwards
             protected String match(Object in) {
               if (in.getClass().equals(CloseDataChangeListenerRegistrationReply.SERIALIZABLE_CLASS)) {
index fd610322201f1ffb168640d413f5afe0c8d743d7..26ec583b3e058108f9cc18517f5f6909847f5cd6 100644 (file)
@@ -6,6 +6,7 @@ import akka.testkit.JavaTestKit;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.messages.DataChanged;
 import org.opendaylight.controller.cluster.datastore.messages.DataChangedReply;
+import org.opendaylight.controller.cluster.datastore.messages.EnableNotification;
 import org.opendaylight.controller.md.cluster.datastore.model.CompositeModel;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
@@ -86,24 +87,28 @@ public class DataChangeListenerTest extends AbstractActorTest {
     }
 
     @Test
-    public void testDataChanged(){
+    public void testDataChangedWhenNotificationsAreEnabled(){
         new JavaTestKit(getSystem()) {{
             final MockDataChangeListener listener = new MockDataChangeListener();
             final Props props = DataChangeListener.props(CompositeModel.createTestContext(),listener,CompositeModel.FAMILY_PATH );
             final ActorRef subject =
-                getSystem().actorOf(props, "testDataChanged");
+                getSystem().actorOf(props, "testDataChangedNotificationsEnabled");
 
             new Within(duration("1 seconds")) {
                 protected void run() {
 
+                    // Let the DataChangeListener know that notifications should
+                    // be enabled
+                    subject.tell(new EnableNotification(true), getRef());
+
                     subject.tell(
-                        new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()).toSerializable(),
+                        new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()),
                         getRef());
 
-                    final Boolean out = new ExpectMsg<Boolean>("dataChanged") {
+                    final Boolean out = new ExpectMsg<Boolean>(duration("800 millis"), "dataChanged") {
                         // do not put code outside this method, will run afterwards
                         protected Boolean match(Object in) {
-                            if (in.getClass().equals(DataChangedReply.SERIALIZABLE_CLASS)) {
+                            if (in != null && in.getClass().equals(DataChangedReply.class)) {
 
                                 return true;
                             } else {
@@ -115,7 +120,30 @@ public class DataChangeListenerTest extends AbstractActorTest {
                     assertTrue(out);
                     assertTrue(listener.gotIt());
                     assertNotNull(listener.getChange().getCreatedData());
-                    // Will wait for the rest of the 3 seconds
+
+                    expectNoMsg();
+                }
+
+
+            };
+        }};
+    }
+
+    @Test
+    public void testDataChangedWhenNotificationsAreDisabled(){
+        new JavaTestKit(getSystem()) {{
+            final MockDataChangeListener listener = new MockDataChangeListener();
+            final Props props = DataChangeListener.props(CompositeModel.createTestContext(),listener,CompositeModel.FAMILY_PATH );
+            final ActorRef subject =
+                getSystem().actorOf(props, "testDataChangedNotificationsDisabled");
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    subject.tell(
+                        new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()),
+                        getRef());
+
                     expectNoMsg();
                 }
 
index b5e3d24ef6d536d6afe2c9a6abc111bbb4b8688b..fc527b6bffe13726d89d5923cee71a6c471af055 100644 (file)
@@ -1,9 +1,12 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorSystem;
+import akka.event.Logging;
 import akka.testkit.JavaTestKit;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
+import junit.framework.Assert;
+import org.apache.commons.io.FileUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -18,17 +21,29 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCoh
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
 
-public class DistributedDataStoreIntegrationTest{
+public class DistributedDataStoreIntegrationTest {
 
     private static ActorSystem system;
 
     @Before
-    public void setUp() {
+    public void setUp() throws IOException {
+        File journal = new File("journal");
+
+        if(journal.exists()) {
+            FileUtils.deleteDirectory(journal);
+        }
+
+
         System.setProperty("shard.persistent", "false");
         system = ActorSystem.create("test");
     }
@@ -45,79 +60,152 @@ public class DistributedDataStoreIntegrationTest{
 
     @Test
     public void integrationTest() throws Exception {
-        Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
+        final Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
         ShardStrategyFactory.setConfiguration(configuration);
-        DistributedDataStore distributedDataStore =
-            new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
 
-        distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
 
-        Thread.sleep(1000);
 
-        DOMStoreReadWriteTransaction transaction =
-            distributedDataStore.newReadWriteTransaction();
+        new JavaTestKit(getSystem()) {
+            {
+
+                new Within(duration("10 seconds")) {
+                    protected void run() {
+                        try {
+                            final DistributedDataStore distributedDataStore =
+                                new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
+
+                            distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
+
+                            // Wait for a specific log message to show up
+                            final boolean result =
+                                new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                                    ) {
+                                    protected Boolean run() {
+                                        return true;
+                                    }
+                                }.from("akka://test/user/shardmanager-config/member-1-shard-test-1-config")
+                                    .message("Switching from state Candidate to Leader")
+                                    .occurrences(1).exec();
+
+                            assertEquals(true, result);
+
+                            DOMStoreReadWriteTransaction transaction =
+                                distributedDataStore.newReadWriteTransaction();
 
-        transaction.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+                            transaction
+                                .write(TestModel.TEST_PATH, ImmutableNodes
+                                    .containerNode(TestModel.TEST_QNAME));
 
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
-            transaction.read(TestModel.TEST_PATH);
+                            ListenableFuture<Optional<NormalizedNode<?, ?>>>
+                                future =
+                                transaction.read(TestModel.TEST_PATH);
 
-        Optional<NormalizedNode<?, ?>> optional = future.get();
+                            Optional<NormalizedNode<?, ?>> optional =
+                                future.get();
 
-        NormalizedNode<?, ?> normalizedNode = optional.get();
+                            Assert.assertTrue("Node not found", optional.isPresent());
 
-        assertEquals(TestModel.TEST_QNAME, normalizedNode.getNodeType());
+                            NormalizedNode<?, ?> normalizedNode =
+                                optional.get();
 
-        DOMStoreThreePhaseCommitCohort ready = transaction.ready();
+                            assertEquals(TestModel.TEST_QNAME,
+                                normalizedNode.getNodeType());
 
-        ListenableFuture<Boolean> canCommit = ready.canCommit();
+                            DOMStoreThreePhaseCommitCohort ready =
+                                transaction.ready();
 
-        assertTrue(canCommit.get());
+                            ListenableFuture<Boolean> canCommit =
+                                ready.canCommit();
 
-        ListenableFuture<Void> preCommit = ready.preCommit();
+                            assertTrue(canCommit.get(5, TimeUnit.SECONDS));
 
-        preCommit.get();
+                            ListenableFuture<Void> preCommit =
+                                ready.preCommit();
 
-        ListenableFuture<Void> commit = ready.commit();
+                            preCommit.get(5, TimeUnit.SECONDS);
 
-        commit.get();
+                            ListenableFuture<Void> commit = ready.commit();
+
+                            commit.get(5, TimeUnit.SECONDS);
+                        } catch (ExecutionException | TimeoutException | InterruptedException e){
+                            fail(e.getMessage());
+                        }
+                    }
+                };
+            }
+        };
 
     }
 
 
-    @Test
+    //FIXME : Disabling test because it's flaky
+    //@Test
     public void integrationTestWithMultiShardConfiguration()
-        throws ExecutionException, InterruptedException {
-        Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
+        throws ExecutionException, InterruptedException, TimeoutException {
+        final Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
 
         ShardStrategyFactory.setConfiguration(configuration);
-        DistributedDataStore distributedDataStore =
-            new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
+
+        new JavaTestKit(getSystem()) {
+            {
+
+                new Within(duration("10 seconds")) {
+                    protected void run() {
+                        try {
+                            final DistributedDataStore distributedDataStore =
+                                new DistributedDataStore(getSystem(), "config",
+                                    new MockClusterWrapper(), configuration);
+
+                            distributedDataStore.onGlobalContextUpdated(
+                                SchemaContextHelper.full());
+
+                            // Wait for a specific log message to show up
+                            final boolean result =
+                                new JavaTestKit.EventFilter<Boolean>(
+                                    Logging.Info.class
+                                ) {
+                                    protected Boolean run() {
+                                        return true;
+                                    }
+                                }.from(
+                                    "akka://test/user/shardmanager-config/member-1-shard-cars-1-config")
+                                    .message(
+                                        "Switching from state Candidate to Leader")
+                                    .occurrences(1)
+                                    .exec();
+
+                            Thread.sleep(1000);
 
 
-        distributedDataStore.onGlobalContextUpdated(SchemaContextHelper.full());
+                            DOMStoreReadWriteTransaction transaction =
+                                distributedDataStore.newReadWriteTransaction();
 
-        Thread.sleep(1000);
+                            transaction.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
+                            transaction.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
 
-        DOMStoreReadWriteTransaction transaction =
-            distributedDataStore.newReadWriteTransaction();
+                            DOMStoreThreePhaseCommitCohort ready = transaction.ready();
 
-        transaction.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
-        transaction.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
+                            ListenableFuture<Boolean> canCommit = ready.canCommit();
 
-        DOMStoreThreePhaseCommitCohort ready = transaction.ready();
+                            assertTrue(canCommit.get(5, TimeUnit.SECONDS));
 
-        ListenableFuture<Boolean> canCommit = ready.canCommit();
+                            ListenableFuture<Void> preCommit = ready.preCommit();
 
-        assertTrue(canCommit.get());
+                            preCommit.get(5, TimeUnit.SECONDS);
 
-        ListenableFuture<Void> preCommit = ready.preCommit();
+                            ListenableFuture<Void> commit = ready.commit();
 
-        preCommit.get();
+                            commit.get(5, TimeUnit.SECONDS);
 
-        ListenableFuture<Void> commit = ready.commit();
+                            assertEquals(true, result);
+                        } catch(ExecutionException | TimeoutException | InterruptedException e){
+                            fail(e.getMessage());
+                        }
+                    }
+                };
+            }
+        };
 
-        commit.get();
 
     }
 
index 23a1ed49315ec827baa95c41b51dfe4d23159d4e..d1beab904984262cd1f83de56a039c5970dc0742 100644 (file)
@@ -54,8 +54,8 @@ public class DistributedDataStoreTest extends AbstractActorTest{
     }
 
     @org.junit.Test
-    public void testRegisterChangeListener() throws Exception {
-        mockActorContext.setExecuteShardOperationResponse(new RegisterChangeListenerReply(doNothingActorRef.path()).toSerializable());
+    public void testRegisterChangeListenerWhenShardIsNotLocal() throws Exception {
+
         ListenerRegistration registration =
                 distributedDataStore.registerChangeListener(TestModel.TEST_PATH, new AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>() {
             @Override
@@ -64,9 +64,31 @@ public class DistributedDataStoreTest extends AbstractActorTest{
             }
         }, AsyncDataBroker.DataChangeScope.BASE);
 
+        // Since we do not expect the shard to be local registration will return a NoOpRegistration
+        Assert.assertTrue(registration instanceof NoOpDataChangeListenerRegistration);
+
+        Assert.assertNotNull(registration);
+    }
+
+    @org.junit.Test
+    public void testRegisterChangeListenerWhenShardIsLocal() throws Exception {
+
+        mockActorContext.setExecuteLocalShardOperationResponse(new RegisterChangeListenerReply(doNothingActorRef.path()));
+
+        ListenerRegistration registration =
+            distributedDataStore.registerChangeListener(TestModel.TEST_PATH, new AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>() {
+                @Override
+                public void onDataChanged(AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
+                    throw new UnsupportedOperationException("onDataChanged");
+                }
+            }, AsyncDataBroker.DataChangeScope.BASE);
+
+        Assert.assertTrue(registration instanceof DataChangeListenerRegistrationProxy);
+
         Assert.assertNotNull(registration);
     }
 
+
     @org.junit.Test
     public void testCreateTransactionChain() throws Exception {
         final DOMStoreTransactionChain transactionChain = distributedDataStore.createTransactionChain();
index 87d257a3f217bf0bfac0b3c8ade1cbe8d4555b04..e9ad450ed86614ff78114ff4bb545e23ab82367f 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.cluster.datastore;
 
+import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import akka.actor.Props;
 import akka.testkit.JavaTestKit;
@@ -8,13 +9,19 @@ import junit.framework.Assert;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard;
 import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.LocalShardFound;
+import org.opendaylight.controller.cluster.datastore.messages.LocalShardNotFound;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
 import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper;
 import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration;
 import scala.concurrent.duration.Duration;
 
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 public class ShardManagerTest {
     private static ActorSystem system;
 
@@ -47,7 +54,6 @@ public class ShardManagerTest {
                     expectMsgEquals(Duration.Zero(),
                         new PrimaryNotFound("inventory").toSerializable());
 
-                    // Will wait for the rest of the 3 seconds
                     expectNoMsg();
                 }
             };
@@ -64,13 +70,81 @@ public class ShardManagerTest {
             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).toSerializable(), getRef());
 
-                    expectMsgClass(PrimaryFound.SERIALIZABLE_CLASS);
+                    expectMsgClass(duration("1 seconds"), PrimaryFound.SERIALIZABLE_CLASS);
+
+                    expectNoMsg();
+                }
+            };
+        }};
+    }
+
+    @Test
+    public void testOnReceiveFindLocalShardForNonExistentShard() throws Exception {
+
+        new JavaTestKit(system) {{
+            final Props props = ShardManager
+                .props("config", new MockClusterWrapper(),
+                    new MockConfiguration());
+            final TestActorRef<ShardManager> subject =
+                TestActorRef.create(system, props);
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    subject.tell(new FindLocalShard("inventory"), getRef());
+
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "find local") {
+                        protected String match(Object in) {
+                            if (in instanceof LocalShardNotFound) {
+                                return ((LocalShardNotFound) in).getShardName();
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    assertEquals("inventory", out);
+
+                    expectNoMsg();
+                }
+            };
+        }};
+    }
+
+    @Test
+    public void testOnReceiveFindLocalShardForExistentShard() throws Exception {
+
+        final MockClusterWrapper mockClusterWrapper = new MockClusterWrapper();
+
+        new JavaTestKit(system) {{
+            final Props props = ShardManager
+                .props("config", mockClusterWrapper,
+                    new MockConfiguration());
+            final TestActorRef<ShardManager> subject =
+                TestActorRef.create(system, props);
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    subject.tell(new FindLocalShard(Shard.DEFAULT_NAME), getRef());
+
+                    final ActorRef out = new ExpectMsg<ActorRef>(duration("1 seconds"), "find local") {
+                        protected ActorRef match(Object in) {
+                            if (in instanceof LocalShardFound) {
+                                return ((LocalShardFound) in).getPath();
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    assertTrue(out.path().toString(), out.path().toString().contains("member-1-shard-default-config"));
+
 
                     expectNoMsg();
                 }
@@ -96,7 +170,7 @@ public class ShardManagerTest {
 
                     subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("primary found") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "primary found") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(PrimaryFound.SERIALIZABLE_CLASS)) {
@@ -134,13 +208,13 @@ public class ShardManagerTest {
 
                     subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
 
-                    expectMsgClass(PrimaryFound.SERIALIZABLE_CLASS);
+                    expectMsgClass(duration("1 seconds"), PrimaryFound.SERIALIZABLE_CLASS);
 
                     MockClusterWrapper.sendMemberRemoved(subject, "member-2", getRef().path().toString());
 
                     subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
 
-                    expectMsgClass(PrimaryNotFound.SERIALIZABLE_CLASS);
+                    expectMsgClass(duration("1 seconds"), PrimaryNotFound.SERIALIZABLE_CLASS);
 
                     expectNoMsg();
                 }
index 7d57ea8284e90dc3f941b7b82385e5db28ed75f4..431a266b148478a49766bd8f0cc173bc7b2e4062 100644 (file)
@@ -2,11 +2,14 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
 import akka.actor.Props;
+import akka.event.Logging;
 import akka.testkit.JavaTestKit;
+import junit.framework.Assert;
 import org.junit.Test;
 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.EnableNotification;
 import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolved;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
@@ -24,6 +27,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import static junit.framework.Assert.assertFalse;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -36,19 +40,25 @@ public class ShardTest extends AbstractActorTest {
                 getSystem().actorOf(props, "testCreateTransactionChain");
 
 
-            // Wait for Shard to become a Leader
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
+            // Wait for a specific log message to show up
+            final boolean result =
+                new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                ) {
+                    protected Boolean run() {
+                        return true;
+                    }
+                }.from(subject.path().toString())
+                    .message("Switching from state Candidate to Leader")
+                    .occurrences(1).exec();
+
+            Assert.assertEquals(true, result);
 
             new Within(duration("1 seconds")) {
                 protected void run() {
 
                     subject.tell(new CreateTransactionChain().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)){
@@ -89,15 +99,28 @@ public class ShardTest extends AbstractActorTest {
                         getRef());
 
                     subject.tell(new RegisterChangeListener(TestModel.TEST_PATH,
-                        getRef().path(), AsyncDataBroker.DataChangeScope.BASE).toSerializable(),
+                        getRef().path(), AsyncDataBroker.DataChangeScope.BASE),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final Boolean notificationEnabled = new ExpectMsg<Boolean>("enable notification") {
+                        // do not put code outside this method, will run afterwards
+                        protected Boolean match(Object in) {
+                            if(in instanceof EnableNotification){
+                                return ((EnableNotification) in).isEnabled();
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    assertFalse(notificationEnabled);
+
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
-                            if (in.getClass().equals(RegisterChangeListenerReply.SERIALIZABLE_CLASS)) {
+                            if (in.getClass().equals(RegisterChangeListenerReply.class)) {
                                 RegisterChangeListenerReply reply =
-                                    RegisterChangeListenerReply.fromSerializable(getSystem(),in);
+                                    (RegisterChangeListenerReply) in;
                                 return reply.getListenerRegistrationPath()
                                     .toString();
                             } else {
@@ -108,8 +131,6 @@ public class ShardTest extends AbstractActorTest {
 
                     assertTrue(out.matches(
                         "akka:\\/\\/test\\/user\\/testRegisterChangeListener\\/\\$.*"));
-                    // Will wait for the rest of the 3 seconds
-                    expectNoMsg();
                 }
 
 
@@ -125,13 +146,18 @@ public class ShardTest extends AbstractActorTest {
                 getSystem().actorOf(props, "testCreateTransaction");
 
 
-            // Wait for Shard to become a Leader
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
+            // Wait for a specific log message to show up
+            final boolean result =
+                new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+                ) {
+                    protected Boolean run() {
+                        return true;
+                    }
+                }.from(subject.path().toString())
+                    .message("Switching from state Candidate to Leader")
+                    .occurrences(1).exec();
 
+            Assert.assertEquals(true, result);
 
             new Within(duration("1 seconds")) {
                 protected void run() {
@@ -140,10 +166,10 @@ public class ShardTest extends AbstractActorTest {
                         new UpdateSchemaContext(TestModel.createTestContext()),
                         getRef());
 
-                    subject.tell(new CreateTransaction("txn-1").toSerializable(),
+                    subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in instanceof CreateTransactionReply) {
index 6330ad8acca33ab6c05f3263aa45ca459f0c283d..b35880a6a501367a4c1155b3cae4ef405352ddb6 100644 (file)
@@ -33,9 +33,9 @@ public class ShardTransactionChainTest extends AbstractActorTest {
      new Within(duration("1 seconds")) {
         protected void run() {
 
-          subject.tell(new CreateTransaction("txn-1").toSerializable(), getRef());
+          subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(), getRef());
 
-          final String out = new ExpectMsg<String>("match hint") {
+          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
             // do not put code outside this method, will run afterwards
             protected String match(Object in) {
               if (in.getClass().equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
@@ -70,7 +70,7 @@ public class ShardTransactionChainTest extends AbstractActorTest {
 
           subject.tell(new CloseTransactionChain().toSerializable(), getRef());
 
-          final String out = new ExpectMsg<String>("match hint") {
+          final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
             // do not put code outside this method, will run afterwards
             protected String match(Object in) {
               if (in.getClass().equals(CloseTransactionChainReply.SERIALIZABLE_CLASS)) {
index 7884eeccdae7874f8d19c9090bf08d755cc991be..632ecc29cd31b727f714be859154a53182ade178 100644 (file)
@@ -4,8 +4,10 @@ import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.actor.Terminated;
 import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
@@ -53,7 +55,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
+                ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testReadData");
 
             new Within(duration("1 seconds")) {
@@ -63,7 +65,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                         new ReadData(YangInstanceIdentifier.builder().build()).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
@@ -93,7 +95,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
+                ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
             final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
 
             new Within(duration("1 seconds")) {
@@ -103,7 +105,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                         new ReadData(TestModel.TEST_PATH).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
@@ -139,7 +141,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                             getRef());
 
                     final CompositeModification compositeModification =
-                        new ExpectMsg<CompositeModification>("match hint") {
+                        new ExpectMsg<CompositeModification>(duration("1 seconds"), "match hint") {
                             // do not put code outside this method, will run afterwards
                             protected CompositeModification match(Object in) {
                                 if (in instanceof ShardTransaction.GetCompositeModificationReply) {
@@ -167,7 +169,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+                ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
             final ActorRef subject =
                 getSystem().actorOf(props, "testWriteData");
 
@@ -178,7 +180,7 @@ public class ShardTransactionTest extends AbstractActorTest {
                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
                         getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
@@ -244,7 +246,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+                ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
             final ActorRef subject =
                 getSystem().actorOf(props, "testDeleteData");
 
@@ -253,7 +255,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
@@ -281,7 +283,7 @@ public class ShardTransactionTest extends AbstractActorTest {
         new JavaTestKit(getSystem()) {{
             final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
             final Props props =
-                ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+                ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
             final ActorRef subject =
                 getSystem().actorOf(props, "testReadyTransaction");
 
@@ -290,7 +292,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     subject.tell(new ReadyTransaction().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
@@ -328,7 +330,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     subject.tell(new CloseTransaction().toSerializable(), getRef());
 
-                    final String out = new ExpectMsg<String>("match hint") {
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
@@ -341,7 +343,7 @@ public class ShardTransactionTest extends AbstractActorTest {
 
                     assertEquals("match", out);
 
-                    final String termination = new ExpectMsg<String>("match hint") {
+                    final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
                         // do not put code outside this method, will run afterwards
                         protected String match(Object in) {
                             if (in instanceof Terminated) {
@@ -361,4 +363,24 @@ public class ShardTransactionTest extends AbstractActorTest {
         }};
 
     }
+
+
+  @Test
+  public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
+    try {
+
+        final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
+        final Props props =
+            ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
+         final TestActorRef subject = TestActorRef.apply(props,getSystem());
+
+        subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
+        Assert.assertFalse(true);
+
+
+    } catch (Exception cs) {
+      assertEquals(cs.getClass().getSimpleName(), Exception.class.getSimpleName());
+      assertTrue(cs.getMessage().startsWith("ShardTransaction:handleRecieve received an unknown message"));
+    }
+  }
 }
index 992518e100a0381ab4c915128cc7975510bed2fc..4eca5671f626543b5c9ca8052f1427945c72a302 100644 (file)
@@ -2,8 +2,14 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
 import akka.actor.Props;
+
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
 import junit.framework.Assert;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.messages.AbortTransactionReply;
@@ -14,7 +20,6 @@ import org.opendaylight.controller.cluster.datastore.utils.MessageCollectorActor
 import org.opendaylight.controller.cluster.datastore.utils.MockActorContext;
 
 import java.util.Arrays;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 import static org.junit.Assert.assertNotNull;
@@ -25,7 +30,8 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
     private Props props;
     private ActorRef actorRef;
     private MockActorContext actorContext;
-    private ExecutorService executor = Executors.newSingleThreadExecutor();
+    private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(
+                        Executors.newSingleThreadExecutor());
 
     @Before
     public void setUp(){
@@ -39,6 +45,11 @@ public class ThreePhaseCommitCohortProxyTest extends AbstractActorTest {
 
     }
 
+    @After
+    public void tearDown() {
+        executor.shutdownNow();
+    }
+
     @Test
     public void testCanCommit() throws Exception {
         actorContext.setExecuteRemoteOperationResponse(new CanCommitTransactionReply(true).toSerializable());
index f654e3aced738ef0c85a6400babe901d9c98d3ea..0cd029c2ffb2da4c093ede214ca037d5a5a345dc 100644 (file)
@@ -2,11 +2,19 @@ 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 com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
 import junit.framework.Assert;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.exceptions.PrimaryNotFoundException;
+import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
@@ -26,11 +34,17 @@ import org.opendaylight.controller.protobuff.messages.transaction.ShardTransacti
 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 scala.concurrent.duration.FiniteDuration;
 
 import java.util.List;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+import static junit.framework.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 public class TransactionProxyTest extends AbstractActorTest {
 
     private final Configuration configuration = new MockConfiguration();
@@ -38,14 +52,19 @@ public class TransactionProxyTest extends AbstractActorTest {
     private final ActorContext testContext =
         new ActorContext(getSystem(), getSystem().actorOf(Props.create(DoNothingActor.class)), new MockClusterWrapper(), configuration );
 
-    private ExecutorService transactionExecutor =
-        Executors.newSingleThreadExecutor();
+    private final ListeningExecutorService transactionExecutor =
+        MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
 
     @Before
     public void setUp(){
         ShardStrategyFactory.setConfiguration(configuration);
     }
 
+    @After
+    public void tearDown() {
+        transactionExecutor.shutdownNow();
+    }
+
     @Test
     public void testRead() throws Exception {
         final Props props = Props.create(DoNothingActor.class);
@@ -111,6 +130,68 @@ public class TransactionProxyTest extends AbstractActorTest {
         Assert.assertFalse(normalizedNodeOptional.isPresent());
     }
 
+    @Test
+    public void testReadWhenAPrimaryNotFoundExceptionIsThrown() throws Exception {
+        final ActorContext actorContext = mock(ActorContext.class);
+
+        when(actorContext.executeShardOperation(anyString(), any(), any(
+            FiniteDuration.class))).thenThrow(new PrimaryNotFoundException("test"));
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext());
+
+
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> read =
+            transactionProxy.read(TestModel.TEST_PATH);
+
+        Assert.assertFalse(read.get().isPresent());
+
+    }
+
+
+    @Test
+    public void testReadWhenATimeoutExceptionIsThrown() throws Exception {
+        final ActorContext actorContext = mock(ActorContext.class);
+
+        when(actorContext.executeShardOperation(anyString(), any(), any(
+            FiniteDuration.class))).thenThrow(new TimeoutException("test", new Exception("reason")));
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext());
+
+
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> read =
+            transactionProxy.read(TestModel.TEST_PATH);
+
+        Assert.assertFalse(read.get().isPresent());
+
+    }
+
+    @Test
+    public void testReadWhenAAnyOtherExceptionIsThrown() throws Exception {
+        final ActorContext actorContext = mock(ActorContext.class);
+
+        when(actorContext.executeShardOperation(anyString(), any(), any(
+            FiniteDuration.class))).thenThrow(new NullPointerException());
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext());
+
+
+        try {
+            ListenableFuture<Optional<NormalizedNode<?, ?>>> read =
+                transactionProxy.read(TestModel.TEST_PATH);
+            fail("A null pointer exception was expected");
+        } catch(NullPointerException e){
+
+        }
+    }
+
+
+
     @Test
     public void testWrite() throws Exception {
         final Props props = Props.create(MessageCollectorActor.class);
index 88753e4b0a56165ed6cba8e2433f9bbc0089e8dc..3394cdc959757e167cb71988cf3d8e208fde041d 100644 (file)
@@ -1,6 +1,5 @@
 package org.opendaylight.controller.cluster.datastore.shardstrategy;
 
-import junit.framework.Assert;
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
@@ -8,6 +7,10 @@ import org.junit.rules.ExpectedException;
 import org.opendaylight.controller.cluster.datastore.Configuration;
 import org.opendaylight.controller.cluster.datastore.ConfigurationImpl;
 import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import static junit.framework.Assert.assertEquals;
 
 public class ModuleShardStrategyTest {
     @Rule
@@ -28,6 +31,23 @@ public class ModuleShardStrategyTest {
 
         String shard = moduleShardStrategy.findShard(CarsModel.BASE_PATH);
 
-        Assert.assertEquals("cars-1", shard);
+        assertEquals("cars-1", shard);
+    }
+
+    @Test
+    public void testFindShardWhenModuleConfigurationPresentInModulesButMissingInModuleShards() {
+
+        final QName BASE_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:missing", "2014-03-13",
+            "missing");
+
+        final YangInstanceIdentifier BASE_PATH = YangInstanceIdentifier.of(BASE_QNAME);
+
+        ModuleShardStrategy moduleShardStrategy =
+            new ModuleShardStrategy("missing", configuration);
+
+        String shard = moduleShardStrategy.findShard(BASE_PATH);
+
+        assertEquals(DefaultShardStrategy.DEFAULT_SHARD, shard);
+
     }
 }
index 3dd0214e9b213c49a4821c303362f13eebe11371..5874eccda40f4f2d08f6b829757206213a743696 100644 (file)
@@ -2,12 +2,20 @@ package org.opendaylight.controller.cluster.datastore.utils;
 
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+import akka.testkit.JavaTestKit;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
 import org.opendaylight.controller.cluster.datastore.ClusterWrapper;
 import org.opendaylight.controller.cluster.datastore.Configuration;
+import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard;
+import org.opendaylight.controller.cluster.datastore.messages.LocalShardFound;
+import org.opendaylight.controller.cluster.datastore.messages.LocalShardNotFound;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.mockito.Mockito.mock;
 
 public class ActorContextTest extends AbstractActorTest{
@@ -44,4 +52,145 @@ public class ActorContextTest extends AbstractActorTest{
         System.out.println(actorContext
             .actorFor("akka://system/user/shardmanager/shard/transaction"));
     }
+
+
+    private static class MockShardManager extends UntypedActor {
+
+        private final boolean found;
+        private final ActorRef actorRef;
+
+        private MockShardManager(boolean found, ActorRef actorRef){
+
+            this.found = found;
+            this.actorRef = actorRef;
+        }
+
+        @Override public void onReceive(Object message) throws Exception {
+            if(found){
+                getSender().tell(new LocalShardFound(actorRef), getSelf());
+            } else {
+                getSender().tell(new LocalShardNotFound(((FindLocalShard) message).getShardName()), getSelf());
+            }
+        }
+
+        private static Props props(final boolean found, final ActorRef actorRef){
+            return Props.create(new Creator<MockShardManager>() {
+
+                @Override public MockShardManager create()
+                    throws Exception {
+                    return new MockShardManager(found,
+                        actorRef);
+                }
+            });
+        }
+    }
+
+    @Test
+    public void testExecuteLocalShardOperationWithShardFound(){
+        new JavaTestKit(getSystem()) {{
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    ActorRef shardActorRef = getSystem().actorOf(Props.create(EchoActor.class));
+
+                    ActorRef shardManagerActorRef = getSystem()
+                        .actorOf(MockShardManager.props(true, shardActorRef));
+
+                    ActorContext actorContext =
+                        new ActorContext(getSystem(), shardManagerActorRef , mock(ClusterWrapper.class),
+                            mock(Configuration.class));
+
+                    Object out = actorContext.executeLocalShardOperation("default", "hello", duration("1 seconds"));
+
+                    assertEquals("hello", out);
+
+
+                    expectNoMsg();
+                }
+            };
+        }};
+
+    }
+
+    @Test
+    public void testExecuteLocalShardOperationWithShardNotFound(){
+        new JavaTestKit(getSystem()) {{
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    ActorRef shardManagerActorRef = getSystem()
+                        .actorOf(MockShardManager.props(false, null));
+
+                    ActorContext actorContext =
+                        new ActorContext(getSystem(), shardManagerActorRef , mock(ClusterWrapper.class),
+                            mock(Configuration.class));
+
+                    Object out = actorContext.executeLocalShardOperation("default", "hello", duration("1 seconds"));
+
+                    assertNull(out);
+
+
+                    expectNoMsg();
+                }
+            };
+        }};
+
+    }
+
+
+    @Test
+    public void testFindLocalShardWithShardFound(){
+        new JavaTestKit(getSystem()) {{
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    ActorRef shardActorRef = getSystem().actorOf(Props.create(EchoActor.class));
+
+                    ActorRef shardManagerActorRef = getSystem()
+                        .actorOf(MockShardManager.props(true, shardActorRef));
+
+                    ActorContext actorContext =
+                        new ActorContext(getSystem(), shardManagerActorRef , mock(ClusterWrapper.class),
+                            mock(Configuration.class));
+
+                    Object out = actorContext.findLocalShard("default");
+
+                    assertEquals(shardActorRef, out);
+
+
+                    expectNoMsg();
+                }
+            };
+        }};
+
+    }
+
+    @Test
+    public void testFindLocalShardWithShardNotFound(){
+        new JavaTestKit(getSystem()) {{
+
+            new Within(duration("1 seconds")) {
+                protected void run() {
+
+                    ActorRef shardManagerActorRef = getSystem()
+                        .actorOf(MockShardManager.props(false, null));
+
+                    ActorContext actorContext =
+                        new ActorContext(getSystem(), shardManagerActorRef , mock(ClusterWrapper.class),
+                            mock(Configuration.class));
+
+                    Object out = actorContext.findLocalShard("default");
+
+                    assertNull(out);
+
+
+                    expectNoMsg();
+                }
+            };
+        }};
+
+    }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/EchoActor.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/utils/EchoActor.java
new file mode 100644 (file)
index 0000000..fe88afe
--- /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.utils;
+
+import akka.actor.UntypedActor;
+
+/**
+ * The EchoActor simply responds back with the same message that it receives
+ */
+public class EchoActor extends UntypedActor{
+
+    @Override public void onReceive(Object message) throws Exception {
+        getSender().tell(message, getSelf());
+    }
+}
index 1d1e6614886e32d5593112375cbefaab0a9c1507..5d3853f311880d791fc177c9a1082f026fb1c5de 100644 (file)
@@ -19,6 +19,7 @@ public class MockActorContext extends ActorContext {
     private Object executeShardOperationResponse;
     private Object executeRemoteOperationResponse;
     private Object executeLocalOperationResponse;
+    private Object executeLocalShardOperationResponse;
 
     public MockActorContext(ActorSystem actorSystem) {
         super(actorSystem, null, new MockClusterWrapper(), new MockConfiguration());
@@ -56,8 +57,18 @@ public class MockActorContext extends ActorContext {
         this.executeLocalOperationResponse = executeLocalOperationResponse;
     }
 
+    public void setExecuteLocalShardOperationResponse(
+        Object executeLocalShardOperationResponse) {
+        this.executeLocalShardOperationResponse = executeLocalShardOperationResponse;
+    }
+
     @Override public Object executeLocalOperation(ActorRef actor,
         Object message, FiniteDuration duration) {
         return this.executeLocalOperationResponse;
     }
+
+    @Override public Object executeLocalShardOperation(String shardName,
+        Object message, FiniteDuration duration) {
+        return this.executeLocalShardOperationResponse;
+    }
 }
index 57df20172d59b6008c691617363788d4b64e7d23..6860872b75fddaf0c952af3943a8713f977531f5 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.md.cluster.datastore.model;
 
+import java.math.BigInteger;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@@ -42,14 +43,14 @@ public class CarsModel {
         MapEntryNode altima =
             ImmutableNodes.mapEntryBuilder(CAR_QNAME, CAR_NAME_QNAME, "altima")
                 .withChild(ImmutableNodes.leafNode(CAR_NAME_QNAME, "altima"))
-                .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, 1000))
+                .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, new BigInteger("1000")))
                 .build();
 
         // Create an entry for the car accord
         MapEntryNode honda =
             ImmutableNodes.mapEntryBuilder(CAR_QNAME, CAR_NAME_QNAME, "accord")
                 .withChild(ImmutableNodes.leafNode(CAR_NAME_QNAME, "accord"))
-                .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, 2000))
+                .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, new BigInteger("2000")))
                 .build();
 
         cars.withChild(altima);
index 1b4020af438c356a3b07b01ded9c179d02a7bdc1..e637920e7855c9859ee9cab249f31b20766e9ef2 100644 (file)
@@ -42,14 +42,14 @@ public class PeopleModel {
         MapEntryNode jack =
             ImmutableNodes.mapEntryBuilder(PERSON_QNAME, PERSON_NAME_QNAME, "jack")
                 .withChild(ImmutableNodes.leafNode(PERSON_NAME_QNAME, "jack"))
-                .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 100))
+                .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 100L))
                 .build();
 
         // Create an entry for the person jill
         MapEntryNode jill =
             ImmutableNodes.mapEntryBuilder(PERSON_QNAME, PERSON_NAME_QNAME, "jill")
                 .withChild(ImmutableNodes.leafNode(PERSON_NAME_QNAME, "jill"))
-                .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 200))
+                .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 200L))
                 .build();
 
         cars.withChild(jack);
index d8fefcd986cc8033d6530622039c5e0ce005114f..be8713c7020c5848e7eec03278a95a9794a095ad 100644 (file)
@@ -18,45 +18,45 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 public class SampleModelsTest {
     @Test
     public void testPeopleModel(){
-        NormalizedNode<?, ?> expected = PeopleModel.create();
+        final NormalizedNode<?, ?> expected = PeopleModel.create();
 
 
-        NormalizedNodeMessages.Container node =
+        final NormalizedNodeMessages.Container node =
             new NormalizedNodeToNodeCodec(SchemaContextHelper.full())
                 .encode(YangInstanceIdentifier.of(PeopleModel.BASE_QNAME),
                     expected);
 
-        NormalizedNodeMessages.Node normalizedNode =
+        final NormalizedNodeMessages.Node normalizedNode =
             node.getNormalizedNode();
 
-        NormalizedNode<?,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(YangInstanceIdentifier.of(PeopleModel.BASE_QNAME),
+        final NormalizedNode<?,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(YangInstanceIdentifier.of(PeopleModel.BASE_QNAME),
             normalizedNode);
 
 
-        Assert.assertEquals(expected.toString(), actual.toString());
+        Assert.assertEquals(expected, actual);
 
     }
 
 
     @Test
     public void testCarsModel(){
-        NormalizedNode<?, ?> expected = CarsModel.create();
+        final NormalizedNode<?, ?> expected = CarsModel.create();
 
 
-        NormalizedNodeMessages.Container node =
+        final NormalizedNodeMessages.Container node =
             new NormalizedNodeToNodeCodec(SchemaContextHelper.full())
                 .encode(YangInstanceIdentifier.of(CarsModel.BASE_QNAME),
                     expected);
 
-        NormalizedNodeMessages.Node normalizedNode =
+        final NormalizedNodeMessages.Node normalizedNode =
             node.getNormalizedNode();
 
-        NormalizedNode<?,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(
+        final NormalizedNode<?,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(
             YangInstanceIdentifier.of(CarsModel.BASE_QNAME),
             normalizedNode);
 
 
-        Assert.assertEquals(expected.toString(), actual.toString());
+        Assert.assertEquals(expected, actual);
 
     }
 }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Client.java
new file mode 100644 (file)
index 0000000..2671be8
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.programs.appendentries;
+
+import akka.actor.ActorSelection;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import com.typesafe.config.ConfigFactory;
+import org.opendaylight.controller.cluster.datastore.CompositeModificationPayload;
+import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
+import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
+import org.opendaylight.controller.cluster.example.messages.KeyValue;
+import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Client {
+
+    private static ActorSystem actorSystem;
+
+    public static class ClientActor extends UntypedActor {
+
+        @Override public void onReceive(Object message) throws Exception {
+
+        }
+    }
+
+    public static void main(String[] args){
+        actorSystem = ActorSystem.create("appendentries", ConfigFactory
+            .load().getConfig("ODLCluster"));
+
+        ActorSelection actorSelection = actorSystem.actorSelection(
+            "akka.tcp://appendentries@127.0.0.1:2550/user/server");
+
+        AppendEntries appendEntries = modificationAppendEntries();
+
+        Payload data = appendEntries.getEntries().get(0).getData();
+        if(data instanceof CompositeModificationPayload) {
+            System.out.println(
+                "Sending : " + ((CompositeModificationPayload) data)
+                    .getModification());
+        } else {
+            System.out.println(
+                "Sending : " + ((KeyValue) data)
+                    .getKey());
+
+        }
+
+        actorSelection.tell(appendEntries.toSerializable(), null);
+
+
+
+
+        actorSystem.actorOf(Props.create(ClientActor.class), "client");
+    }
+
+    public static AppendEntries modificationAppendEntries() {
+        List<ReplicatedLogEntry> modification = new ArrayList<>();
+
+        modification.add(0, new ReplicatedLogEntry() {
+            @Override public Payload getData() {
+                WriteModification writeModification =
+                    new WriteModification(TestModel.TEST_PATH, ImmutableNodes
+                        .containerNode(TestModel.TEST_QNAME),
+                        TestModel.createTestContext()
+                    );
+
+                MutableCompositeModification compositeModification =
+                    new MutableCompositeModification();
+
+                compositeModification.addModification(writeModification);
+
+                return new CompositeModificationPayload(
+                    compositeModification.toSerializable());
+            }
+
+            @Override public long getTerm() {
+                return 1;
+            }
+
+            @Override public long getIndex() {
+                return 1;
+            }
+        });
+
+        return new AppendEntries(1, "member-1", 0, 100, modification, 1);
+    }
+
+    public static AppendEntries keyValueAppendEntries() {
+        List<ReplicatedLogEntry> modification = new ArrayList<>();
+
+        modification.add(0, new ReplicatedLogEntry() {
+            @Override public Payload getData() {
+                return new KeyValue("moiz", "test");
+            }
+
+            @Override public long getTerm() {
+                return 1;
+            }
+
+            @Override public long getIndex() {
+                return 1;
+            }
+        });
+
+        return new AppendEntries(1, "member-1", 0, 100, modification, 1);
+    }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Server.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Server.java
new file mode 100644 (file)
index 0000000..0e6d535
--- /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.programs.appendentries;
+
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import com.typesafe.config.ConfigFactory;
+import org.opendaylight.controller.cluster.datastore.CompositeModificationPayload;
+import org.opendaylight.controller.cluster.example.messages.KeyValue;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+
+public class Server {
+
+    private static ActorSystem actorSystem;
+
+    public static class ServerActor extends UntypedActor {
+
+        @Override public void onReceive(Object message) throws Exception {
+            if(AppendEntries.SERIALIZABLE_CLASS.equals(message.getClass())){
+                AppendEntries appendEntries =
+                    AppendEntries.fromSerializable(message);
+
+                Payload data = appendEntries.getEntries()
+                    .get(0).getData();
+                if(data instanceof KeyValue){
+                    System.out.println("Received : " + ((KeyValue) appendEntries.getEntries().get(0).getData()).getKey());
+                } else {
+                    System.out.println("Received :" +
+                        ((CompositeModificationPayload) appendEntries
+                            .getEntries()
+                            .get(0).getData()).getModification().toString());
+                }
+            } else if(message instanceof String){
+                System.out.println(message);
+            }
+        }
+    }
+
+    public static void main(String[] args){
+        actorSystem = ActorSystem.create("appendentries", ConfigFactory
+            .load().getConfig("ODLCluster"));
+
+        actorSystem.actorOf(Props.create(ServerActor.class), "server");
+    }
+}
index aebff27c7dc0345864bfb8ecff9f5b30789ecf24..eda1c304e42bcac73e3e8597a3028324732e223e 100644 (file)
@@ -1,4 +1,5 @@
 akka {
+    loggers = [akka.testkit.TestEventListener]
     actor {
          serializers {
                   java = "akka.serialization.JavaSerializer"
index 22854cb11a968bd66f1b969d95a5cc07da7941de..f4919e7895a88d48840365effc16b4d55c6deda6 100644 (file)
@@ -15,4 +15,10 @@ modules = [
      shard-strategy = "module"
     }
 
+    {
+     name = "missing"
+     namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:missing"
+     shard-strategy = "module"
+    }
+
 ]
index afa2286d53d94d4af669af7ba2c542221961372c..fc251c8445a77d1485a2dffc4880afa9b3907f95 100644 (file)
@@ -9,11 +9,12 @@ package org.opendaylight.controller.md.sal.dom.api;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncReadTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.CheckedFuture;
 
 /**
  * A transaction that provides read access to a logical data store.
@@ -33,14 +34,17 @@ public interface DOMDataReadTransaction extends AsyncReadTransaction<YangInstanc
      * @param path
      *            Path which uniquely identifies subtree which client want to
      *            read
-     * @return Listenable Future which contains read result
+     * @return a CheckFuture containing the result of the read. The Future blocks until the
+     *         commit operation is complete. Once complete:
      *         <ul>
-     *         <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 ListenbleFuture#get()} returns {@link Optional#absent()}.
+     *         <li>If the data at the supplied path exists, the Future returns an Optional object
+     *         containing the data.</li>
+     *         <li>If the data at the supplied path does not exist, the Future returns
+     *         Optional#absent().</li>
+     *         <li>If the read of the data fails, the Future will fail with a
+     *         {@link ReadFailedException} or an exception derived from ReadFailedException.</li>
      *         </ul>
      */
-    ListenableFuture<Optional<NormalizedNode<?,?>>> read(LogicalDatastoreType store,YangInstanceIdentifier path);
+    CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(
+            LogicalDatastoreType store, YangInstanceIdentifier path);
 }
index 34e5b1b8033d2cbda100b1fe6b0552af983abee3..c3e979c536b268c4a6156b7241e745f328569618 100644 (file)
@@ -11,7 +11,7 @@ import org.opendaylight.controller.sal.core.api.BrokerService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 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.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 
 public interface SchemaService extends BrokerService {
 
@@ -42,5 +42,11 @@ public interface SchemaService extends BrokerService {
      */
     SchemaContext getGlobalContext();
 
-    ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener);
+    /**
+     * Register a listener for changes in schema context.
+     *
+     * @param listener Listener which should be registered
+     * @return Listener registration handle
+     */
+    ListenerRegistration<SchemaContextListener> registerSchemaContextListener(SchemaContextListener listener);
 }
index 17b78f4ebd0e6602532f4fd7f5869d184d8125ba..f1f16cd635ba9ab336eb286ba3e8593c51dc2c50 100644 (file)
@@ -91,7 +91,7 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi
         wrappedStore.changeDelegate(legacyStore);
         wrappedStore.setValidationEnabled(false);
 
-        schemaService.registerSchemaServiceListener(wrappedStore);
+        schemaService.registerSchemaContextListener(wrappedStore);
 
         dataService.registerConfigurationReader(rootPath, wrappedStore);
         dataService.registerCommitHandler(rootPath, wrappedStore);
index 69b17ee3c48aeb5aae64dc8c4b02e36abdfce7a7..22dad6af23c1464b63f8a4aa25075551b64ef686 100644 (file)
@@ -10,9 +10,11 @@ package org.opendaylight.controller.config.yang.md.sal.dom.impl;
 import java.util.concurrent.Executors;
 
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
 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.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -50,7 +52,7 @@ public final class DomInmemoryDataBrokerModule extends
            //we will default to InMemoryDOMDataStore creation
           operStore = new InMemoryDOMDataStore("DOM-OPER", storeExecutor);
           //here we will register the SchemaContext listener
-          getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)operStore);
+          getSchemaServiceDependency().registerSchemaContextListener((InMemoryDOMDataStore)operStore);
         }
 
         DOMStore configStore = getConfigDataStoreDependency();
@@ -58,13 +60,15 @@ public final class DomInmemoryDataBrokerModule extends
            //we will default to InMemoryDOMDataStore creation
            configStore = new InMemoryDOMDataStore("DOM-CFG", storeExecutor);
           //here we will register the SchemaContext listener
-          getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)configStore);
+          getSchemaServiceDependency().registerSchemaContextListener((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()));
+        DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores,
+                new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+                                              TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION));
 
         return newDataBroker;
     }
index fbc418dc2aec0203d4f52ad6b7ace8cc083ca019..62b026430ac07756bb21d2a90095a4c73ce6229a 100644 (file)
@@ -13,7 +13,7 @@ import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 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.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -90,8 +90,8 @@ org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImp
         }
 
         @Override
-        public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(final SchemaServiceListener arg0) {
-            return delegate.registerSchemaServiceListener(arg0);
+        public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(final SchemaContextListener arg0) {
+            return delegate.registerSchemaContextListener(arg0);
         }
 
         @Override
index 8b9eb445fd45b4d19f5a3f6523a7ce2a711ef310..9a6d12fb1872fc0a96556b06133a48894e14a532 100644 (file)
@@ -15,6 +15,7 @@ import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -91,7 +92,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
             Futures.addCallback(commitFuture, new DOMDataCommitErrorInvoker(transaction, listener.get()));
         }
 
-        return Futures.makeChecked(commitFuture, TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
+        return MappingCheckedFuture.create(commitFuture,
+                TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
     }
 
     /**
@@ -285,7 +287,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
              */
             @SuppressWarnings({ "unchecked", "rawtypes" })
             ListenableFuture<Void> compositeResult = (ListenableFuture) Futures.allAsList(ops.build());
-            return Futures.makeChecked(compositeResult, TransactionCommitFailedExceptionMapper.PRE_COMMIT_MAPPER);
+            return MappingCheckedFuture.create(compositeResult,
+                                         TransactionCommitFailedExceptionMapper.PRE_COMMIT_MAPPER);
         }
 
         /**
@@ -316,7 +319,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
              */
             @SuppressWarnings({ "unchecked", "rawtypes" })
             ListenableFuture<Void> compositeResult = (ListenableFuture) Futures.allAsList(ops.build());
-            return Futures.makeChecked(compositeResult, TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
+            return MappingCheckedFuture.create(compositeResult,
+                                     TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
         }
 
         /**
@@ -342,8 +346,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
             }
             ListenableFuture<List<Boolean>> allCanCommits = Futures.allAsList(canCommitOperations.build());
             ListenableFuture<Boolean> allSuccessFuture = Futures.transform(allCanCommits, AND_FUNCTION);
-            return Futures
-                    .makeChecked(allSuccessFuture, TransactionCommitFailedExceptionMapper.CAN_COMMIT_ERROR_MAPPER);
+            return MappingCheckedFuture.create(allSuccessFuture,
+                                       TransactionCommitFailedExceptionMapper.CAN_COMMIT_ERROR_MAPPER);
 
         }
 
index c8edcbc6e2ef1dcf50e6b644da69c0224a62c140..b4562cf2eccd2c8b6560552c510fe1bfeb8d9989 100644 (file)
@@ -8,6 +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.common.api.data.ReadFailedException;
 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.YangInstanceIdentifier;
@@ -15,7 +16,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.CheckedFuture;
 
 /**
  *
@@ -34,8 +35,8 @@ class DOMForwardedReadOnlyTransaction extends
     }
 
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store,
-            final YangInstanceIdentifier path) {
+    public CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(
+            final LogicalDatastoreType store, final YangInstanceIdentifier path) {
         return getSubtransaction(store).read(path);
     }
 
index e6521b237727f10a8a1ccef376da0f13c0d61af9..74a4c52e36ff33883754b0ef5543706054134967 100644 (file)
@@ -7,6 +7,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.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -14,7 +15,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.CheckedFuture;
 
 /**
  *
@@ -45,8 +46,8 @@ class DOMForwardedReadWriteTransaction extends DOMForwardedWriteTransaction<DOMS
     }
 
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store,
-            final YangInstanceIdentifier path) {
+    public CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(
+            final LogicalDatastoreType store, final YangInstanceIdentifier path) {
         return getSubtransaction(store).read(path);
     }
 }
\ No newline at end of file
index 258b06892963c1d311e01bdef1a69c6d884d9ed5..799a8a09edc3144b78896c0dc3a64f0603572d45 100644 (file)
@@ -7,29 +7,16 @@
  */
 package org.opendaylight.controller.md.sal.dom.broker.impl;
 
-import java.util.concurrent.ExecutionException;
-
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.util.concurrent.ExceptionMapper;
 
 /**
+ * Utility exception mapper which translates Exception to {@link TransactionCommitFailedException}.
  *
- * Utility exception mapper which translates {@link Exception}
- * to {@link TransactionCommitFailedException}.
- *
- * This mapper is intended to be used with {@link com.google.common.util.concurrent.Futures#makeChecked(com.google.common.util.concurrent.ListenableFuture, Function)}
- * <ul>
- * <li>if exception is {@link TransactionCommitFailedException} or one of its subclasses returns original exception.
- * <li>if exception is {@link ExecutionException} and cause is  {@link TransactionCommitFailedException} return cause
- * <li>otherwise returns {@link TransactionCommitFailedException} with original exception as a cause.
- * </ul>
- *
+ * @see ExceptionMapper
  */
-
-final class TransactionCommitFailedExceptionMapper implements
-        Function<Exception, TransactionCommitFailedException> {
+final class TransactionCommitFailedExceptionMapper
+                           extends ExceptionMapper<TransactionCommitFailedException> {
 
     static final TransactionCommitFailedExceptionMapper PRE_COMMIT_MAPPER = create("canCommit");
 
@@ -37,10 +24,8 @@ final class TransactionCommitFailedExceptionMapper implements
 
     static final TransactionCommitFailedExceptionMapper COMMIT_ERROR_MAPPER = create("commit");
 
-    private final String opName;
-
     private TransactionCommitFailedExceptionMapper(final String opName) {
-        this.opName = Preconditions.checkNotNull(opName);
+        super( opName, TransactionCommitFailedException.class );
     }
 
     public static final TransactionCommitFailedExceptionMapper create(final String opName) {
@@ -48,22 +33,7 @@ final class TransactionCommitFailedExceptionMapper implements
     }
 
     @Override
-    public TransactionCommitFailedException apply(final Exception e) {
-        // If excetion is TransactionCommitFailedException
-        // we reuse it directly.
-        if (e instanceof TransactionCommitFailedException) {
-            return (TransactionCommitFailedException) e;
-        }
-        // If error is ExecutionException which was caused by cause of
-        // TransactionCommitFailedException
-        // we reuse original cause
-        if (e instanceof ExecutionException && e.getCause() instanceof TransactionCommitFailedException) {
-            return (TransactionCommitFailedException) e.getCause();
-        }
-        if (e instanceof InterruptedException) {
-            return new TransactionCommitFailedException(opName + " failed - DOMStore was interupted.", e);
-        }
-        // Otherwise we are using new exception, with original cause
-        return new TransactionCommitFailedException(opName + " failed", e);
+    protected TransactionCommitFailedException newWithCause( String message, Throwable cause ) {
+        return new TransactionCommitFailedException( message, cause );
     }
 }
\ No newline at end of file
index e8f8da53c90dd7ff1cafd2f96f50cc2072a5c432..dc122cfdc24d672f9bcf563e26501a57b79bbad4 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
 package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
 
 import javax.annotation.concurrent.ThreadSafe;
@@ -21,18 +28,17 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
 
 @ThreadSafe
 public class BackwardsCompatibleDataBroker implements DataProviderService {
 
     private final DOMDataBroker backingBroker;
     private volatile DataNormalizer normalizer;
-    private final ListenerRegistration<SchemaServiceListener> schemaReg;
+    private final ListenerRegistration<SchemaContextListener> schemaReg;
 
     public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl, final SchemaService schemaService) {
         backingBroker = newBiDataImpl;
-        schemaReg = schemaService.registerSchemaServiceListener(new SchemaListener());
+        schemaReg = schemaService.registerSchemaContextListener(new SchemaListener());
     }
 
     @Override
index d837d75ddc09aecef00a9d2dc7fc78e5be89890c..5bd8a7bc021f935fd20251892101f861e2c2db39 100644 (file)
@@ -15,16 +15,20 @@ import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ListenableFuture;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import javax.annotation.Nullable;
+
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
@@ -72,7 +76,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 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.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 
 public class BackwardsCompatibleMountPoint implements MountProvisionInstance, SchemaContextProvider, SchemaService {
 
@@ -83,7 +87,7 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
     private final NotificationPublishService notificationPublishService;
     private final RpcProvisionRegistry rpcs;
 
-    private final ListenerRegistry<SchemaServiceListener> schemaListenerRegistry = new ListenerRegistry<>();
+    private final ListenerRegistry<SchemaContextListener> schemaListenerRegistry = new ListenerRegistry<>();
 
     private SchemaContext schemaContext;
 
@@ -154,7 +158,7 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
     }
 
     @Override
-    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(final SchemaServiceListener listener) {
+    public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(final SchemaContextListener listener) {
         return schemaListenerRegistry.register(listener);
     }
 
@@ -275,7 +279,7 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
     @Override
     public void setSchemaContext(final SchemaContext schemaContext) {
         this.schemaContext = schemaContext;
-        for (ListenerRegistration<SchemaServiceListener> schemaServiceListenerListenerRegistration : schemaListenerRegistry.getListeners()) {
+        for (ListenerRegistration<SchemaContextListener> schemaServiceListenerListenerRegistration : schemaListenerRegistry.getListeners()) {
             schemaServiceListenerListenerRegistration.getInstance().onGlobalContextUpdated(schemaContext);
         }
     }
@@ -380,7 +384,8 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
             }
 
             @Override
-            public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+            public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
+                    final LogicalDatastoreType store, final YangInstanceIdentifier path) {
 
                 CompositeNode rawData = null;
 
@@ -398,7 +403,7 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
 
                 final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = normalizer.toNormalized(path, rawData);
                 final Optional<NormalizedNode<?, ?>> normalizedNodeOptional = Optional.<NormalizedNode<?, ?>>fromNullable(normalized.getValue());
-                return com.google.common.util.concurrent.Futures.immediateFuture(normalizedNodeOptional);
+                return Futures.immediateCheckedFuture(normalizedNodeOptional);
             }
         }
 
@@ -508,7 +513,8 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
             }
 
             @Override
-            public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+            public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
+                    final LogicalDatastoreType store, final YangInstanceIdentifier path) {
                 return new BackwardsCompatibleReadTransaction(dataReader, dataNormalizer).read(store, path);
             }
 
index d8174c312ab0e9622a23f17549dd841130a633ff..82637327f6b10d719c04e4fa04ad6a7b53b2dafe 100644 (file)
@@ -23,7 +23,7 @@ import org.opendaylight.yangtools.concepts.Registration;
 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;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.opendaylight.yangtools.yang.parser.impl.util.URLSchemaContextResolver;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -40,15 +40,15 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
-public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvider, SchemaService, ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, AutoCloseable {
+public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvider, SchemaService, ServiceTrackerCustomizer<SchemaContextListener, SchemaContextListener>, AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class);
 
-    private final ListenerRegistry<SchemaServiceListener> listeners = new ListenerRegistry<>();
+    private final ListenerRegistry<SchemaContextListener> listeners = new ListenerRegistry<>();
     private final URLSchemaContextResolver contextResolver = new URLSchemaContextResolver();
     private final BundleScanner scanner = new BundleScanner();
     private final BundleContext context;
 
-    private ServiceTracker<SchemaServiceListener, SchemaServiceListener> listenerTracker;
+    private ServiceTracker<SchemaContextListener, SchemaContextListener> listenerTracker;
     private BundleTracker<Iterable<Registration>> bundleTracker;
     private boolean starting = true;
     private static GlobalBundleScanningSchemaServiceImpl instance;
@@ -81,7 +81,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     public void start() {
         checkState(context != null);
 
-        listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, GlobalBundleScanningSchemaServiceImpl.this);
+        listenerTracker = new ServiceTracker<>(context, SchemaContextListener.class, GlobalBundleScanningSchemaServiceImpl.this);
         bundleTracker = new BundleTracker<>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
         bundleTracker.open();
         listenerTracker.open();
@@ -115,7 +115,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     }
 
     @Override
-    public synchronized ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(final SchemaServiceListener listener) {
+    public synchronized ListenerRegistration<SchemaContextListener> registerSchemaContextListener(final SchemaContextListener listener) {
         Optional<SchemaContext> potentialCtx = contextResolver.getSchemaContext();
         if(potentialCtx.isPresent()) {
             listener.onGlobalContextUpdated(potentialCtx.get());
@@ -137,7 +137,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
 
     private synchronized void updateContext(final SchemaContext snapshot) {
         Object[] services = listenerTracker.getServices();
-        for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+        for (ListenerRegistration<SchemaContextListener> listener : listeners) {
             try {
                 listener.getInstance().onGlobalContextUpdated(snapshot);
             } catch (Exception e) {
@@ -146,7 +146,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
         }
         if (services != null) {
             for (Object rawListener : services) {
-                SchemaServiceListener listener = (SchemaServiceListener) rawListener;
+                final SchemaContextListener listener = (SchemaContextListener) rawListener;
                 try {
                     listener.onGlobalContextUpdated(snapshot);
                 } catch (Exception e) {
@@ -213,9 +213,9 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     }
 
     @Override
-    public synchronized SchemaServiceListener addingService(final ServiceReference<SchemaServiceListener> reference) {
+    public synchronized SchemaContextListener addingService(final ServiceReference<SchemaContextListener> reference) {
 
-        SchemaServiceListener listener = context.getService(reference);
+        SchemaContextListener listener = context.getService(reference);
         SchemaContext _ctxContext = getGlobalContext();
         if (getContext() != null && _ctxContext != null) {
             listener.onGlobalContextUpdated(_ctxContext);
@@ -234,12 +234,12 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
     }
 
     @Override
-    public void modifiedService(final ServiceReference<SchemaServiceListener> reference, final SchemaServiceListener service) {
+    public void modifiedService(final ServiceReference<SchemaContextListener> reference, final SchemaContextListener service) {
         // NOOP
     }
 
     @Override
-    public void removedService(final ServiceReference<SchemaServiceListener> reference, final SchemaServiceListener service) {
+    public void removedService(final ServiceReference<SchemaContextListener> reference, final SchemaContextListener service) {
         context.ungetService(reference);
     }
 }
index 1d864eec5bab32c2e1de266ed22eb5f065273109..d8d2346a8cfa42a89685a2dc12552920aea59664 100644 (file)
@@ -8,10 +8,10 @@
 package org.opendaylight.controller.sal.dom.broker.osgi;
 
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 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.osgi.framework.ServiceReference;
 
 public class SchemaServiceProxy extends AbstractBrokerServiceProxy<SchemaService> implements SchemaService {
@@ -41,12 +41,9 @@ public class SchemaServiceProxy extends AbstractBrokerServiceProxy<SchemaService
     }
 
     @Override
-    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
-        ListenerRegistration<SchemaServiceListener> registration = getDelegate().registerSchemaServiceListener(listener);
+    public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(SchemaContextListener listener) {
+        ListenerRegistration<SchemaContextListener> registration = getDelegate().registerSchemaContextListener(listener);
         addRegistration(registration);
         return registration;
     }
-
-
-
 }
index b006ca94e5d1387bfd84e7a76eccba3700756905..0bb16a39b90f7eb513093b18faa20815061fad3c 100644 (file)
@@ -3,26 +3,40 @@ package org.opendaylight.controller.md.sal.dom.broker.impl;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
+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.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.collect.ImmutableMap;
+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 com.google.common.util.concurrent.MoreExecutors;
@@ -31,6 +45,7 @@ public class DOMBrokerTest {
 
     private SchemaContext schemaContext;
     private DOMDataBrokerImpl domBroker;
+    private ListeningExecutorService executor;
 
     @Before
     public void setupStore() {
@@ -46,11 +61,19 @@ public class DOMBrokerTest {
                 .put(OPERATIONAL, operStore) //
                 .build();
 
-        ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+        executor = new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+                                          TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION);
         domBroker = new DOMDataBrokerImpl(stores, executor);
     }
 
-    @Test
+    @After
+    public void tearDown() {
+        if( executor != null ) {
+            executor.shutdownNow();
+        }
+    }
+
+    @Test(timeout=10000)
     public void testTransactionIsolation() throws InterruptedException, ExecutionException {
 
         assertNotNull(domBroker);
@@ -86,7 +109,7 @@ public class DOMBrokerTest {
         assertFalse(readTxContainer.get().isPresent());
     }
 
-    @Test
+    @Test(timeout=10000)
     public void testTransactionCommit() throws InterruptedException, ExecutionException {
 
         DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
@@ -114,6 +137,173 @@ public class DOMBrokerTest {
         assertTrue(afterCommitRead.isPresent());
     }
 
+    /**
+     * Tests a simple DataChangeListener notification after a write.
+     */
+    @Test
+    public void testDataChangeListener() throws Throwable {
+
+        final NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode( TestModel.TEST_QNAME );
+
+        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener();
+
+        domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+                                              dcListener, DataChangeScope.BASE );
+
+        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
+
+        writeTx.put( OPERATIONAL, TestModel.TEST_PATH, testNode );
+
+        AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+        dcListener.waitForChange();
+
+        if( caughtEx.get() != null ) {
+            throw caughtEx.get();
+        }
+
+        NormalizedNode<?, ?> actualNode = dcListener.change.getCreatedData().get( TestModel.TEST_PATH );
+        assertEquals( "Created node", testNode, actualNode );
+    }
+
+    /**
+     * Tests a DataChangeListener that does an async submit of a write Tx in its onDataChanged method.
+     * This should succeed without deadlock.
+     */
+    @Test
+    public void testDataChangeListenerDoingAsyncWriteTxSubmit() throws Throwable {
+
+        final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+        final CountDownLatch commitCompletedLatch = new CountDownLatch( 1 );
+
+        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+            @Override
+            public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+
+                DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+                writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+                             ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+                Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
+                    @Override
+                    public void onSuccess( Void result ) {
+                        commitCompletedLatch.countDown();
+                    }
+
+                    @Override
+                    public void onFailure( Throwable t ) {
+                        caughtCommitEx.set( t );
+                        commitCompletedLatch.countDown();
+                    }
+                } );
+
+                super.onDataChanged( change );
+            }
+        };
+
+        domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+                                              dcListener, DataChangeScope.BASE );
+
+        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
+
+        writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+        AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+        dcListener.waitForChange();
+
+        if( caughtEx.get() != null ) {
+            throw caughtEx.get();
+        }
+
+        assertTrue( "Commit Future was not invoked", commitCompletedLatch.await( 5, TimeUnit.SECONDS ) );
+
+        if( caughtCommitEx.get() != null ) {
+            throw caughtCommitEx.get();
+        }
+    }
+
+    /**
+     * Tests a DataChangeListener that does a blocking submit of a write Tx in its onDataChanged method.
+     * This should throw an exception and not deadlock.
+     */
+    @Test(expected=TransactionCommitDeadlockException.class)
+    public void testDataChangeListenerDoingBlockingWriteTxSubmit() throws Throwable {
+
+        final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+
+        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+            @Override
+            public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+                DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+                writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+                             ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+                try {
+                    writeTx.submit().get();
+                } catch( ExecutionException e ) {
+                    caughtCommitEx.set( e.getCause() );
+                } catch( Exception e ) {
+                    caughtCommitEx.set( e );
+                }
+                finally {
+                    super.onDataChanged( change );
+                }
+            }
+        };
+
+        domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+                                              dcListener, DataChangeScope.BASE );
+
+        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
+
+        writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+        AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
 
+        dcListener.waitForChange();
 
+        if( caughtEx.get() != null ) {
+            throw caughtEx.get();
+        }
+
+        if( caughtCommitEx.get() != null ) {
+            throw caughtCommitEx.get();
+        }
+    }
+
+    AtomicReference<Throwable> submitTxAsync( final DOMDataWriteTransaction writeTx ) {
+        final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
+        new Thread() {
+            @Override
+            public void run() {
+
+                try {
+                    writeTx.submit();
+                } catch( Throwable e ) {
+                    caughtEx.set( e );
+                }
+            }
+
+        }.start();
+
+        return caughtEx;
+    }
+
+    static class TestDOMDataChangeListener implements DOMDataChangeListener {
+
+        volatile AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change;
+        private final CountDownLatch latch = new CountDownLatch( 1 );
+
+        @Override
+        public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+            this.change = change;
+            latch.countDown();
+        }
+
+        void waitForChange() throws InterruptedException {
+            assertTrue( "onDataChanged was not called", latch.await( 5, TimeUnit.SECONDS ) );
+        }
+    }
 }
index d5ba2a2b9a50212e0b75c4036f1afc5fc890b065..09835ec5e37dcd92db413be12cfe5d35967d0910 100644 (file)
@@ -21,6 +21,8 @@ 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 TEST2_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+            "test2");
     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");
@@ -30,6 +32,7 @@ public class TestModel {
     private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
 
     public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
+    public static final YangInstanceIdentifier TEST2_PATH = YangInstanceIdentifier.of(TEST2_QNAME);
     public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.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");
index 17541fecab02c62f35c7a64cd679ad3ca52849e6..5fbf470f090e44e9e3c080998baa1c1a3a948c46 100644 (file)
@@ -39,4 +39,7 @@ module odl-datastore-test {
             }
         }
     }
+
+    container test2 {
+    }
 }
\ No newline at end of file
index ae1b3ee2aa32db9eb0836a6403fcadc5d0615a87..84d09c7cb024a275ebfdfa6edd8a75af00abc3af 100644 (file)
@@ -7,29 +7,31 @@
  */
 package org.opendaylight.controller.sal.core.spi.data;
 
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.CheckedFuture;
 
 public interface DOMStoreReadTransaction extends DOMStoreTransaction {
 
     /**
-     *
      * Reads data from provided logical data store located at provided path
      *
-     *
      * @param path
      *            Path which uniquely identifies subtree which client want to
      *            read
-     * @return Listenable Future which contains read result
+     * @return a CheckFuture containing the result of the read. The Future blocks until the
+     *         commit operation is complete. Once complete:
      *         <ul>
-     *         <li>If data at supplied path exists the {@link java.util.concurrent.Future#get()}
-     *         returns Optional object containing data
-     *         <li>If data at supplied path does not exists the
-     *         {@link java.util.concurrent.Future#get()} returns {@link Optional#absent()}.
+     *         <li>If the data at the supplied path exists, the Future returns an Optional object
+     *         containing the data.</li>
+     *         <li>If the data at the supplied path does not exist, the Future returns
+     *         Optional#absent().</li>
+     *         <li>If the read of the data fails, the Future will fail with a
+     *         {@link ReadFailedException} or an exception derived from ReadFailedException.</li>
      *         </ul>
      */
-    ListenableFuture<Optional<NormalizedNode<?,?>>> read(YangInstanceIdentifier path);
+    CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(YangInstanceIdentifier path);
 }
index 399f49bd6b49094acf9aa92a63fc68e0c874ed18..59cdc76e7ade377911d0cdc1e841b573ab35913f 100644 (file)
@@ -20,7 +20,7 @@ public class XSQLModule extends org.opendaylight.yang.gen.v1.http.netconfcentral
     @Override
     public java.lang.AutoCloseable createInstance() {
         XSQLAdapter xsqlAdapter = XSQLAdapter.getInstance();
-        getSchemaServiceDependency().registerSchemaServiceListener(xsqlAdapter);
+        getSchemaServiceDependency().registerSchemaContextListener(xsqlAdapter);
         xsqlAdapter.setDataBroker(getAsyncDataBrokerDependency());
         XSQLProvider p = new XSQLProvider();
         p.buildXSQL(getDataBrokerDependency());
index 906847426c6087d9b486de7aeb3237f28f971a7f..725b24cd9e733c342d26adf5b07076aa7348c49e 100644 (file)
       <artifactId>binding-generator-impl</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>mockito-configuration</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-test-model</artifactId>
       <scope>test</scope>
-      <version>${project.version}</version>
-    </dependency>
+      </dependency>
   </dependencies>
 
   <build>
index 01a5989dcd8a6b5afa67a50844e540cbd68c80c5..805608d479e0e76d1ecebb6a7398a884e11498cb 100644 (file)
@@ -23,7 +23,7 @@ public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.cont
     @Override
     public java.lang.AutoCloseable createInstance() {
       InMemoryDOMDataStore   ids = new InMemoryDOMDataStore("DOM-CFG", MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
-      getSchemaServiceDependency().registerSchemaServiceListener(ids);
+      getSchemaServiceDependency().registerSchemaContextListener(ids);
       return ids;
     }
 
index b39c9bbbd8ca7f0cbe504470ec5f9237e88c0a70..f4795588ab61ef62a9f74f6eb1530da1b6307141 100644 (file)
@@ -23,7 +23,7 @@ public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight
     @Override
     public java.lang.AutoCloseable createInstance() {
       InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-OPER", MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
-      getOperationalSchemaServiceDependency().registerSchemaServiceListener(ids);
+      getOperationalSchemaServiceDependency().registerSchemaContextListener(ids);
       return ids;
     }
 
index ff64cd64c412d57b12da080468f188d457948c6b..3ddf0b60faf07323f7f26cb4d7488851015ef688 100644 (file)
@@ -9,9 +9,15 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 
 import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
 
+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;
@@ -37,13 +43,6 @@ 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;
-
 /**
  * Resolve Data Change Events based on modifications and listeners
  *
@@ -278,6 +277,11 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             final Collection<Node> listeners, final NormalizedNode<?, ?> beforeData,
             final NormalizedNode<?, ?> afterData) {
 
+        // FIXME: BUG-1493: check the listeners to prune unneeded changes:
+        //                  for subtrees, we have to do all
+        //                  for one, we need to expand children
+        //                  for base, we just report replacement
+
         if (beforeData instanceof NormalizedNodeContainer<?, ?, ?>) {
             // Node is container (contains child) and we have interested
             // listeners registered for it, that means we need to do
@@ -306,14 +310,12 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             final Collection<Node> listeners,
             final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont,
                     final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
-        final Set<PathArgument> alreadyProcessed = new HashSet<>();
         final List<DOMImmutableDataChangeEvent> childChanges = new LinkedList<>();
 
-        DataChangeScope potentialScope = DataChangeScope.BASE;
         // We look at all children from before and compare it with after state.
         for (NormalizedNode<PathArgument, ?> beforeChild : beforeCont.getValue()) {
-            PathArgument childId = beforeChild.getIdentifier();
-            alreadyProcessed.add(childId);
+            final PathArgument childId = beforeChild.getIdentifier();
+
             YangInstanceIdentifier childPath = path.node(childId);
             Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
             Optional<NormalizedNode<PathArgument, ?>> afterChild = afterCont.getChild(childId);
@@ -323,15 +325,17 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             if (childChange != NO_CHANGE) {
                 childChanges.add(childChange);
             }
-
         }
 
         for (NormalizedNode<PathArgument, ?> afterChild : afterCont.getValue()) {
-            PathArgument childId = afterChild.getIdentifier();
-            if (!alreadyProcessed.contains(childId)) {
-                // We did not processed that child already
-                // and it was not present in previous loop, that means it is
-                // created.
+            final PathArgument childId = afterChild.getIdentifier();
+
+            /*
+             * We have already iterated of the before-children, so have already
+             * emitted modify/delete events. This means the child has been
+             * created.
+             */
+            if (!beforeCont.getChild(childId).isPresent()) {
                 Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
                 YangInstanceIdentifier childPath = path.node(childId);
                 childChanges.add(resolveSameEventRecursivelly(childPath , childListeners, afterChild,
@@ -342,7 +346,7 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             return NO_CHANGE;
         }
 
-        Builder eventBuilder = builder(potentialScope) //
+        Builder eventBuilder = builder(DataChangeScope.BASE) //
                 .setBefore(beforeCont) //
                 .setAfter(afterCont)
                 .addUpdated(path, beforeCont, afterCont);
index 39d6483c525ed648ea8c7f922ce8c57ee0064af0..2a9840634381efea5c76cfd220530a11a83d80f0 100644 (file)
@@ -8,9 +8,8 @@
 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.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -19,8 +18,8 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
 
 /**
  *
@@ -30,8 +29,9 @@ import com.google.common.util.concurrent.ListenableFuture;
  * which delegates most of its calls to similar methods provided by underlying snapshot.
  *
  */
-final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
-DOMStoreReadTransaction {
+final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction
+                                          implements DOMStoreReadTransaction {
+
     private static final Logger LOG = LoggerFactory.getLogger(SnapshotBackedReadTransaction.class);
     private DataTreeSnapshot stableSnapshot;
 
@@ -48,9 +48,19 @@ DOMStoreReadTransaction {
     }
 
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final YangInstanceIdentifier path) {
+    public CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(final YangInstanceIdentifier path) {
+        LOG.debug("Tx: {} Read: {}", getIdentifier(), path);
         checkNotNull(path, "Path must not be null.");
-        checkState(stableSnapshot != null, "Transaction is closed");
-        return Futures.immediateFuture(stableSnapshot.readNode(path));
+
+        if(stableSnapshot == null) {
+            return Futures.immediateFailedCheckedFuture(new ReadFailedException("Transaction is closed"));
+        }
+
+        try {
+            return Futures.immediateCheckedFuture(stableSnapshot.readNode(path));
+        } catch (Exception e) {
+            LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
+            return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e));
+        }
     }
 }
\ No newline at end of file
index ec17d7a3f7e4cbaccc2c5a4ffa1f65cddbd8d60e..5c5e9c6b6d82f4263959c6f8e137cc0bf1af25ad 100644 (file)
@@ -7,7 +7,11 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -15,16 +19,16 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
 
 /**
  * Implementation of Read-Write transaction which is backed by {@link DataTreeSnapshot}
  * and executed according to {@link TransactionReadyPrototype}.
  *
  */
-class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements
-DOMStoreReadWriteTransaction {
+class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction
+                                         implements DOMStoreReadWriteTransaction {
 
     private static final Logger LOG = LoggerFactory.getLogger(SnapshotBackedReadWriteTransaction.class);
 
@@ -41,13 +45,20 @@ DOMStoreReadWriteTransaction {
     }
 
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final YangInstanceIdentifier path) {
+    public CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(final YangInstanceIdentifier path) {
         LOG.debug("Tx: {} Read: {}", getIdentifier(), path);
+        checkNotNull(path, "Path must not be null.");
+
+        DataTreeModification dataView = getMutatedView();
+        if(dataView == null) {
+            return Futures.immediateFailedCheckedFuture(new ReadFailedException("Transaction is closed"));
+        }
+
         try {
-            return Futures.immediateFuture(getMutatedView().readNode(path));
+            return Futures.immediateCheckedFuture(dataView.readNode(path));
         } catch (Exception e) {
             LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
-            throw e;
+            return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e));
         }
     }
 }
\ No newline at end of file
index 96369dea5fabc7d3ce25272f5e0cceaf5291a0c6..9b105aa3064121b518295220a5fb3351d030c13b 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -16,12 +17,22 @@ import java.util.concurrent.ExecutionException;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction.TransactionReadyPrototype;
 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.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+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.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;
@@ -31,226 +42,373 @@ import com.google.common.util.concurrent.MoreExecutors;
 
 public class InMemoryDataStoreTest {
 
-  private SchemaContext schemaContext;
-  private InMemoryDOMDataStore domStore;
+    private SchemaContext schemaContext;
+    private InMemoryDOMDataStore domStore;
 
-  @Before
-  public void setupStore() {
-    domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.sameThreadExecutor());
-    schemaContext = TestModel.createTestContext();
-    domStore.onGlobalContextUpdated(schemaContext);
+    @Before
+    public void setupStore() {
+        domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.sameThreadExecutor());
+        schemaContext = TestModel.createTestContext();
+        domStore.onGlobalContextUpdated(schemaContext);
+    }
 
-  }
+    @Test
+    public void testTransactionIsolation() throws InterruptedException, ExecutionException {
 
-  @Test
-  public void testTransactionIsolation() throws InterruptedException, ExecutionException {
+        assertNotNull(domStore);
 
-    assertNotNull(domStore);
+        DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
+        assertNotNull(readTx);
 
-    DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
-    assertNotNull(readTx);
+        DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+        assertNotNull(writeTx);
 
-    DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
-    assertNotNull(writeTx);
-    /**
-     *
-     * Writes /test in writeTx
-     *
-     */
-    writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+        /**
+         * Writes /test in writeTx
+         */
+        NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+        writeTx.write(TestModel.TEST_PATH, testNode);
 
-    /**
-     *
-     * Reads /test from writeTx Read should return container.
-     *
-     */
-    ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
-    assertTrue(writeTxContainer.get().isPresent());
+        /**
+         * Reads /test from writeTx Read should return container.
+         */
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
+        assertEquals("read: isPresent", true, writeTxContainer.get().isPresent());
+        assertEquals("read: data", testNode, writeTxContainer.get().get());
 
-    /**
-     *
-     * Reads /test from readTx Read should return Absent.
-     *
-     */
-    ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx.read(TestModel.TEST_PATH);
-    assertFalse(readTxContainer.get().isPresent());
-  }
+        /**
+         * Reads /test from readTx Read should return Absent.
+         */
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx.read(TestModel.TEST_PATH);
+        assertEquals("read: isPresent", false, readTxContainer.get().isPresent());
+    }
 
-  @Test
-  public void testTransactionCommit() throws InterruptedException, ExecutionException {
+    @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));
+        DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+        assertNotNull(writeTx);
 
-    /**
-     *
-     * Reads /test from writeTx Read should return container.
-     *
-     */
-    ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
-    assertTrue(writeTxContainer.get().isPresent());
+        /**
+         * Writes /test in writeTx
+         */
+        NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
+        writeTx.write(TestModel.TEST_PATH, testNode);
 
-    DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
+        /**
+         * Reads /test from writeTx Read should return container.
+         */
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
+        assertEquals("read: isPresent", true, writeTxContainer.get().isPresent());
+        assertEquals("read: data", testNode, writeTxContainer.get().get());
 
-    assertThreePhaseCommit(cohort);
+        DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
 
-    Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
-        .get();
-    assertTrue(afterCommitRead.isPresent());
-  }
+        assertThreePhaseCommit(cohort);
 
-  @Test
-  public void testTransactionAbort() throws InterruptedException, ExecutionException {
+        Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
+                .get();
+        assertEquals("After commit read: isPresent", true, afterCommitRead.isPresent());
+        assertEquals("After commit read: data", testNode, afterCommitRead.get());
+    }
 
-    DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
-    assertNotNull(writeTx);
+    @Test
+    public void testDelete() throws Exception {
 
-    assertTestContainerWrite(writeTx);
+        DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
 
-    DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
+        // Write /test and commit
 
-    assertTrue(cohort.canCommit().get().booleanValue());
-    cohort.preCommit().get();
-    cohort.abort().get();
+        writeTx.write( TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
 
-    Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
-        .get();
-    assertFalse(afterCommitRead.isPresent());
-  }
+        assertThreePhaseCommit( writeTx.ready() );
 
-  @Test
-  public void testTransactionChain() throws InterruptedException, ExecutionException {
-    DOMStoreTransactionChain txChain = domStore.createTransactionChain();
-    assertNotNull(txChain);
+        Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().
+                read(TestModel.TEST_PATH ).get();
+        assertEquals( "After commit read: isPresent", true, afterCommitRead.isPresent() );
 
-    /**
-     * We alocate new read-write transaction and write /test
-     *
-     *
-     */
-    DOMStoreReadWriteTransaction firstTx = txChain.newReadWriteTransaction();
-    assertTestContainerWrite(firstTx);
+        // Delete /test and verify
 
-    /**
-     * First transaction is marked as ready, we are able to allocate chained
-     * transactions
-     */
-    DOMStoreThreePhaseCommitCohort firstWriteTxCohort = firstTx.ready();
+        writeTx = domStore.newWriteOnlyTransaction();
 
-    /**
-     * We alocate chained transaction - read transaction, note first one is
-     * still not commited to datastore.
-     */
-    DOMStoreReadTransaction secondReadTx = txChain.newReadOnlyTransaction();
+        writeTx.delete( TestModel.TEST_PATH );
 
-    /**
-     *
-     * We test if we are able to read data from tx, read should not fail
-     * since we are using chained transaction.
-     *
-     *
-     */
-    assertTestContainerExists(secondReadTx);
+        assertThreePhaseCommit( writeTx.ready() );
 
-    /**
-     *
-     * We alocate next transaction, which is still based on first one, but
-     * is read-write.
-     *
-     */
-    DOMStoreReadWriteTransaction thirdDeleteTx = txChain.newReadWriteTransaction();
+        afterCommitRead = domStore.newReadOnlyTransaction().
+                read(TestModel.TEST_PATH ).get();
+        assertEquals( "After commit read: isPresent", false, afterCommitRead.isPresent() );
+    }
 
-    /**
-     * We test existence of /test in third transaction container should
-     * still be visible from first one (which is still uncommmited).
-     *
-     *
-     */
-    assertTestContainerExists(thirdDeleteTx);
+    @Test
+    public void testMerge() throws Exception {
 
-    /**
-     * We delete node in third transaction
-     */
-    thirdDeleteTx.delete(TestModel.TEST_PATH);
+        DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
 
-    /**
-     * third transaction is sealed.
-     */
-    DOMStoreThreePhaseCommitCohort thirdDeleteTxCohort = thirdDeleteTx.ready();
+        ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier( new NodeIdentifier( TestModel.TEST_QNAME ) )
+                .addChild( ImmutableNodes.mapNodeBuilder( TestModel.OUTER_LIST_QNAME )
+                        .addChild( ImmutableNodes.mapEntry( TestModel.OUTER_LIST_QNAME,
+                                                            TestModel.ID_QNAME, 1 ) ).build() ).build();
 
-    /**
-     * We commit first transaction
-     *
-     */
-    assertThreePhaseCommit(firstWriteTxCohort);
+        writeTx.merge( TestModel.TEST_PATH, containerNode );
 
-    // 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);
-  }
+        assertThreePhaseCommit( writeTx.ready() );
 
-  @Test
-  @Ignore
-  public void testTransactionConflict() throws InterruptedException, ExecutionException {
-    DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
-    DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
-    assertTestContainerWrite(txOne);
-    assertTestContainerWrite(txTwo);
+        Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().
+                read(TestModel.TEST_PATH ).get();
+        assertEquals( "After commit read: isPresent", true, afterCommitRead.isPresent() );
+        assertEquals( "After commit read: data", containerNode, afterCommitRead.get() );
 
-    /**
-     * Commits transaction
-     */
-    assertThreePhaseCommit(txOne.ready());
+        // Merge a new list entry node
 
-    /**
-     * 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));
+        writeTx = domStore.newWriteOnlyTransaction();
+        assertNotNull( writeTx );
+
+        containerNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier( new NodeIdentifier( TestModel.TEST_QNAME ) )
+                .addChild( ImmutableNodes.mapNodeBuilder( TestModel.OUTER_LIST_QNAME )
+                        .addChild( ImmutableNodes.mapEntry( TestModel.OUTER_LIST_QNAME,
+                                                            TestModel.ID_QNAME, 1 ) )
+                        .addChild( ImmutableNodes.mapEntry( TestModel.OUTER_LIST_QNAME,
+                                                            TestModel.ID_QNAME, 2 ) ).build() ).build();
+
+        writeTx.merge( TestModel.TEST_PATH, containerNode );
+
+        assertThreePhaseCommit( writeTx.ready() );
+
+        afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH ).get();
+        assertEquals( "After commit read: isPresent", true, afterCommitRead.isPresent() );
+        assertEquals( "After commit read: data", containerNode, afterCommitRead.get() );
+    }
+
+    @Test(expected=ReadFailedException.class)
+    public void testReadWithReadOnlyTransactionClosed() throws Throwable {
+
+        DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
+        assertNotNull( readTx );
+
+        readTx.close();
+
+        doReadAndThrowEx( readTx );
+    }
+
+    @Test(expected=ReadFailedException.class)
+    public void testReadWithReadOnlyTransactionFailure() throws Throwable {
+
+        DataTreeSnapshot mockSnapshot = Mockito.mock( DataTreeSnapshot.class );
+        Mockito.doThrow( new RuntimeException( "mock ex" ) ).when( mockSnapshot )
+        .readNode( Mockito.any( YangInstanceIdentifier.class ) );
+
+        DOMStoreReadTransaction readTx = new SnapshotBackedReadTransaction( "1", mockSnapshot );
+
+        doReadAndThrowEx( readTx );
+    }
 
-    return assertTestContainerExists(writeTx);
-  }
+    @Test(expected=ReadFailedException.class)
+    public void testReadWithReadWriteTransactionClosed() throws Throwable {
 
-  /**
-   * Reads /test from readTx Read should return container.
-   */
-  private static Optional<NormalizedNode<?, ?>> assertTestContainerExists(final DOMStoreReadTransaction readTx)
-      throws InterruptedException, ExecutionException {
+        DOMStoreReadTransaction readTx = domStore.newReadWriteTransaction();
+        assertNotNull( readTx );
+
+        readTx.close();
+
+        doReadAndThrowEx( readTx );
+    }
+
+    @Test(expected=ReadFailedException.class)
+    public void testReadWithReadWriteTransactionFailure() throws Throwable {
+
+        DataTreeSnapshot mockSnapshot = Mockito.mock( DataTreeSnapshot.class );
+        DataTreeModification mockModification = Mockito.mock( DataTreeModification.class );
+        Mockito.doThrow( new RuntimeException( "mock ex" ) ).when( mockModification )
+        .readNode( Mockito.any( YangInstanceIdentifier.class ) );
+        Mockito.doReturn( mockModification ).when( mockSnapshot ).newModification();
+        TransactionReadyPrototype mockReady = Mockito.mock( TransactionReadyPrototype.class );
+        DOMStoreReadTransaction readTx = new SnapshotBackedReadWriteTransaction( "1", mockSnapshot, mockReady );
+
+        doReadAndThrowEx( readTx );
+    }
+
+    private void doReadAndThrowEx( DOMStoreReadTransaction readTx ) throws Throwable {
+
+        try {
+            readTx.read(TestModel.TEST_PATH).get();
+        } catch( ExecutionException e ) {
+            throw e.getCause();
+        }
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testWriteWithTransactionReady() throws Exception {
+
+        DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
+
+        writeTx.ready();
+
+        // Should throw ex
+        writeTx.write( TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testReadyWithTransactionAlreadyReady() throws Exception {
+
+        DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
+
+        writeTx.ready();
+
+        // Should throw ex
+        writeTx.ready();
+    }
+
+    @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(final DOMStoreReadTransaction readTx)
+            throws InterruptedException, ExecutionException {
 
-    ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = readTx.read(TestModel.TEST_PATH);
-    assertTrue(writeTxContainer.get().isPresent());
-    return writeTxContainer.get();
-  }
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = readTx.read(TestModel.TEST_PATH);
+        assertTrue(writeTxContainer.get().isPresent());
+        return writeTxContainer.get();
+    }
 
 }
index 10fe4a587a1f0c8ba7b52ac7e10314adbe1c9b62..049f8c2e3c7a4e6869d83bff20a8f0dad97c30de 100644 (file)
       <artifactId>logback-config</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-broker-impl</artifactId>
-      <scope>test</scope>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-broker-impl</artifactId>
index 037bfb4a82c2cd8f34dbfe05513e602e7077b3ff..b75df80f4ef4b3091975e3b5e0f50a70ed9bc71c 100644 (file)
@@ -13,8 +13,10 @@ import static org.opendaylight.controller.config.api.JmxAttributeValidationExcep
 import java.io.File;
 import java.io.InputStream;
 import java.net.InetSocketAddress;
+import java.util.List;
 import java.util.concurrent.ExecutorService;
 
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
@@ -24,6 +26,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities;
 import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceSalFacade;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.Broker;
@@ -40,6 +43,8 @@ import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+
 /**
  *
  */
@@ -49,6 +54,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
 
     private static AbstractCachingSchemaSourceProvider<String, InputStream> GLOBAL_NETCONF_SOURCE_PROVIDER = null;
     private BundleContext bundleContext;
+    private Optional<NetconfSessionCapabilities> userCapabilities;
 
     public NetconfConnectorModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
@@ -82,9 +88,11 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
             checkNotNull(getPassword(), passwordJmxAttribute);
         }
 
+        userCapabilities = getUserCapabilities();
+
     }
 
-    private boolean isHostAddressPresent(Host address) {
+    private boolean isHostAddressPresent(final Host address) {
         return address.getDomainName() != null ||
                address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
     }
@@ -98,10 +106,14 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         final Broker domBroker = getDomRegistryDependency();
         final BindingAwareBroker bindingBroker = getBindingRegistryDependency();
 
-        final RemoteDeviceHandler salFacade = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, globalProcessingExecutor);
+        final RemoteDeviceHandler<NetconfSessionCapabilities> salFacade
+                = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, globalProcessingExecutor);
         final NetconfDevice device =
                 NetconfDevice.createNetconfDevice(id, getGlobalNetconfSchemaProvider(), globalProcessingExecutor, salFacade);
-        final NetconfDeviceCommunicator listener = new NetconfDeviceCommunicator(id, device);
+
+        final NetconfDeviceCommunicator listener = userCapabilities.isPresent() ?
+                new NetconfDeviceCommunicator(id, device, userCapabilities.get()) : new NetconfDeviceCommunicator(id, device);
+
         final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(listener);
 
         final NetconfClientDispatcher dispatcher = getClientDispatcherDependency();
@@ -116,6 +128,26 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         };
     }
 
+    private Optional<NetconfSessionCapabilities> getUserCapabilities() {
+        if(getYangModuleCapabilities() == null) {
+            return Optional.absent();
+        }
+
+        final List<String> capabilities = getYangModuleCapabilities().getCapability();
+        if(capabilities == null || capabilities.isEmpty()) {
+            return Optional.absent();
+        }
+
+        final NetconfSessionCapabilities parsedOverrideCapabilities = NetconfSessionCapabilities.fromStrings(capabilities);
+        JmxAttributeValidationException.checkCondition(
+                parsedOverrideCapabilities.getNonModuleCaps().isEmpty(),
+                "Capabilities to override can only contain module based capabilities, non-module capabilities will be retrieved from the device," +
+                        " configured non-module capabilities: " + parsedOverrideCapabilities.getNonModuleCaps(),
+                yangModuleCapabilitiesJmxAttribute);
+
+        return Optional.of(parsedOverrideCapabilities);
+    }
+
     private synchronized AbstractCachingSchemaSourceProvider<String, InputStream> getGlobalNetconfSchemaProvider() {
         if(GLOBAL_NETCONF_SOURCE_PROVIDER == null) {
             final String storageFile = "cache/schema";
@@ -175,8 +207,8 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         if(getAddress().getDomainName() != null) {
             return new InetSocketAddress(getAddress().getDomainName().getValue(), getPort().getValue());
         } else {
-            IpAddress ipAddress = getAddress().getIpAddress();
-            String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
+            final IpAddress ipAddress = getAddress().getIpAddress();
+            final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
             return new InetSocketAddress(ip, getPort().getValue());
         }
     }
index de4ac7ac18a106f88f530ac4dc16ea047976b091..07d3c087740c811d4f8404c34d4d90c12ed17143 100644 (file)
@@ -118,6 +118,7 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
                 // Unable to initialize device, set as disconnected
                 logger.error("{}: Initialization failed", id, t);
                 salFacade.onDeviceDisconnected();
+                // TODO ssh connection is still open if sal initialization fails
             }
         });
     }
index 8045f8cb4a9556160b44fb46d4d3bbc12374435a..3871cdfa4f4cb7556313d8419407e1d3326dc802 100644 (file)
@@ -7,13 +7,19 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.listener;
 
+import com.google.common.base.Optional;
+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;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.FutureListener;
 import java.util.ArrayDeque;
 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;
@@ -36,31 +42,35 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 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;
-
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.FutureListener;
-
 public class NetconfDeviceCommunicator implements NetconfClientSessionListener, RemoteDeviceCommunicator<NetconfMessage> {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfDeviceCommunicator.class);
 
     private final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice;
+    private final Optional<NetconfSessionCapabilities> overrideNetconfCapabilities;
     private final RemoteDeviceId id;
     private final Lock sessionLock = new ReentrantLock();
 
+    private final Queue<Request> requests = new ArrayDeque<>();
+    private NetconfClientSession session;
+
+    public NetconfDeviceCommunicator(final RemoteDeviceId id, final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice,
+            final NetconfSessionCapabilities netconfSessionCapabilities) {
+        this(id, remoteDevice, Optional.of(netconfSessionCapabilities));
+    }
+
     public NetconfDeviceCommunicator(final RemoteDeviceId id,
-            final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice) {
+                                     final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice) {
+        this(id, remoteDevice, Optional.<NetconfSessionCapabilities>absent());
+    }
+
+    private NetconfDeviceCommunicator(final RemoteDeviceId id, final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice,
+            final Optional<NetconfSessionCapabilities> overrideNetconfCapabilities) {
         this.id = id;
         this.remoteDevice = remoteDevice;
+        this.overrideNetconfCapabilities = overrideNetconfCapabilities;
     }
 
-    private final Queue<Request> requests = new ArrayDeque<>();
-    private NetconfClientSession session;
-
     @Override
     public void onSessionUp(final NetconfClientSession session) {
         sessionLock.lock();
@@ -68,10 +78,15 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
             logger.debug("{}: Session established", id);
             this.session = session;
 
-            final NetconfSessionCapabilities netconfSessionCapabilities =
+            NetconfSessionCapabilities netconfSessionCapabilities =
                                              NetconfSessionCapabilities.fromNetconfSession(session);
             logger.trace("{}: Session advertised capabilities: {}", id, netconfSessionCapabilities);
 
+            if(overrideNetconfCapabilities.isPresent()) {
+                netconfSessionCapabilities = netconfSessionCapabilities.replaceModuleCaps(overrideNetconfCapabilities.get());
+                logger.debug("{}: Session capabilities overridden, capabilities that will be used: {}", id, netconfSessionCapabilities);
+            }
+
             remoteDevice.onRemoteSessionUp(netconfSessionCapabilities, this);
         }
         finally {
@@ -223,7 +238,7 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
                 return;
             }
 
-            request.future.set( RpcResultBuilder.<NetconfMessage>success( message ).build() );
+            request.future.set( RpcResultBuilder.success( message ).build() );
         }
     }
 
index 8964a80228bf848538dc83dfc6db71c05f93a102..1a7d90e9c0ad1d9424da229b29eef9ebf7c9b6a4 100644 (file)
@@ -8,6 +8,7 @@ import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 
+import com.google.common.collect.Sets;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
@@ -19,6 +20,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class NetconfSessionCapabilities {
+
     private static final class ParameterMatcher {
         private final Predicate<String> predicate;
         private final int skipLength;
@@ -57,10 +59,10 @@ public final class NetconfSessionCapabilities {
     };
 
     private final Set<QName> moduleBasedCaps;
-    private final Set<String> capabilities;
+    private final Set<String> nonModuleCaps;
 
-    private NetconfSessionCapabilities(final Set<String> capabilities, final Set<QName> moduleBasedCaps) {
-        this.capabilities = Preconditions.checkNotNull(capabilities);
+    private NetconfSessionCapabilities(final Set<String> nonModuleCaps, final Set<QName> moduleBasedCaps) {
+        this.nonModuleCaps = Preconditions.checkNotNull(nonModuleCaps);
         this.moduleBasedCaps = Preconditions.checkNotNull(moduleBasedCaps);
     }
 
@@ -68,30 +70,49 @@ public final class NetconfSessionCapabilities {
         return moduleBasedCaps;
     }
 
-    public boolean containsCapability(final String capability) {
-        return capabilities.contains(capability);
+    public Set<String> getNonModuleCaps() {
+        return nonModuleCaps;
+    }
+
+    public boolean containsNonModuleCapability(final String capability) {
+        return nonModuleCaps.contains(capability);
     }
 
-    public boolean containsCapability(final QName capability) {
+    public boolean containsModuleCapability(final QName capability) {
         return moduleBasedCaps.contains(capability);
     }
 
     @Override
     public String toString() {
         return Objects.toStringHelper(this)
-                .add("capabilities", capabilities)
+                .add("capabilities", nonModuleCaps)
+                .add("moduleBasedCapabilities", moduleBasedCaps)
                 .add("rollback", isRollbackSupported())
                 .add("monitoring", isMonitoringSupported())
                 .toString();
     }
 
     public boolean isRollbackSupported() {
-        return containsCapability(NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString());
+        return containsNonModuleCapability(NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString());
+    }
+
+    public boolean isCandidateSupported() {
+        return containsNonModuleCapability(NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString());
     }
 
     public boolean isMonitoringSupported() {
-        return containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)
-                || containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
+        return containsModuleCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)
+                || containsNonModuleCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
+    }
+
+    public NetconfSessionCapabilities replaceModuleCaps(final NetconfSessionCapabilities netconfSessionModuleCapabilities) {
+        final Set<QName> moduleBasedCaps = Sets.newHashSet(netconfSessionModuleCapabilities.getModuleBasedCaps());
+
+        // Preserve monitoring module, since it indicates support for ietf-netconf-monitoring
+        if(containsModuleCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)) {
+            moduleBasedCaps.add(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING);
+        }
+        return new NetconfSessionCapabilities(getNonModuleCaps(), moduleBasedCaps);
     }
 
     public static NetconfSessionCapabilities fromNetconfSession(final NetconfClientSession session) {
@@ -100,6 +121,7 @@ public final class NetconfSessionCapabilities {
 
     public static NetconfSessionCapabilities fromStrings(final Collection<String> capabilities) {
         final Set<QName> moduleBasedCaps = new HashSet<>();
+        final Set<String> nonModuleCaps = Sets.newHashSet(capabilities);
 
         for (final String capability : capabilities) {
             final int qmark = capability.indexOf('?');
@@ -117,6 +139,7 @@ public final class NetconfSessionCapabilities {
             String revision = REVISION_PARAM.from(queryParams);
             if (revision != null) {
                 moduleBasedCaps.add(QName.create(namespace, revision, moduleName));
+                nonModuleCaps.remove(capability);
                 continue;
             }
 
@@ -136,8 +159,9 @@ public final class NetconfSessionCapabilities {
 
             // FIXME: do we really want to continue here?
             moduleBasedCaps.add(QName.create(namespace, revision, moduleName));
+            nonModuleCaps.remove(capability);
         }
 
-        return new NetconfSessionCapabilities(ImmutableSet.copyOf(capabilities), ImmutableSet.copyOf(moduleBasedCaps));
+        return new NetconfSessionCapabilities(ImmutableSet.copyOf(nonModuleCaps), ImmutableSet.copyOf(moduleBasedCaps));
     }
 }
index ee0c8b72179d4101cd22bca526cc7e39cfe40100..f3a9acd630f33bfbf3339d9051d2c4fe4c733a10 100644 (file)
@@ -42,7 +42,7 @@ final class NetconfDeviceDataBroker implements DOMDataBroker {
 
     @Override
     public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
-        return new NetconfDeviceReadOnlyTx(rpc, normalizer);
+        return new NetconfDeviceReadOnlyTx(rpc, normalizer, id);
     }
 
     @Override
@@ -52,8 +52,7 @@ final class NetconfDeviceDataBroker implements DOMDataBroker {
 
     @Override
     public DOMDataWriteTransaction newWriteOnlyTransaction() {
-        // FIXME detect if candidate is supported, true is hardcoded
-        return new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, true, netconfSessionPreferences.isRollbackSupported());
+        return new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, netconfSessionPreferences.isCandidateSupported(), netconfSessionPreferences.isRollbackSupported());
     }
 
     @Override
index 3248453baf498f372715696aaf749c509005345d..533df9cce7f06575c75419a80f8b43e591dd3e7b 100644 (file)
@@ -15,42 +15,53 @@ import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessag
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction {
 
     private static final Logger LOG  = LoggerFactory.getLogger(NetconfDeviceReadOnlyTx.class);
 
     private final RpcImplementation rpc;
     private final DataNormalizer normalizer;
+    private final RemoteDeviceId id;
 
-    public NetconfDeviceReadOnlyTx(final RpcImplementation rpc, final DataNormalizer normalizer) {
+    public NetconfDeviceReadOnlyTx(final RpcImplementation rpc, final DataNormalizer normalizer, final RemoteDeviceId id) {
         this.rpc = rpc;
         this.normalizer = normalizer;
+        this.id = id;
     }
 
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> readConfigurationData(final YangInstanceIdentifier path) {
+    private CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readConfigurationData(
+            final YangInstanceIdentifier path) {
         final ListenableFuture<RpcResult<CompositeNode>> future = rpc.invokeRpc(NETCONF_GET_CONFIG_QNAME,
                 NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, CONFIG_SOURCE_RUNNING, toFilterStructure(path)));
 
-        return Futures.transform(future, new Function<RpcResult<CompositeNode>, Optional<NormalizedNode<?, ?>>>() {
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> transformedFuture = Futures.transform(future, new Function<RpcResult<CompositeNode>, Optional<NormalizedNode<?, ?>>>() {
             @Override
             public Optional<NormalizedNode<?, ?>> apply(final RpcResult<CompositeNode> result) {
+                checkReadSuccess(result, path);
+
                 final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
                 final CompositeNode node = (CompositeNode) findNode(data, path);
 
@@ -59,6 +70,17 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
                         transform(path, node);
             }
         });
+
+        return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER);
+    }
+
+    private void checkReadSuccess(final RpcResult<CompositeNode> result, final YangInstanceIdentifier path) {
+        try {
+            Preconditions.checkArgument(result.isSuccessful(), "%s: Unable to read data: %s, errors: %s", id, path, result.getErrors());
+        } catch (IllegalArgumentException e) {
+            LOG.warn("{}: Unable to read data: {}, errors: {}", id, path, result.getErrors());
+            throw e;
+        }
     }
 
     private Optional<NormalizedNode<?, ?>> transform(final YangInstanceIdentifier path, final CompositeNode node) {
@@ -68,17 +90,20 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
         try {
             return Optional.<NormalizedNode<?, ?>>of(normalizer.toNormalized(path, node).getValue());
         } catch (final Exception e) {
-            LOG.error("Unable to normalize data for {}, data: {}", path, node, e);
+            LOG.error("{}: Unable to normalize data for {}, data: {}", id, path, node, e);
             throw e;
         }
     }
 
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> readOperationalData(final YangInstanceIdentifier path) {
+    private CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readOperationalData(
+            final YangInstanceIdentifier path) {
         final ListenableFuture<RpcResult<CompositeNode>> future = rpc.invokeRpc(NETCONF_GET_QNAME, NetconfMessageTransformUtil.wrap(NETCONF_GET_QNAME, toFilterStructure(path)));
 
-        return Futures.transform(future, new Function<RpcResult<CompositeNode>, Optional<NormalizedNode<?, ?>>>() {
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> transformedFuture = Futures.transform(future, new Function<RpcResult<CompositeNode>, Optional<NormalizedNode<?, ?>>>() {
             @Override
             public Optional<NormalizedNode<?, ?>> apply(final RpcResult<CompositeNode> result) {
+                checkReadSuccess(result, path);
+
                 final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
                 final CompositeNode node = (CompositeNode) findNode(data, path);
 
@@ -87,6 +112,8 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
                         transform(path, node);
             }
         });
+
+        return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER);
     }
 
     private static Node<?> findNode(final CompositeNode node, final YangInstanceIdentifier identifier) {
@@ -122,8 +149,9 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
     }
 
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-        final YangInstanceIdentifier legacyPath = toLegacyPath(normalizer, path);
+    public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
+            final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+        final YangInstanceIdentifier legacyPath = toLegacyPath(normalizer, path, id);
 
         switch (store) {
             case CONFIGURATION : {
@@ -134,14 +162,14 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
             }
         }
 
-        throw new IllegalArgumentException(String.format("Cannot read data %s for %s datastore, unknown datastore type", path, store));
+        throw new IllegalArgumentException(String.format("%s, Cannot read data %s for %s datastore, unknown datastore type", id, path, store));
     }
 
-    static YangInstanceIdentifier toLegacyPath(final DataNormalizer normalizer, final YangInstanceIdentifier path) {
+    static YangInstanceIdentifier toLegacyPath(final DataNormalizer normalizer, final YangInstanceIdentifier path, final RemoteDeviceId id) {
         try {
             return normalizer.toLegacy(path);
         } catch (final DataNormalizationException e) {
-            throw new IllegalArgumentException("Cannot normalize path " + path, e);
+            throw new IllegalArgumentException(id + ": Cannot normalize path " + path, e);
         }
     }
 
index 4054cf940364872a1a75e313db9d06f2688c4290..3d2c3b9d44b95fc90355ba7ce1085b1749520b9f 100644 (file)
@@ -11,8 +11,10 @@ package org.opendaylight.controller.sal.connect.netconf.sal.tx;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.ListenableFuture;
+
 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.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
@@ -62,7 +64,8 @@ public class NetconfDeviceReadWriteTx implements DOMDataReadWriteTransaction {
     }
 
     @Override
-    public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+    public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
+            final LogicalDatastoreType store, final YangInstanceIdentifier path) {
         return delegateReadTx.read(store, path);
     }
 
index c8d90282109b3fcd244ceb163f47e1f0ce62036b..87f5477d35d0f986b6f2a0fd8b1044b8b421e58c 100644 (file)
@@ -8,10 +8,11 @@
 
 package org.opendaylight.controller.sal.connect.netconf.sal.tx;
 
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.DISCARD_CHANGES_RPC_CONTENT;
 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_DISCARD_CHANGES_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;
@@ -26,13 +27,14 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
-import javax.annotation.Nullable;
+import java.util.concurrent.atomic.AtomicBoolean;
 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.common.api.data.TransactionCommitFailedException;
@@ -57,97 +59,114 @@ import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
+public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction, FutureCallback<RpcResult<TransactionStatus>> {
 
     private static final Logger LOG  = LoggerFactory.getLogger(NetconfDeviceWriteOnlyTx.class);
 
     private final RemoteDeviceId id;
     private final RpcImplementation rpc;
     private final DataNormalizer normalizer;
+
     private final boolean rollbackSupported;
+    private final boolean candidateSupported;
     private final CompositeNode targetNode;
 
+    // Allow commit to be called only once
+    private final AtomicBoolean finished = new AtomicBoolean(false);
+
     public NetconfDeviceWriteOnlyTx(final RemoteDeviceId id, final RpcImplementation rpc, final DataNormalizer normalizer, final boolean candidateSupported, final boolean rollbackOnErrorSupported) {
         this.id = id;
         this.rpc = rpc;
         this.normalizer = normalizer;
-        this.targetNode = getTargetNode(candidateSupported);
+
+        this.candidateSupported = candidateSupported;
+        this.targetNode = getTargetNode(this.candidateSupported);
         this.rollbackSupported = rollbackOnErrorSupported;
     }
 
-    // FIXME add logging
-
     @Override
     public boolean cancel() {
-        if(isCommitted()) {
+        if(isFinished()) {
             return false;
         }
 
         return discardChanges();
     }
 
-    private boolean isCommitted() {
-        // TODO 732
-        return true;
+    private boolean isFinished() {
+        return finished.get();
     }
 
     private boolean discardChanges() {
-        // TODO 732
+        finished.set(true);
+
+        if(candidateSupported) {
+            sendDiscardChanges();
+        }
         return true;
     }
 
     // TODO should the edit operations be blocking ?
+    // TODO should the discard-changes operations be blocking ?
 
     @Override
     public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+        checkNotFinished();
         Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can merge only configuration, not %s", store);
 
         try {
-            final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path);
+            final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path, id);
             final CompositeNode legacyData = normalizer.toLegacy(path, data);
-            sendEditRpc(createEditConfigStructure(legacyPath, Optional.of(ModifyAction.REPLACE), Optional.fromNullable(legacyData)), Optional.of(ModifyAction.NONE));
+            sendEditRpc(
+                    createEditConfigStructure(legacyPath, Optional.of(ModifyAction.REPLACE), Optional.fromNullable(legacyData)), Optional.of(ModifyAction.NONE));
         } catch (final ExecutionException e) {
-            LOG.warn("Error putting data to {}, data: {}, discarding changes", path, data, e);
+            LOG.warn("{}: Error putting data to {}, data: {}, discarding changes", id, path, data, e);
             discardChanges();
-            throw new RuntimeException("Error while replacing " + path, e);
+            throw new RuntimeException(id + ": Error while replacing " + path, e);
         }
     }
 
+    private void checkNotFinished() {
+        Preconditions.checkState(isFinished() == false, "%s: Transaction %s already finished", id, getIdentifier());
+    }
+
     @Override
     public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
-        Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can merge only configuration, not %s", store);
+        checkNotFinished();
+        Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "%s: Can merge only configuration, not %s", id, store);
 
         try {
-            final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path);
+            final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path, id);
             final CompositeNode legacyData = normalizer.toLegacy(path, data);
             sendEditRpc(
                     createEditConfigStructure(legacyPath, Optional.<ModifyAction> absent(), Optional.fromNullable(legacyData)), Optional.<ModifyAction> absent());
         } catch (final ExecutionException e) {
-            LOG.warn("Error merging data to {}, data: {}, discarding changes", path, data, e);
+            LOG.warn("{}: Error merging data to {}, data: {}, discarding changes", id, path, data, e);
             discardChanges();
-            throw new RuntimeException("Error while merging " + path, e);
+            throw new RuntimeException(id + ": Error while merging " + path, e);
         }
     }
 
     @Override
     public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-        Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can merge only configuration, not %s", store);
+        checkNotFinished();
+        Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "%s: Can merge only configuration, not %s", id, store);
 
         try {
-            sendEditRpc(createEditConfigStructure(NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path), Optional.of(ModifyAction.DELETE), Optional.<CompositeNode>absent()), Optional.of(ModifyAction.NONE));
+            sendEditRpc(
+                    createEditConfigStructure(NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path, id), Optional.of(ModifyAction.DELETE), Optional.<CompositeNode>absent()), Optional.of(ModifyAction.NONE));
         } catch (final ExecutionException e) {
-            LOG.warn("Error deleting data {}, discarding changes", path, e);
+            LOG.warn("{}: Error deleting data {}, discarding changes", id, path, e);
             discardChanges();
-            throw new RuntimeException("Error while deleting " + path, e);
+            throw new RuntimeException(id + ": Error while deleting " + path, e);
         }
     }
 
     @Override
     public CheckedFuture<Void, TransactionCommitFailedException> submit() {
         final ListenableFuture<Void> commmitFutureAsVoid = Futures.transform(commit(), new Function<RpcResult<TransactionStatus>, Void>() {
-            @Nullable
             @Override
-            public Void apply(@Nullable final RpcResult<TransactionStatus> input) {
+            public Void apply(final RpcResult<TransactionStatus> input) {
                 return null;
             }
         });
@@ -162,25 +181,46 @@ public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
 
     @Override
     public ListenableFuture<RpcResult<TransactionStatus>> commit() {
-        // FIXME do not allow commit if closed or failed
+        checkNotFinished();
+        finished.set(true);
 
-        final ListenableFuture<RpcResult<CompositeNode>> rpcResult = rpc.invokeRpc(NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME, getCommitRequest());
-        return Futures.transform(rpcResult, new Function<RpcResult<CompositeNode>, RpcResult<TransactionStatus>>() {
-            @Override
-            public RpcResult<TransactionStatus> apply(@Nullable final RpcResult<CompositeNode> input) {
-                if(input.isSuccessful()) {
-                    return RpcResultBuilder.success(TransactionStatus.COMMITED).build();
-                } else {
-                    final RpcResultBuilder<TransactionStatus> failed = RpcResultBuilder.failed();
-                    for (final RpcError rpcError : input.getErrors()) {
-                        failed.withError(rpcError.getErrorType(), rpcError.getTag(), rpcError.getMessage(), rpcError.getApplicationTag(), rpcError.getInfo(), rpcError.getCause());
+        if(candidateSupported == false) {
+            return Futures.immediateFuture(RpcResultBuilder.success(TransactionStatus.COMMITED).build());
+        }
+
+        final ListenableFuture<RpcResult<CompositeNode>> rpcResult = rpc.invokeRpc(
+                NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME, NetconfMessageTransformUtil.COMMIT_RPC_CONTENT);
+
+        final ListenableFuture<RpcResult<TransactionStatus>> transformed = Futures.transform(rpcResult,
+                new Function<RpcResult<CompositeNode>, RpcResult<TransactionStatus>>() {
+                    @Override
+                    public RpcResult<TransactionStatus> apply(final RpcResult<CompositeNode> input) {
+                        if (input.isSuccessful()) {
+                            return RpcResultBuilder.success(TransactionStatus.COMMITED).build();
+                        } else {
+                            final RpcResultBuilder<TransactionStatus> failed = RpcResultBuilder.failed();
+                            for (final RpcError rpcError : input.getErrors()) {
+                                failed.withError(rpcError.getErrorType(), rpcError.getTag(), rpcError.getMessage(),
+                                        rpcError.getApplicationTag(), rpcError.getInfo(), rpcError.getCause());
+                            }
+                            return failed.build();
+                        }
                     }
-                    return failed.build();
-                }
-            }
-        });
+                });
 
-        // FIXME 732 detect commit failure
+        Futures.addCallback(transformed, this);
+        return transformed;
+    }
+
+    @Override
+    public void onSuccess(final RpcResult<TransactionStatus> result) {
+        LOG.debug("{}: Write successful, transaction: {}", id, getIdentifier());
+    }
+
+    @Override
+    public void onFailure(final Throwable t) {
+        LOG.warn("{}: Write failed, transaction {}, discarding changes", id, getIdentifier(), t);
+        discardChanges();
     }
 
     private void sendEditRpc(final CompositeNode editStructure, final Optional<ModifyAction> defaultOperation) throws ExecutionException {
@@ -200,6 +240,22 @@ public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
         }
     }
 
+    private void sendDiscardChanges() {
+        final ListenableFuture<RpcResult<CompositeNode>> discardFuture = rpc.invokeRpc(NETCONF_DISCARD_CHANGES_QNAME, DISCARD_CHANGES_RPC_CONTENT);
+        Futures.addCallback(discardFuture, new FutureCallback<RpcResult<CompositeNode>>() {
+            @Override
+            public void onSuccess(final RpcResult<CompositeNode> result) {
+                LOG.debug("{}: Discarding transaction: {}", id, getIdentifier());
+            }
+
+            @Override
+            public void onFailure(final Throwable t) {
+                LOG.error("{}: Discarding changes failed, transaction: {}. Device configuration might be corrupted", id, getIdentifier(), t);
+                throw new RuntimeException(id + ": Discarding changes failed, transaction " + getIdentifier(), t);
+            }
+        });
+    }
+
     private CompositeNode createEditConfigStructure(final YangInstanceIdentifier dataPath, final Optional<ModifyAction> operation,
                                                     final Optional<CompositeNode> lastChildOverride) {
         Preconditions.checkArgument(Iterables.isEmpty(dataPath.getPathArguments()) == false, "Instance identifier with empty path %s", dataPath);
@@ -298,13 +354,6 @@ public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
         }
     }
 
-    private ImmutableCompositeNode getCommitRequest() {
-        final CompositeNodeBuilder<ImmutableCompositeNode> commitInput = ImmutableCompositeNode.builder();
-        commitInput.setQName(NETCONF_COMMIT_QNAME);
-        return commitInput.toInstance();
-    }
-
-
     @Override
     public Object getIdentifier() {
         return this;
index 80d0f67ac49c72b47d35e6ca094ec4610099c1b1..47ef9039d1ac6f69065b1be2d8bd45b5115422a4 100644 (file)
@@ -70,10 +70,15 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
                 if (NetconfMessageTransformUtil.isDataEditOperation(rpc)) {
                     final DataNodeContainer schemaForEdit = NetconfMessageTransformUtil.createSchemaForEdit(schemaContext.get());
                     w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForEdit, codecProvider);
+                } else if (NetconfMessageTransformUtil.isGetOperation(rpc)) {
+                    final DataNodeContainer schemaForGet = NetconfMessageTransformUtil.createSchemaForGet(schemaContext.get());
+                    w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForGet, codecProvider);
+                } else if (NetconfMessageTransformUtil.isGetConfigOperation(rpc)) {
+                    final DataNodeContainer schemaForGetConfig = NetconfMessageTransformUtil.createSchemaForGetConfig(schemaContext.get());
+                    w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForGetConfig, 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);
+                    final DataNodeContainer schemaForGetConfig = NetconfMessageTransformUtil.createSchemaForRpc(rpc, schemaContext.get());
+                    w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, schemaForGetConfig, codecProvider);
                 }
             } else {
                 w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, codecProvider);
@@ -97,24 +102,23 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
 
     private static RpcResult<CompositeNode> toRpcResult(final NetconfMessage message, final QName rpc, final SchemaContext context) {
         final CompositeNode compositeNode;
-
         if (NetconfMessageTransformUtil.isDataRetrievalOperation(rpc)) {
-
             final Element xmlData = NetconfMessageTransformUtil.getDataSubtree(message.getDocument());
-
             final List<org.opendaylight.yangtools.yang.data.api.Node<?>> dataNodes = XmlDocumentUtils.toDomNodes(xmlData,
                     Optional.of(context.getDataDefinitions()), context);
 
             final CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder();
             it.setQName(NetconfMessageTransformUtil.NETCONF_RPC_REPLY_QNAME);
             it.add(ImmutableCompositeNode.create(NetconfMessageTransformUtil.NETCONF_DATA_QNAME, dataNodes));
-
             compositeNode = it.toInstance();
         } else {
-            // TODO map rpc with schema
-            compositeNode = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
+            final CompositeNode rpcReply = XmlDocumentUtils.rpcReplyToDomNodes(message.getDocument(), rpc, context);
+            if (rpcReply != null) {
+                compositeNode = rpcReply;
+            } else {
+                compositeNode = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
+            }
         }
-
         return RpcResultBuilder.success( compositeNode ).build();
     }
 
index a6924d9d37a3b3e81921c049d1bc1f5b3a5571a2..4f792a0a7169b00c72672d182393bd011ad1ca74 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.util;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
@@ -35,6 +36,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -45,8 +47,7 @@ import org.w3c.dom.Element;
 
 public class NetconfMessageTransformUtil {
 
-    private 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 URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
@@ -66,14 +67,27 @@ public class NetconfMessageTransformUtil {
     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_DISCARD_CHANGES_QNAME = QName.create(NETCONF_QNAME, "discard-changes");
     public static QName NETCONF_TYPE_QNAME = QName.create(NETCONF_QNAME, "type");
     public static QName NETCONF_FILTER_QNAME = QName.create(NETCONF_QNAME, "filter");
     public static QName NETCONF_GET_QNAME = QName.create(NETCONF_QNAME, "get");
     public static QName NETCONF_RPC_QNAME = QName.create(NETCONF_QNAME, "rpc");
+
     public static URI NETCONF_ROLLBACK_ON_ERROR_URI = URI
             .create("urn:ietf:params:netconf:capability:rollback-on-error:1.0");
     public static String ROLLBACK_ON_ERROR_OPTION = "rollback-on-error";
 
+    public static URI NETCONF_CANDIDATE_URI = URI
+            .create("urn:ietf:params:netconf:capability:candidate:1.0");
+
+    // Discard changes message
+    public static final CompositeNode DISCARD_CHANGES_RPC_CONTENT =
+            NodeFactory.createImmutableCompositeNode(NETCONF_DISCARD_CHANGES_QNAME, null, Collections.<Node<?>>emptyList());
+
+    // Commit changes message
+    public static final CompositeNode COMMIT_RPC_CONTENT =
+            NodeFactory.createImmutableCompositeNode(NETCONF_COMMIT_QNAME, null, Collections.<Node<?>>emptyList());
+
     public static Node<?> toFilterStructure(final YangInstanceIdentifier identifier) {
         Node<?> previous = null;
         if (Iterables.isEmpty(identifier.getPathArguments())) {
@@ -213,6 +227,14 @@ public class NetconfMessageTransformUtil {
                         NETCONF_GET_QNAME.getLocalName()));
     }
 
+    public static boolean isGetOperation(final QName rpc) {
+        return NETCONF_URI.equals(rpc.getNamespace()) && rpc.getLocalName().equals(NETCONF_GET_QNAME.getLocalName());
+    }
+
+    public static boolean isGetConfigOperation(final QName rpc) {
+        return NETCONF_URI.equals(rpc.getNamespace()) && rpc.getLocalName().equals(NETCONF_GET_CONFIG_QNAME.getLocalName());
+    }
+
     public static boolean isDataEditOperation(final QName rpc) {
         return NETCONF_URI.equals(rpc.getNamespace())
                 && rpc.getLocalName().equals(NETCONF_EDIT_CONFIG_QNAME.getLocalName());
@@ -243,6 +265,80 @@ public class NetconfMessageTransformUtil {
         return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(editConfigProxy));
     }
 
+    /**
+     * Creates artificial schema node for edit-config rpc. This artificial schema looks like:
+     * <pre>
+     * {@code
+     * rpc
+     *   get
+     *     filter
+     *         // All schema nodes from remote schema
+     *     filter
+     *   get
+     * rpc
+     * }
+     * </pre>
+     *
+     * This makes the translation of rpc get request(especially the config node)
+     * to xml use schema which is crucial for some types of nodes e.g. identity-ref.
+     */
+    public static DataNodeContainer createSchemaForGet(final SchemaContext schemaContext) {
+        final QName filter = QName.create(NETCONF_GET_QNAME, "filter");
+        final QName get = QName.create(NETCONF_GET_QNAME, "get");
+        final NodeContainerProxy configProxy = new NodeContainerProxy(filter, schemaContext.getChildNodes());
+        final NodeContainerProxy editConfigProxy = new NodeContainerProxy(get, Sets.<DataSchemaNode>newHashSet(configProxy));
+        return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(editConfigProxy));
+    }
+
+    /**
+     * Creates artificial schema node for get rpc. This artificial schema looks like:
+     * <pre>
+     * {@code
+     * rpc
+     *   get-config
+     *     filter
+     *         // All schema nodes from remote schema
+     *     filter
+     *   get-config
+     * rpc
+     * }
+     * </pre>
+     *
+     * This makes the translation of rpc get-config request(especially the config node)
+     * to xml use schema which is crucial for some types of nodes e.g. identity-ref.
+     */
+    public static DataNodeContainer createSchemaForGetConfig(final SchemaContext schemaContext) {
+        final QName filter = QName.create(NETCONF_GET_CONFIG_QNAME, "filter");
+        final QName getConfig = QName.create(NETCONF_GET_CONFIG_QNAME, "get-config");
+        final NodeContainerProxy configProxy = new NodeContainerProxy(filter, schemaContext.getChildNodes());
+        final NodeContainerProxy editConfigProxy = new NodeContainerProxy(getConfig, Sets.<DataSchemaNode>newHashSet(configProxy));
+        return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(editConfigProxy));
+    }
+
+    /**
+     * Creates artificial schema node for schema defined rpc. This artificial schema looks like:
+     * <pre>
+     * {@code
+     * rpc
+     *   rpc-name
+     *      // All schema nodes from remote schema
+     *   rpc-name
+     * rpc
+     * }
+     * </pre>
+     *
+     * This makes the translation of schema defined rpc request
+     * to xml use schema which is crucial for some types of nodes e.g. identity-ref.
+     */
+    public static DataNodeContainer createSchemaForRpc(final QName rpcName, final SchemaContext schemaContext) {
+        Preconditions.checkNotNull(rpcName);
+        Preconditions.checkNotNull(schemaContext);
+
+        final NodeContainerProxy rpcBodyProxy = new NodeContainerProxy(rpcName, schemaContext.getChildNodes());
+        return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(rpcBodyProxy));
+
+    }
+
     public static CompositeNodeTOImpl wrap(final QName name, final Node<?> node) {
         if (node != null) {
             return new CompositeNodeTOImpl(name, null, Collections.<Node<?>> singletonList(node));
@@ -269,5 +365,4 @@ public class NetconfMessageTransformUtil {
             return it.toInstance();
         }
     }
-
 }
index 6bad4798c290524dc04ff2d39611f2a1f0c33453..e13398b1dfd36a748bcdeb019db55b30b01c4c04 100644 (file)
@@ -58,6 +58,14 @@ module odl-sal-netconf-connector-cfg {
                 type string;
             }
 
+            container yang-module-capabilities {
+                leaf-list capability {
+                    type string;
+                    description "Set a list of capabilities to override capabilities provided in device's hello message.
+                                 Can be used for devices that do not report any yang modules in their hello message";
+                }
+            }
+
             container dom-registry {
                 uses config:service-ref {
                     refine type {
index 521a55df682340cfacdcf4e11513641ce64c0107..127b0cbfcdd510f569af8b1d71d0e773d9e1f740 100644 (file)
@@ -31,6 +31,7 @@ public class NetconfToNotificationTest {
 
     NetconfMessage userNotification;
 
+    @SuppressWarnings("deprecation")
     @Before
     public void setup() throws Exception {
         final List<InputStream> modelsToParse = Collections.singletonList(getClass().getResourceAsStream("/schemas/user-notification.yang"));
index 18a3b9f0ff65d9055daf13d6f7e70f01653de6ea..e744e11bc9212fc58666654b454a804e1e7f06ce 100644 (file)
@@ -9,7 +9,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
@@ -22,6 +22,8 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.w3c.dom.Document;
+
 
 /**
  * Test case for reported bug 1355
@@ -32,33 +34,195 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
  */
 public class NetconfToRpcRequestTest {
 
-    private String TEST_MODEL_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
-    private String REVISION = "2014-07-14";
-    private QName INPUT_QNAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "input");
-    private QName STREAM_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "stream-name");
-    private QName RPC_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "subscribe");
+    private final static String TEST_MODEL_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
+    private final static String REVISION = "2014-07-14";
+    private final static QName INPUT_QNAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "input");
+    private final static QName STREAM_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "stream-name");
+    private final static QName SUBSCRIBE_RPC_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "subscribe");
+
+    private final static String CONFIG_TEST_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:rpc:config:defs";
+    private final static String CONFIG_TEST_REVISION = "2014-07-21";
+    private final static QName EDIT_CONFIG_QNAME = QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "edit-config");
+    private final static QName GET_QNAME = QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "get");
+    private final static QName GET_CONFIG_QNAME = QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "get-config");
 
-    NetconfMessageTransformer messageTransformer;
+    static SchemaContext notifCtx;
+    static SchemaContext cfgCtx;
+    static NetconfMessageTransformer messageTransformer;
 
     @SuppressWarnings("deprecation")
-    @Before
-    public void setup() throws Exception {
-        final List<InputStream> modelsToParse = Collections
-            .singletonList(getClass().getResourceAsStream("/schemas/rpc-notification-subscription.yang"));
-        final YangContextParser parser = new YangParserImpl();
-        final Set<Module> modules = parser.parseYangModelsFromStreams(modelsToParse);
-        assertTrue(!modules.isEmpty());
-        final SchemaContext schemaContext = parser.resolveSchemaContext(modules);
-        assertNotNull(schemaContext);
+    @BeforeClass
+    public static void setup() throws Exception {
+        List<InputStream> modelsToParse = Collections
+            .singletonList(NetconfToRpcRequestTest.class.getResourceAsStream("/schemas/rpc-notification-subscription.yang"));
+        YangContextParser parser = new YangParserImpl();
+        final Set<Module> notifModules = parser.parseYangModelsFromStreams(modelsToParse);
+        assertTrue(!notifModules.isEmpty());
+
+        notifCtx = parser.resolveSchemaContext(notifModules);
+        assertNotNull(notifCtx);
+
+        modelsToParse = Collections
+            .singletonList(NetconfToRpcRequestTest.class.getResourceAsStream("/schemas/config-test-rpc.yang"));
+        parser = new YangParserImpl();
+        final Set<Module> configModules = parser.parseYangModelsFromStreams(modelsToParse);
+        cfgCtx = parser.resolveSchemaContext(configModules);
+        assertNotNull(cfgCtx);
 
         messageTransformer = new NetconfMessageTransformer();
-        messageTransformer.onGlobalContextUpdated(schemaContext);
     }
 
     @Test
-    public void test() throws Exception {
+    public void testIsDataEditOperation() throws Exception {
+        messageTransformer.onGlobalContextUpdated(cfgCtx);
+
         final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
-        rootBuilder.setQName(RPC_NAME);
+        rootBuilder.setQName(EDIT_CONFIG_QNAME);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "input"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> targetBuilder = ImmutableCompositeNode.builder();
+        targetBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "target"));
+        targetBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "running"), null);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> configBuilder = ImmutableCompositeNode.builder();
+        configBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "config"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlTopBuilder = ImmutableCompositeNode.builder();
+        anyxmlTopBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "top"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlInterfBuilder = ImmutableCompositeNode.builder();
+        anyxmlInterfBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "interface"));
+
+        anyxmlInterfBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "name"), "Ethernet0/0");
+        anyxmlInterfBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "mtu"), "1500");
+
+        anyxmlTopBuilder.add(anyxmlInterfBuilder.toInstance());
+        configBuilder.add(anyxmlTopBuilder.toInstance());
+
+        inputBuilder.add(targetBuilder.toInstance());
+        inputBuilder.add(configBuilder.toInstance());
+
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(EDIT_CONFIG_QNAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node editConfigNode = rpcChild.getFirstChild();
+        assertEquals(editConfigNode.getLocalName(), "edit-config");
+
+        final org.w3c.dom.Node targetNode = editConfigNode.getFirstChild();
+        assertEquals(targetNode.getLocalName(), "target");
+
+        final org.w3c.dom.Node runningNode = targetNode.getFirstChild();
+        assertEquals(runningNode.getLocalName(), "running");
+
+        final org.w3c.dom.Node configNode = targetNode.getNextSibling();
+        assertEquals(configNode.getLocalName(), "config");
+
+        final org.w3c.dom.Node topNode = configNode.getFirstChild();
+        assertEquals(topNode.getLocalName(), "top");
+
+        final org.w3c.dom.Node interfaceNode = topNode.getFirstChild();
+        assertEquals(interfaceNode.getLocalName(), "interface");
+
+        final org.w3c.dom.Node nameNode = interfaceNode.getFirstChild();
+        assertEquals(nameNode.getLocalName(), "name");
+
+        final org.w3c.dom.Node mtuNode = nameNode.getNextSibling();
+        assertEquals(mtuNode.getLocalName(), "mtu");
+    }
+
+    @Test
+    public void testIsGetOperation() throws Exception {
+        messageTransformer.onGlobalContextUpdated(cfgCtx);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(GET_QNAME);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "input"));
+
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(GET_QNAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node get = rpcChild.getFirstChild();
+        assertEquals(get.getLocalName(), "get");
+    }
+
+    @Test
+    public void testIsGetConfigOperation() throws Exception {
+        messageTransformer.onGlobalContextUpdated(cfgCtx);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(GET_CONFIG_QNAME);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "input"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> sourceBuilder = ImmutableCompositeNode.builder();
+        sourceBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "source"));
+        sourceBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "running"), null);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlFilterBuilder = ImmutableCompositeNode.builder();
+        anyxmlFilterBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "filter"));
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> anyxmlTopBuilder = ImmutableCompositeNode.builder();
+        anyxmlTopBuilder.setQName(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "top"));
+        anyxmlTopBuilder.addLeaf(QName.create(CONFIG_TEST_NAMESPACE, CONFIG_TEST_REVISION, "users"), null);
+
+        anyxmlFilterBuilder.add(anyxmlTopBuilder.toInstance());
+
+        inputBuilder.add(sourceBuilder.toInstance());
+        inputBuilder.add(anyxmlFilterBuilder.toInstance());
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(GET_CONFIG_QNAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node getConfig = rpcChild.getFirstChild();
+        assertEquals(getConfig.getLocalName(), "get-config");
+
+        final org.w3c.dom.Node sourceNode = getConfig.getFirstChild();
+        assertEquals(sourceNode.getLocalName(), "source");
+
+        final org.w3c.dom.Node runningNode = sourceNode.getFirstChild();
+        assertEquals(runningNode.getLocalName(), "running");
+
+        final org.w3c.dom.Node filterNode = sourceNode.getNextSibling();
+        assertEquals(filterNode.getLocalName(), "filter");
+
+        final org.w3c.dom.Node topNode = filterNode.getFirstChild();
+        assertEquals(topNode.getLocalName(), "top");
+
+        final org.w3c.dom.Node usersNode = topNode.getFirstChild();
+        assertEquals(usersNode.getLocalName(), "users");
+    }
+
+    @Test
+    public void testUserDefinedRpcCall() throws Exception {
+        messageTransformer.onGlobalContextUpdated(notifCtx);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(SUBSCRIBE_RPC_NAME);
 
         final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
         inputBuilder.setQName(INPUT_QNAME);
@@ -75,7 +239,51 @@ public class NetconfToRpcRequestTest {
         assertNotNull(inputNode);
         assertTrue(inputNode.isEmpty());
 
-        final NetconfMessage message = messageTransformer.toRpcRequest(RPC_NAME, root);
+        final NetconfMessage message = messageTransformer.toRpcRequest(SUBSCRIBE_RPC_NAME, root);
+        assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node subscribeName = rpcChild.getFirstChild();
+        assertEquals(subscribeName.getLocalName(), "subscribe");
+
+        final org.w3c.dom.Node streamName = subscribeName.getFirstChild();
+        assertEquals(streamName.getLocalName(), "stream-name");
+    }
+
+    @Test
+    public void testNoSchemaContextToRpcRequest() throws Exception {
+        final String exampleNamespace = "http://example.net/me/my-own/1.0";
+        final String exampleRevision = "2014-07-22";
+        final QName myOwnMethodRpcQName = QName.create(exampleNamespace, exampleRevision, "my-own-method");
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+        rootBuilder.setQName(myOwnMethodRpcQName);
+
+        final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create(exampleNamespace, exampleRevision, "input"));
+        inputBuilder.addLeaf(QName.create(exampleNamespace, exampleRevision, "my-first-parameter"), "14");
+        inputBuilder.addLeaf(QName.create(exampleNamespace, exampleRevision, "another-parameter"), "fred");
+
+        rootBuilder.add(inputBuilder.toInstance());
+        final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+        final NetconfMessage message = messageTransformer.toRpcRequest(myOwnMethodRpcQName, root);
         assertNotNull(message);
+
+        final Document xmlDoc = message.getDocument();
+        final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
+        assertEquals(rpcChild.getLocalName(), "rpc");
+
+        final org.w3c.dom.Node myOwnMethodNode = rpcChild.getFirstChild();
+        assertEquals(myOwnMethodNode.getLocalName(), "my-own-method");
+
+        final org.w3c.dom.Node firstParamNode = myOwnMethodNode.getFirstChild();
+        assertEquals(firstParamNode.getLocalName(), "my-first-parameter");
+
+        final org.w3c.dom.Node secParamNode = firstParamNode.getNextSibling();
+        assertEquals(secParamNode.getLocalName(), "another-parameter");
     }
 }
index 391bf9c6a42f5302ba05e078041edee50022c6af..001b9a8d3abc411b041d3f3624ea27505722560c 100644 (file)
@@ -8,35 +8,35 @@
 
 package org.opendaylight.controller.sal.connect.netconf.listener;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+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 com.google.common.base.Strings;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.ListenableFuture;
 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;
@@ -56,10 +56,6 @@ 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
@@ -129,9 +125,9 @@ public class NetconfDeviceCommunicatorTest {
         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( "containsModuleCapability", true, actualCapabilites.containsNonModuleCapability(
+                NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString()) );
+        assertEquals( "containsModuleCapability", false, actualCapabilites.containsNonModuleCapability(testCapability) );
         assertEquals( "getModuleBasedCaps", Sets.newHashSet(
                             QName.create( "urn:opendaylight:params:xml:ns:test", "2014-06-02", "test-module" )),
                       actualCapabilites.getModuleBasedCaps() );
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilitiesTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilitiesTest.java
new file mode 100644 (file)
index 0000000..87947b5
--- /dev/null
@@ -0,0 +1,50 @@
+package org.opendaylight.controller.sal.connect.netconf.listener;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class NetconfSessionCapabilitiesTest {
+
+    @Test
+    public void testMerge() throws Exception {
+        final List<String> caps1 = Lists.newArrayList(
+                "namespace:1?module=module1&revision=2012-12-12",
+                "namespace:2?module=module2&amp;revision=2012-12-12",
+                "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&amp;revision=2010-10-04",
+                "urn:ietf:params:netconf:base:1.0",
+                "urn:ietf:params:netconf:capability:rollback-on-error:1.0"
+        );
+        final NetconfSessionCapabilities sessionCaps1 = NetconfSessionCapabilities.fromStrings(caps1);
+        assertCaps(sessionCaps1, 2, 3);
+
+        final List<String> caps2 = Lists.newArrayList(
+                "namespace:3?module=module3&revision=2012-12-12",
+                "namespace:4?module=module4&revision=2012-12-12",
+                "randomNonModuleCap"
+        );
+        final NetconfSessionCapabilities sessionCaps2 = NetconfSessionCapabilities.fromStrings(caps2);
+        assertCaps(sessionCaps2, 1, 2);
+
+        final NetconfSessionCapabilities merged = sessionCaps1.replaceModuleCaps(sessionCaps2);
+        assertCaps(merged, 2, 2 + 1 /*Preserved monitoring*/);
+        for (final QName qName : sessionCaps2.getModuleBasedCaps()) {
+            assertThat(merged.getModuleBasedCaps(), JUnitMatchers.hasItem(qName));
+        }
+        assertThat(merged.getModuleBasedCaps(), JUnitMatchers.hasItem(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING));
+
+        assertThat(merged.getNonModuleCaps(), JUnitMatchers.hasItem("urn:ietf:params:netconf:base:1.0"));
+        assertThat(merged.getNonModuleCaps(), JUnitMatchers.hasItem("urn:ietf:params:netconf:capability:rollback-on-error:1.0"));
+    }
+
+    private void assertCaps(final NetconfSessionCapabilities sessionCaps1, final int nonModuleCaps, final int moduleCaps) {
+        assertEquals(nonModuleCaps, sessionCaps1.getNonModuleCaps().size());
+        assertEquals(moduleCaps, sessionCaps1.getModuleBasedCaps().size());
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java
new file mode 100644 (file)
index 0000000..a65e426
--- /dev/null
@@ -0,0 +1,79 @@
+package org.opendaylight.controller.sal.connect.netconf.sal.tx;
+
+import static junit.framework.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.DISCARD_CHANGES_RPC_CONTENT;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class NetconfDeviceWriteOnlyTxTest {
+
+    private final RemoteDeviceId id = new RemoteDeviceId("test-mount");
+
+    @Mock
+    private RpcImplementation rpc;
+    @Mock
+    private DataNormalizer normalizer;
+    private YangInstanceIdentifier yangIId;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        doReturn(Futures.<RpcResult<CompositeNode>>immediateFailedFuture(new IllegalStateException("Failed tx")))
+        .doReturn(Futures.immediateFuture(RpcResultBuilder.<CompositeNode>success().build()))
+                .when(rpc).invokeRpc(any(QName.class), any(CompositeNode.class));
+
+        yangIId = YangInstanceIdentifier.builder().node(QName.create("namespace", "2012-12-12", "name")).build();
+        doReturn(yangIId).when(normalizer).toLegacy(yangIId);
+    }
+
+    @Test
+    public void testDiscardCahnges() {
+        final NetconfDeviceWriteOnlyTx tx = new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, true, true);
+        final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = tx.submit();
+        try {
+            submitFuture.checkedGet();
+        } catch (final TransactionCommitFailedException e) {
+            // verify discard changes was sent
+            verify(rpc).invokeRpc(NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME, DISCARD_CHANGES_RPC_CONTENT);
+            return;
+        }
+
+        fail("Submit should fail");
+    }
+
+
+    @Test
+    public void testDiscardCahngesNotSentWithoutCandidate() {
+        doReturn(Futures.immediateFuture(RpcResultBuilder.<CompositeNode>success().build()))
+        .doReturn(Futures.<RpcResult<CompositeNode>>immediateFailedFuture(new IllegalStateException("Failed tx")))
+                .when(rpc).invokeRpc(any(QName.class), any(CompositeNode.class));
+
+        final NetconfDeviceWriteOnlyTx tx = new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, false, true);
+        tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId);
+        verify(rpc).invokeRpc(eq(NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME), any(CompositeNode.class));
+        verifyNoMoreInteractions(rpc);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/config-test-rpc.yang b/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/config-test-rpc.yang
new file mode 100644 (file)
index 0000000..f67c2df
--- /dev/null
@@ -0,0 +1,167 @@
+module config-test-rpc {
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:rpc:config:defs";
+    prefix "rpc";
+
+    organization
+    "Cisco Systems, Inc.";
+
+    contact
+    "lsedlak@cisco.com";
+
+    description "Test model containing hacked definition of rpc edit-config and definitions for
+        get and get-config rpc operations.
+        The rpc definition is copied from rfc 6241 Appendix C: http://tools.ietf.org/html/rfc6241#appendix-C";
+
+    revision 2014-07-21 {
+        description "Initial revision.";
+    }
+    
+    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.";
+    }
+    
+    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.";
+                    }
+                }
+            }
+
+            choice edit-content {
+                mandatory true;
+                description "The content for the edit operation.";
+
+                anyxml config {
+                    description
+                      "Inline Config content.";
+                }
+
+                leaf url {
+                    if-feature url;
+                    type string;
+                    description
+                      "URL-based config content.";
+                }
+            }
+        }
+    }
+
+    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.";
+                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 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.";
+              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.";
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/NormalizedNodeVisitor.java
deleted file mode 100644 (file)
index 69b00be..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.opendaylight.controller.cluster.datastore.node.utils;
-
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-public interface NormalizedNodeVisitor {
-    public void visitNode(int level, String parentPath, NormalizedNode normalizedNode);
-}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/NormalizedNodeToNodeCodecTest.java
deleted file mode 100644 (file)
index 4ccbc97..0000000
+++ /dev/null
@@ -1,158 +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.cluster.datastore.node;
-
-import junit.framework.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
-import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeGetter;
-import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
-import org.opendaylight.controller.cluster.datastore.util.TestModel;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Container;
-import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-
-public class NormalizedNodeToNodeCodecTest {
-
-
-
-    private SchemaContext schemaContext;
-
-    @Before
-    public void setUp(){
-        schemaContext = TestModel.createTestContext();
-        assertNotNull("Schema context must not be null.", schemaContext);
-    }
-
-    private YangInstanceIdentifier instanceIdentifierFromString(String s){
-
-        String[] ids = s.split("/");
-
-        List<YangInstanceIdentifier.PathArgument> pathArguments = new ArrayList<>();
-        for(String nodeId : ids){
-            if(!"".equals(nodeId)) {
-                pathArguments.add(NodeIdentifierFactory.getArgument(nodeId));
-            }
-        }
-        final YangInstanceIdentifier instanceIdentifier = YangInstanceIdentifier.create(pathArguments);
-        return instanceIdentifier;
-    }
-
-
-    @Test
-    public void testNormalizeNodeAttributesToProtoBuffNode(){
-        final NormalizedNode<?, ?> documentOne = TestModel.createTestContainer();
-        String id = "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test" +
-            "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)outer-list" +
-            "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)outer-list[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=2}]" +
-            "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id";
-
-        NormalizedNodeGetter normalizedNodeGetter = new NormalizedNodeGetter(id);
-        new NormalizedNodeNavigator(normalizedNodeGetter).navigate(
-            YangInstanceIdentifier.builder().build().toString(), documentOne);
-
-        // Validate the value of id can be retrieved from the normalized node
-        NormalizedNode output = normalizedNodeGetter.getOutput();
-        assertNotNull(output);
-
-
-      NormalizedNodeToNodeCodec codec = new NormalizedNodeToNodeCodec(schemaContext);
-      Container container = codec.encode(instanceIdentifierFromString(id),output);
-
-       assertNotNull(container);
-       assertEquals(id, container.getParentPath()+"/"+container.getNormalizedNode().getPath()) ;
-
-      // Decode the normalized node from the ProtocolBuffer form
-      //first get the node representation of normalized node
-      final Node node = container.getNormalizedNode();
-
-      NormalizedNode<?,?> normalizedNode = codec.decode(instanceIdentifierFromString(id),node);
-
-      assertEquals(normalizedNode.getValue().toString(),output.getValue().toString());
-    }
-
-    @Test
-    public void testThatANormalizedNodeToProtoBuffNodeEncodeDecode() throws Exception {
-        final NormalizedNode<?, ?> documentOne = TestModel.createTestContainer();
-
-        final NormalizedNodeToNodeCodec normalizedNodeToNodeCodec = new NormalizedNodeToNodeCodec(schemaContext);
-
-        Container container = normalizedNodeToNodeCodec.encode(YangInstanceIdentifier.builder().build(), documentOne);
-
-
-        final NormalizedNode<?, ?> decode = normalizedNodeToNodeCodec.decode(instanceIdentifierFromString("/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test"),container.getNormalizedNode());
-        assertNotNull(decode != null);
-
-        //let us ensure that the return decode normalized node encode returns same container
-        Container containerResult =  normalizedNodeToNodeCodec.encode(YangInstanceIdentifier.builder().build(), decode);
-
-        assertEquals(container.getParentPath(),containerResult.getParentPath());
-        assertEquals(container.getNormalizedNode().getChildCount(),container.getNormalizedNode().getChildCount());
-
-        Assert.assertEquals(containerResult.getNormalizedNode().getChildCount(),container.getNormalizedNode().getChildCount());
-
-        //check first level children are proper
-        List<Node>childrenResult = containerResult.getNormalizedNode().getChildList();
-        List<Node>childrenOriginal = container.getNormalizedNode().getChildList();
-
-        System.out.println("-------------------------------------------------");
-
-        System.out.println(childrenOriginal.toString());
-
-        System.out.println("-------------------------------------------------");
-
-        System.out.println(childrenResult.toString());
-
-       boolean bFound;
-        for(Node resultChild: childrenResult){
-           bFound = false;
-          for(Node originalChild:childrenOriginal){
-            if(originalChild.getPath().equals(resultChild.getPath())
-                && resultChild.getType().equals(resultChild.getType())){
-               bFound=true;
-               break;
-            }
-          }
-          Assert.assertTrue(bFound);
-        }
-
-    }
-
-    @Test
-    public void addAugmentations(){
-        String stringId = "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test" +
-            "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)augmented-list" +
-            "/(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)augmented-list[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=1}]";
-
-        YangInstanceIdentifier identifier = instanceIdentifierFromString(stringId);
-
-        MapEntryNode uno = TestModel.createAugmentedListEntry(1, "Uno");
-
-        NormalizedNodeToNodeCodec codec =
-            new NormalizedNodeToNodeCodec(schemaContext);
-
-        Container encode = codec
-            .encode(identifier, uno);
-
-        System.out.println(encode.getNormalizedNode());
-
-        codec.decode(identifier, encode.getNormalizedNode());
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/node/utils/NodeIdentifierFactoryTest.java
deleted file mode 100644 (file)
index 4b0bde8..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.opendaylight.controller.cluster.datastore.node.utils;
-
-import junit.framework.Assert;
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-public class NodeIdentifierFactoryTest {
-
-    @Test
-    public void validateAugmentationIdentifier(){
-        YangInstanceIdentifier.PathArgument argument = NodeIdentifierFactory
-            .getArgument(
-                "AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}");
-
-        Assert.assertTrue(argument instanceof YangInstanceIdentifier.AugmentationIdentifier);
-
-
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtilsTest.java
deleted file mode 100644 (file)
index bb246fb..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.opendaylight.controller.cluster.datastore.util;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-
-public class InstanceIdentifierUtilsTest {
-
-    private static QName TEST_QNAME = QName.create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test");
-    private static QName NODE_WITH_VALUE_QNAME = QName.create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)value");
-    private static QName NODE_WITH_PREDICATES_QNAME = QName.create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)pred");
-    private static QName NAME_QNAME = QName.create("(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)name");
-
-    @Test
-    public void testSerializationOfNodeIdentifier(){
-        YangInstanceIdentifier.PathArgument p1 =
-            new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME);
-
-        List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
-
-        arguments.add(p1);
-
-        YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
-
-        NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
-            InstanceIdentifierUtils.toSerializable(expected);
-
-        YangInstanceIdentifier actual =
-            InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
-
-
-        Assert.assertEquals(expected.getLastPathArgument(),
-            actual.getLastPathArgument());
-
-
-    }
-
-    @Test
-    public void testSerializationOfNodeWithValue(){
-
-        withValue((short) 1);
-        withValue((long) 2);
-        withValue(3);
-        withValue(true);
-
-    }
-
-    private void withValue(Object value){
-        YangInstanceIdentifier.PathArgument p1 =
-            new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME);
-
-        YangInstanceIdentifier.PathArgument p2 =
-            new YangInstanceIdentifier.NodeWithValue(NODE_WITH_VALUE_QNAME, value);
-
-
-        List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
-
-        arguments.add(p1);
-        arguments.add(p2);
-
-        YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
-
-        NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
-            InstanceIdentifierUtils.toSerializable(expected);
-
-        YangInstanceIdentifier actual =
-            InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
-
-
-        Assert.assertEquals(expected.getLastPathArgument(),
-            actual.getLastPathArgument());
-    }
-
-
-    @Test
-    public void testSerializationOfNodeIdentifierWithPredicates(){
-
-        withPredicates((short) 1);
-        withPredicates((long) 2);
-        withPredicates(3);
-        withPredicates(true);
-
-    }
-
-    private void withPredicates(Object value){
-        YangInstanceIdentifier.PathArgument p1 =
-            new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME);
-
-        YangInstanceIdentifier.PathArgument p2 =
-            new YangInstanceIdentifier.NodeIdentifierWithPredicates(NODE_WITH_PREDICATES_QNAME, NAME_QNAME, value);
-
-
-        List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
-
-        arguments.add(p1);
-        arguments.add(p2);
-
-        YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
-
-        NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
-            InstanceIdentifierUtils.toSerializable(expected);
-
-        YangInstanceIdentifier actual =
-            InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
-
-
-        Assert.assertEquals(expected.getLastPathArgument(),
-            actual.getLastPathArgument());
-    }
-
-    @Test
-    public void testAugmentationIdentifier(){
-        YangInstanceIdentifier.PathArgument p1 =
-            new YangInstanceIdentifier.AugmentationIdentifier(new HashSet(Arrays.asList(TEST_QNAME)));
-
-        List<YangInstanceIdentifier.PathArgument> arguments = new ArrayList<>();
-
-        arguments.add(p1);
-
-        YangInstanceIdentifier expected = YangInstanceIdentifier.create(arguments);
-
-        NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
-            InstanceIdentifierUtils.toSerializable(expected);
-
-        YangInstanceIdentifier actual =
-            InstanceIdentifierUtils.fromSerializable(instanceIdentifier);
-
-
-        Assert.assertEquals(expected.getLastPathArgument(),
-            actual.getLastPathArgument());
-
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/NormalizedNodeXmlConverterTest.java
deleted file mode 100644 (file)
index fb28704..0000000
+++ /dev/null
@@ -1,482 +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.cluster.datastore.util;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.custommonkey.xmlunit.Diff;
-import org.custommonkey.xmlunit.XMLUnit;
-import org.junit.Test;
-import org.opendaylight.controller.protobuff.messages.common.SimpleNormalizedNodeMessage;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-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.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer.DomFromNormalizedNodeSerializerFactory;
-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.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
-import java.net.URI;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-
-/**
- * Two of the testcases in the yangtools/yang-data-impl are leveraged (with  modification) to
- * create the serialization of NormalizedNode using the ProtocolBuffer
- *
- * @syedbahm
- *
- */
-
-
-public class NormalizedNodeXmlConverterTest {
-    private static final Logger logger = LoggerFactory
-        .getLogger(NormalizedNodeXmlConverterTest.class);
-    public static final String NAMESPACE =
-        "urn:opendaylight:params:xml:ns:yang:controller:test";
-    private static Date revision;
-    private ContainerNode expectedNode;
-    private ContainerSchemaNode containerNode;
-    private String xmlPath;
-
-    static {
-        try {
-            revision = new SimpleDateFormat("yyyy-MM-dd").parse("2014-03-13");
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static DataSchemaNode getSchemaNode(final SchemaContext context,
-        final String moduleName, final String childNodeName) {
-        for (Module module : context.getModules()) {
-            if (module.getName().equals(moduleName)) {
-                DataSchemaNode found =
-                    findChildNode(module.getChildNodes(), childNodeName);
-                Preconditions.checkState(found != null, "Unable to find %s",
-                    childNodeName);
-                return found;
-            }
-        }
-        throw new IllegalStateException("Unable to find child node "
-            + childNodeName);
-    }
-
-    static DataSchemaNode findChildNode(final Collection<DataSchemaNode> children, final String name) {
-        List<DataNodeContainer> containers = Lists.newArrayList();
-
-        for (DataSchemaNode dataSchemaNode : children) {
-            if (dataSchemaNode.getQName().getLocalName().equals(name)) {
-                return dataSchemaNode;
-            }
-            if (dataSchemaNode instanceof DataNodeContainer) {
-                containers.add((DataNodeContainer) dataSchemaNode);
-            } else if (dataSchemaNode instanceof ChoiceNode) {
-                containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
-            }
-        }
-
-        for (DataNodeContainer container : containers) {
-            DataSchemaNode retVal = findChildNode(container.getChildNodes(), name);
-            if (retVal != null) {
-                return retVal;
-            }
-        }
-
-        return null;
-    }
-
-    public static YangInstanceIdentifier.NodeIdentifier getNodeIdentifier(
-        final String localName) {
-        return new YangInstanceIdentifier.NodeIdentifier(QName.create(
-            URI.create(NAMESPACE), revision, localName));
-    }
-
-    public static YangInstanceIdentifier.AugmentationIdentifier getAugmentIdentifier(
-        final String... childNames) {
-        Set<QName> qn = Sets.newHashSet();
-
-        for (String childName : childNames) {
-            qn.add(getNodeIdentifier(childName).getNodeType());
-        }
-
-        return new YangInstanceIdentifier.AugmentationIdentifier(qn);
-    }
-
-
-    public static ContainerNode augmentChoiceExpectedNode() {
-
-        DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> b =
-            Builders.containerBuilder();
-        b.withNodeIdentifier(getNodeIdentifier("container"));
-
-        b.withChild(Builders
-            .choiceBuilder()
-            .withNodeIdentifier(getNodeIdentifier("ch2"))
-            .withChild(
-                Builders.leafBuilder()
-                    .withNodeIdentifier(getNodeIdentifier("c2Leaf")).withValue("2")
-                    .build())
-            .withChild(
-                Builders
-                    .choiceBuilder()
-                    .withNodeIdentifier(getNodeIdentifier("c2DeepChoice"))
-                    .withChild(
-                        Builders
-                            .leafBuilder()
-                            .withNodeIdentifier(
-                                getNodeIdentifier("c2DeepChoiceCase1Leaf2"))
-                            .withValue("2").build()).build()).build());
-
-        b.withChild(Builders
-            .choiceBuilder()
-            .withNodeIdentifier(getNodeIdentifier("ch3"))
-            .withChild(
-                Builders.leafBuilder()
-                    .withNodeIdentifier(getNodeIdentifier("c3Leaf")).withValue("3")
-                    .build()).build());
-
-        b.withChild(Builders
-            .augmentationBuilder()
-            .withNodeIdentifier(getAugmentIdentifier("augLeaf"))
-            .withChild(
-                Builders.leafBuilder()
-                    .withNodeIdentifier(getNodeIdentifier("augLeaf"))
-                    .withValue("augment").build()).build());
-
-        b.withChild(Builders
-            .augmentationBuilder()
-            .withNodeIdentifier(getAugmentIdentifier("ch"))
-            .withChild(
-                Builders
-                    .choiceBuilder()
-                    .withNodeIdentifier(getNodeIdentifier("ch"))
-                    .withChild(
-                        Builders.leafBuilder()
-                            .withNodeIdentifier(getNodeIdentifier("c1Leaf"))
-                            .withValue("1").build())
-                    .withChild(
-                        Builders
-                            .augmentationBuilder()
-                            .withNodeIdentifier(
-                                getAugmentIdentifier("c1Leaf_AnotherAugment",
-                                    "deepChoice"))
-                            .withChild(
-                                Builders
-                                    .leafBuilder()
-                                    .withNodeIdentifier(
-                                        getNodeIdentifier("c1Leaf_AnotherAugment"))
-                                    .withValue("1").build())
-                            .withChild(
-                                Builders
-                                    .choiceBuilder()
-                                    .withNodeIdentifier(
-                                        getNodeIdentifier("deepChoice"))
-                                    .withChild(
-                                        Builders
-                                            .leafBuilder()
-                                            .withNodeIdentifier(
-                                                getNodeIdentifier("deepLeafc1"))
-                                            .withValue("1").build()).build())
-                            .build()).build()).build());
-
-        return b.build();
-    }
-
-
-
-    public void init(final String yangPath, final String xmlPath, final ContainerNode expectedNode)
-        throws Exception {
-        SchemaContext schema = parseTestSchema(yangPath);
-        this.xmlPath = xmlPath;
-        this.containerNode =
-            (ContainerSchemaNode) getSchemaNode(schema, "test", "container");
-        this.expectedNode = expectedNode;
-    }
-
-    SchemaContext parseTestSchema(final String yangPath) throws Exception {
-
-        YangParserImpl yangParserImpl = new YangParserImpl();
-        InputStream stream =
-            NormalizedNodeXmlConverterTest.class.getResourceAsStream(yangPath);
-        ArrayList<InputStream> al = new ArrayList<InputStream>();
-        al.add(stream);
-        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(al);
-        return yangParserImpl.resolveSchemaContext(modules);
-
-    }
-
-
-    @Test
-    public void testConversionWithAugmentChoice() throws Exception {
-        init("/augment_choice.yang", "/augment_choice.xml",
-            augmentChoiceExpectedNode());
-        Document doc = loadDocument(xmlPath);
-
-        ContainerNode built =
-            DomToNormalizedNodeParserFactory
-                .getInstance(DomUtils.defaultValueCodecProvider())
-                .getContainerNodeParser()
-                .parse(Collections.singletonList(doc.getDocumentElement()),
-                    containerNode);
-
-        if (expectedNode != null) {
-            junit.framework.Assert.assertEquals(expectedNode, built);
-        }
-
-        logger.info("{}", built);
-
-        Iterable<Element> els =
-            DomFromNormalizedNodeSerializerFactory
-                .getInstance(XmlDocumentUtils.getDocument(),
-                    DomUtils.defaultValueCodecProvider())
-                .getContainerNodeSerializer().serialize(containerNode, built);
-
-        Element el = els.iterator().next();
-
-        XMLUnit.setIgnoreWhitespace(true);
-        XMLUnit.setIgnoreComments(true);
-
-        System.out.println(toString(doc.getDocumentElement()));
-        System.out.println(toString(el));
-
-        new Diff(
-            XMLUnit.buildControlDocument(toString(doc.getDocumentElement())),
-            XMLUnit.buildTestDocument(toString(el))).similar();
-    }
-
-    private static ContainerNode listLeafListWithAttributes() {
-        DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> b =
-            Builders.containerBuilder();
-        b.withNodeIdentifier(getNodeIdentifier("container"));
-
-        CollectionNodeBuilder<MapEntryNode, MapNode> listBuilder =
-            Builders.mapBuilder().withNodeIdentifier(getNodeIdentifier("list"));
-
-        Map<QName, Object> predicates = Maps.newHashMap();
-        predicates.put(getNodeIdentifier("uint32InList").getNodeType(), 3L);
-
-        DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> list1Builder =
-            Builders.mapEntryBuilder().withNodeIdentifier(
-                new YangInstanceIdentifier.NodeIdentifierWithPredicates(
-                    getNodeIdentifier("list").getNodeType(), predicates));
-        NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>> uint32InListBuilder =
-            Builders.leafBuilder().withNodeIdentifier(
-                getNodeIdentifier("uint32InList"));
-
-        list1Builder.withChild(uint32InListBuilder.withValue(3L).build());
-
-        listBuilder.withChild(list1Builder.build());
-        b.withChild(listBuilder.build());
-
-        NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>> booleanBuilder =
-            Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("boolean"));
-        booleanBuilder.withValue(false);
-        b.withChild(booleanBuilder.build());
-
-        ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListBuilder =
-            Builders.leafSetBuilder().withNodeIdentifier(
-                getNodeIdentifier("leafList"));
-
-        NormalizedNodeBuilder<YangInstanceIdentifier.NodeWithValue, Object, LeafSetEntryNode<Object>> leafList1Builder =
-            Builders.leafSetEntryBuilder().withNodeIdentifier(
-                new YangInstanceIdentifier.NodeWithValue(getNodeIdentifier("leafList")
-                    .getNodeType(), "a"));
-
-        leafList1Builder.withValue("a");
-
-        leafListBuilder.withChild(leafList1Builder.build());
-        b.withChild(leafListBuilder.build());
-
-        return b.build();
-    }
-
-
-    @Test
-    public void testConversionWithAttributes() throws Exception {
-        init("/test.yang", "/simple_xml_with_attributes.xml",
-            listLeafListWithAttributes());
-        Document doc = loadDocument(xmlPath);
-
-        ContainerNode built =
-            DomToNormalizedNodeParserFactory
-                .getInstance(DomUtils.defaultValueCodecProvider())
-                .getContainerNodeParser()
-                .parse(Collections.singletonList(doc.getDocumentElement()),
-                    containerNode);
-
-        if (expectedNode != null) {
-            junit.framework.Assert.assertEquals(expectedNode, built);
-        }
-
-        logger.info("{}", built);
-
-        Iterable<Element> els =
-            DomFromNormalizedNodeSerializerFactory
-                .getInstance(XmlDocumentUtils.getDocument(),
-                    DomUtils.defaultValueCodecProvider())
-                .getContainerNodeSerializer().serialize(containerNode, built);
-
-        Element el = els.iterator().next();
-
-        XMLUnit.setIgnoreWhitespace(true);
-        XMLUnit.setIgnoreComments(true);
-
-        System.out.println(toString(doc.getDocumentElement()));
-        System.out.println(toString(el));
-
-        new Diff(
-            XMLUnit.buildControlDocument(toString(doc.getDocumentElement())),
-            XMLUnit.buildTestDocument(toString(el))).similar();
-    }
-
-
-    private Document loadDocument(final String xmlPath) throws Exception {
-        InputStream resourceAsStream =
-            NormalizedNodeXmlConverterTest.class.getResourceAsStream(xmlPath);
-
-        Document currentConfigElement = readXmlToDocument(resourceAsStream);
-        Preconditions.checkNotNull(currentConfigElement);
-        return currentConfigElement;
-    }
-
-    private static final DocumentBuilderFactory BUILDERFACTORY;
-
-    static {
-        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-        factory.setNamespaceAware(true);
-        factory.setCoalescing(true);
-        factory.setIgnoringElementContentWhitespace(true);
-        factory.setIgnoringComments(true);
-        BUILDERFACTORY = factory;
-    }
-
-    private Document readXmlToDocument(final InputStream xmlContent)
-        throws IOException, SAXException {
-        DocumentBuilder dBuilder;
-        try {
-            dBuilder = BUILDERFACTORY.newDocumentBuilder();
-        } catch (ParserConfigurationException e) {
-            throw new RuntimeException("Failed to parse XML document", e);
-        }
-        Document doc = dBuilder.parse(xmlContent);
-
-        doc.getDocumentElement().normalize();
-        return doc;
-    }
-
-    public static String toString(final Element xml) {
-        try {
-            Transformer transformer =
-                TransformerFactory.newInstance().newTransformer();
-            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-
-            StreamResult result = new StreamResult(new StringWriter());
-            DOMSource source = new DOMSource(xml);
-            transformer.transform(source, result);
-
-            return result.getWriter().toString();
-        } catch (IllegalArgumentException | TransformerFactoryConfigurationError
-            | TransformerException e) {
-            throw new RuntimeException("Unable to serialize xml element " + xml, e);
-        }
-    }
-
-    @Test
-    public void testConversionToNormalizedXml() throws Exception {
-        SimpleNormalizedNodeMessage.NormalizedNodeXml nnXml =
-            EncoderDecoderUtil.encode(parseTestSchema("/augment_choice.yang"),
-                augmentChoiceExpectedNode());
-        Document expectedDoc = loadDocument("/augment_choice.xml");
-        Document convertedDoc =
-            EncoderDecoderUtil.factory.newDocumentBuilder().parse(
-                new ByteArrayInputStream(nnXml.getXmlString().getBytes("utf-8")));
-        System.out.println(toString(convertedDoc.getDocumentElement()));
-        XMLUnit.setIgnoreWhitespace(true);
-        XMLUnit.setIgnoreComments(true);
-        new Diff(XMLUnit.buildControlDocument(toString(expectedDoc
-            .getDocumentElement())),
-            XMLUnit.buildTestDocument(toString(convertedDoc
-                .getDocumentElement()))).similar();
-        System.out.println(toString(expectedDoc.getDocumentElement()));
-
-    }
-
-
-    @Test
-    public void testConversionFromXmlToNormalizedNode() throws Exception {
-        SimpleNormalizedNodeMessage.NormalizedNodeXml nnXml =
-            EncoderDecoderUtil.encode(parseTestSchema("/test.yang"),
-                listLeafListWithAttributes());
-        Document expectedDoc = loadDocument("/simple_xml_with_attributes.xml");
-        Document convertedDoc =
-            EncoderDecoderUtil.factory.newDocumentBuilder().parse(
-                new ByteArrayInputStream(nnXml.getXmlString().getBytes("utf-8")));
-        System.out.println(toString(convertedDoc.getDocumentElement()));
-        XMLUnit.setIgnoreWhitespace(true);
-        XMLUnit.setIgnoreComments(true);
-        new Diff(XMLUnit.buildControlDocument(toString(expectedDoc
-            .getDocumentElement())),
-            XMLUnit.buildTestDocument(toString(convertedDoc
-                .getDocumentElement()))).similar();
-        System.out.println(toString(expectedDoc.getDocumentElement()));
-
-        // now we will try to convert xml back to normalize node.
-        ContainerNode cn =
-            (ContainerNode) EncoderDecoderUtil.decode(
-                parseTestSchema("/test.yang"), nnXml);
-        junit.framework.Assert.assertEquals(listLeafListWithAttributes(), cn);
-
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/cluster/datastore/util/TestModel.java
deleted file mode 100644 (file)
index bef4057..0000000
+++ /dev/null
@@ -1,486 +0,0 @@
-package org.opendaylight.controller.cluster.datastore.util;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-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.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.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-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.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-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;
-
-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 AUG_NAME_QNAME = QName.create(
-        "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:aug",
-        "2014-03-13", "name");
-
-    public static final QName AUG_CONT_QNAME = QName.create(
-        "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:aug",
-        "2014-03-13", "cont");
-
-
-    public static final QName DESC_QNAME = QName.create(TEST_QNAME, "desc");
-    public static final QName POINTER_QNAME =
-        QName.create(TEST_QNAME, "pointer");
-    public static final QName SOME_REF_QNAME =
-        QName.create(TEST_QNAME, "some-ref");
-    public static final QName MYIDENTITY_QNAME =
-        QName.create(TEST_QNAME, "myidentity");
-    public static final QName SWITCH_FEATURES_QNAME =
-        QName.create(TEST_QNAME, "switch-features");
-
-    public static final QName AUGMENTED_LIST_QNAME =
-        QName.create(TEST_QNAME, "augmented-list");
-
-    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";
-    private static final String DATASTORE_AUG_YANG =
-        "/odl-datastore-augmentation.yang";
-    private static final String DATASTORE_TEST_NOTIFICATION_YANG =
-        "/odl-datastore-test-notification.yang";
-
-
-    public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier
-        .of(TEST_QNAME);
-    public static final YangInstanceIdentifier DESC_PATH = YangInstanceIdentifier
-        .builder(TEST_PATH).node(DESC_QNAME).build();
-    public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier
-        .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");
-
-    private static final Integer ONE_ID = 1;
-    private static final Integer TWO_ID = 2;
-    private static final String TWO_ONE_NAME = "one";
-    private static final String TWO_TWO_NAME = "two";
-    private static final String DESC = "Hello there";
-
-    // Family specific constants
-    public static final QName FAMILY_QNAME =
-        QName
-            .create(
-                "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:notification-test",
-                "2014-04-17", "family");
-    public static final QName CHILDREN_QNAME = QName.create(FAMILY_QNAME,
-        "children");
-    public static final QName GRAND_CHILDREN_QNAME = QName.create(FAMILY_QNAME,
-        "grand-children");
-    public static final QName CHILD_NUMBER_QNAME = QName.create(FAMILY_QNAME,
-        "child-number");
-    public static final QName CHILD_NAME_QNAME = QName.create(FAMILY_QNAME,
-        "child-name");
-    public static final QName GRAND_CHILD_NUMBER_QNAME = QName.create(
-        FAMILY_QNAME, "grand-child-number");
-    public static final QName GRAND_CHILD_NAME_QNAME =
-        QName.create(FAMILY_QNAME,
-            "grand-child-name");
-
-    public static final YangInstanceIdentifier FAMILY_PATH = YangInstanceIdentifier
-        .of(FAMILY_QNAME);
-    public static final YangInstanceIdentifier FAMILY_DESC_PATH = YangInstanceIdentifier
-        .builder(FAMILY_PATH).node(DESC_QNAME).build();
-    public static final YangInstanceIdentifier CHILDREN_PATH = YangInstanceIdentifier
-        .builder(FAMILY_PATH).node(CHILDREN_QNAME).build();
-
-    private static final Integer FIRST_CHILD_ID = 1;
-    private static final Integer SECOND_CHILD_ID = 2;
-
-    private static final String FIRST_CHILD_NAME = "first child";
-    private static final String SECOND_CHILD_NAME = "second child";
-
-    private static final Integer FIRST_GRAND_CHILD_ID = 1;
-    private static final Integer SECOND_GRAND_CHILD_ID = 2;
-
-    private static final String FIRST_GRAND_CHILD_NAME = "first grand child";
-    private static final String SECOND_GRAND_CHILD_NAME = "second grand child";
-
-    // first child
-    private static final YangInstanceIdentifier CHILDREN_1_PATH = YangInstanceIdentifier
-        .builder(CHILDREN_PATH)
-        .nodeWithKey(CHILDREN_QNAME, CHILD_NUMBER_QNAME, FIRST_CHILD_ID) //
-        .build();
-    private static final YangInstanceIdentifier CHILDREN_1_NAME_PATH =
-        YangInstanceIdentifier.builder(CHILDREN_PATH)
-            .nodeWithKey(CHILDREN_QNAME, CHILD_NAME_QNAME, FIRST_CHILD_NAME) //
-            .build();
-
-    private static final YangInstanceIdentifier CHILDREN_2_PATH = YangInstanceIdentifier
-        .builder(CHILDREN_PATH)
-        .nodeWithKey(CHILDREN_QNAME, CHILD_NUMBER_QNAME, SECOND_CHILD_ID) //
-        .build();
-    private static final YangInstanceIdentifier CHILDREN_2_NAME_PATH =
-        YangInstanceIdentifier.builder(CHILDREN_PATH)
-            .nodeWithKey(CHILDREN_QNAME, CHILD_NAME_QNAME, SECOND_CHILD_NAME) //
-            .build();
-
-
-    private static final YangInstanceIdentifier GRAND_CHILD_1_PATH =
-        YangInstanceIdentifier.builder(CHILDREN_1_PATH)
-            .node(GRAND_CHILDREN_QNAME)
-                //
-            .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
-                FIRST_GRAND_CHILD_ID) //
-            .build();
-
-    private static final YangInstanceIdentifier GRAND_CHILD_1_NAME_PATH =
-        YangInstanceIdentifier.builder(CHILDREN_1_PATH)
-            .node(GRAND_CHILDREN_QNAME)
-                //
-            .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NAME_QNAME,
-                FIRST_GRAND_CHILD_NAME) //
-            .build();
-
-    private static final YangInstanceIdentifier GRAND_CHILD_2_PATH =
-        YangInstanceIdentifier.builder(CHILDREN_2_PATH)
-            .node(GRAND_CHILDREN_QNAME)
-                //
-            .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
-                SECOND_GRAND_CHILD_ID) //
-            .build();
-
-    private static final YangInstanceIdentifier GRAND_CHILD_2_NAME_PATH =
-        YangInstanceIdentifier.builder(CHILDREN_2_PATH)
-            .node(GRAND_CHILDREN_QNAME)
-                //
-            .nodeWithKey(GRAND_CHILDREN_QNAME, GRAND_CHILD_NAME_QNAME,
-                SECOND_GRAND_CHILD_NAME) //
-            .build();
-
-    private static final YangInstanceIdentifier DESC_PATH_ID = YangInstanceIdentifier
-        .builder(DESC_PATH).build();
-    private static final YangInstanceIdentifier OUTER_LIST_1_PATH =
-        YangInstanceIdentifier.builder(OUTER_LIST_PATH)
-            .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, ONE_ID) //
-            .build();
-
-    private static final YangInstanceIdentifier OUTER_LIST_2_PATH =
-        YangInstanceIdentifier.builder(OUTER_LIST_PATH)
-            .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
-            .build();
-
-    private static final YangInstanceIdentifier TWO_TWO_PATH = YangInstanceIdentifier
-        .builder(OUTER_LIST_2_PATH).node(INNER_LIST_QNAME) //
-        .nodeWithKey(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME) //
-        .build();
-
-    private static final YangInstanceIdentifier TWO_TWO_VALUE_PATH =
-        YangInstanceIdentifier.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();
-
-    public static final InputStream getDatastoreTestInputStream() {
-        return getInputStream(DATASTORE_TEST_YANG);
-    }
-
-    public static final InputStream getDatastoreAugInputStream() {
-        return getInputStream(DATASTORE_AUG_YANG);
-    }
-
-    public static final InputStream getDatastoreTestNotificationInputStream() {
-        return getInputStream(DATASTORE_TEST_NOTIFICATION_YANG);
-    }
-
-    private static InputStream getInputStream(final String resourceName) {
-        return TestModel.class.getResourceAsStream(resourceName);
-    }
-
-    public static SchemaContext createTestContext() {
-        List<InputStream> inputStreams = new ArrayList<>();
-        inputStreams.add(getDatastoreTestInputStream());
-        inputStreams.add(getDatastoreAugInputStream());
-        inputStreams.add(getDatastoreTestNotificationInputStream());
-
-        YangParserImpl parser = new YangParserImpl();
-        Set<Module> modules = parser.parseYangModelsFromStreams(inputStreams);
-        return parser.resolveSchemaContext(modules);
-    }
-
-    /**
-     * Returns a test document
-     * <p/>
-     * <pre>
-     * test
-     *     outer-list
-     *          id 1
-     *     outer-list
-     *          id 2
-     *          inner-list
-     *                  name "one"
-     *          inner-list
-     *                  name "two"
-     *
-     * </pre>
-     *
-     * @return
-     */
-    public static NormalizedNode<?, ?> createDocumentOne(
-        SchemaContext schemaContext) {
-        return ImmutableContainerNodeBuilder
-            .create()
-            .withNodeIdentifier(
-                new YangInstanceIdentifier.NodeIdentifier(schemaContext.getQName()))
-            .withChild(createTestContainer()).build();
-
-    }
-
-    public static ContainerNode createTestContainer() {
-
-
-        // Create a list of shoes
-        // This is to test leaf list entry
-        final LeafSetEntryNode<Object> nike =
-            ImmutableLeafSetEntryNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    new YangInstanceIdentifier.NodeWithValue(
-                        QName.create(TEST_QNAME,
-                            "shoe"), "nike")
-                ).withValue("nike").build();
-
-        final LeafSetEntryNode<Object> puma =
-            ImmutableLeafSetEntryNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    new YangInstanceIdentifier.NodeWithValue(
-                        QName.create(TEST_QNAME,
-                            "shoe"), "puma")
-                ).withValue("puma").build();
-
-        final LeafSetNode<Object> shoes =
-            ImmutableLeafSetNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    new YangInstanceIdentifier.NodeIdentifier(
-                        QName.create(TEST_QNAME,
-                            "shoe"))
-                ).withChild(nike).withChild(puma).build();
-
-
-        // Test a leaf-list where each entry contains an identity
-        final LeafSetEntryNode<Object> cap1 =
-            ImmutableLeafSetEntryNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    new YangInstanceIdentifier.NodeWithValue(
-                        QName.create(TEST_QNAME,
-                            "capability"), DESC_QNAME)
-                ).withValue(DESC_QNAME).build();
-
-        final LeafSetNode<Object> capabilities =
-            ImmutableLeafSetNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    new YangInstanceIdentifier.NodeIdentifier(
-                        QName.create(TEST_QNAME,
-                            "capability"))
-                ).withChild(cap1).build();
-
-        ContainerNode switchFeatures = ImmutableContainerNodeBuilder
-            .create()
-            .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(
-                SWITCH_FEATURES_QNAME))
-            .withChild(capabilities)
-            .build();
-
-        // Create a leaf list with numbers
-        final LeafSetEntryNode<Object> five =
-            ImmutableLeafSetEntryNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    (new YangInstanceIdentifier.NodeWithValue(
-                        QName.create(TEST_QNAME,
-                            "number"), 5))
-                ).withValue(5).build();
-        final LeafSetEntryNode<Object> fifteen =
-            ImmutableLeafSetEntryNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    (new YangInstanceIdentifier.NodeWithValue(
-                        QName.create(TEST_QNAME,
-                            "number"), 15))
-                ).withValue(15).build();
-        final LeafSetNode<Object> numbers =
-            ImmutableLeafSetNodeBuilder
-                .create()
-                .withNodeIdentifier(
-                    new YangInstanceIdentifier.NodeIdentifier(
-                        QName.create(TEST_QNAME,
-                            "number"))
-                ).withChild(five).withChild(fifteen).build();
-
-
-        // Create augmentations
-        MapEntryNode mapEntry = createAugmentedListEntry(1, "First Test");
-
-
-        // Create the document
-        return ImmutableContainerNodeBuilder
-            .create()
-            .withNodeIdentifier(
-                new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME))
-            .withChild(ImmutableNodes.leafNode(DESC_QNAME, DESC))
-            .withChild(ImmutableNodes.leafNode(POINTER_QNAME, "pointer"))
-            .withChild(ImmutableNodes.leafNode(SOME_REF_QNAME,
-                YangInstanceIdentifier.builder().build()))
-            .withChild(ImmutableNodes.leafNode(MYIDENTITY_QNAME, DESC_QNAME))
-
-                //.withChild(augmentationNode)
-            .withChild(shoes)
-            .withChild(numbers)
-            .withChild(switchFeatures)
-            .withChild(mapNodeBuilder(AUGMENTED_LIST_QNAME).withChild(mapEntry).build())
-            .withChild(
-                mapNodeBuilder(OUTER_LIST_QNAME)
-                    .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
-                    .withChild(BAR_NODE).build()
-            ).build();
-
-    }
-
-    public static MapEntryNode createAugmentedListEntry(int id, String name) {
-
-        Set<QName> childAugmentations = new HashSet<>();
-        childAugmentations.add(AUG_CONT_QNAME);
-
-        ContainerNode augCont = ImmutableContainerNodeBuilder
-            .create()
-            .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(AUG_CONT_QNAME))
-            .withChild(ImmutableNodes.leafNode(AUG_NAME_QNAME, name))
-            .build();
-
-
-        final YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier =
-            new YangInstanceIdentifier.AugmentationIdentifier(childAugmentations);
-
-        final AugmentationNode augmentationNode =
-            Builders.augmentationBuilder()
-                .withNodeIdentifier(augmentationIdentifier)
-                .withChild(augCont)
-                .build();
-
-        return ImmutableMapEntryNodeBuilder.create()
-            .withNodeIdentifier(
-                new YangInstanceIdentifier.NodeIdentifierWithPredicates(
-                    AUGMENTED_LIST_QNAME, ID_QNAME, id))
-            .withChild(ImmutableNodes.leafNode(ID_QNAME, id))
-            .withChild(augmentationNode).build();
-    }
-
-
-    public static ContainerNode createFamily() {
-        final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode>
-            familyContainerBuilder =
-            ImmutableContainerNodeBuilder.create().withNodeIdentifier(
-                new YangInstanceIdentifier.NodeIdentifier(FAMILY_QNAME));
-
-        final CollectionNodeBuilder<MapEntryNode, MapNode> childrenBuilder =
-            mapNodeBuilder(CHILDREN_QNAME);
-
-        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode>
-            firstChildBuilder =
-            mapEntryBuilder(CHILDREN_QNAME, CHILD_NUMBER_QNAME, FIRST_CHILD_ID);
-        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode>
-            secondChildBuilder =
-            mapEntryBuilder(CHILDREN_QNAME, CHILD_NUMBER_QNAME,
-                SECOND_CHILD_ID);
-
-        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode>
-            firstGrandChildBuilder =
-            mapEntryBuilder(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
-                FIRST_GRAND_CHILD_ID);
-        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode>
-            secondGrandChildBuilder =
-            mapEntryBuilder(GRAND_CHILDREN_QNAME, GRAND_CHILD_NUMBER_QNAME,
-                SECOND_GRAND_CHILD_ID);
-
-        firstGrandChildBuilder
-            .withChild(
-                ImmutableNodes.leafNode(GRAND_CHILD_NUMBER_QNAME,
-                    FIRST_GRAND_CHILD_ID)
-            ).withChild(
-            ImmutableNodes.leafNode(GRAND_CHILD_NAME_QNAME,
-                FIRST_GRAND_CHILD_NAME)
-        );
-
-        secondGrandChildBuilder.withChild(
-            ImmutableNodes
-                .leafNode(GRAND_CHILD_NUMBER_QNAME, SECOND_GRAND_CHILD_ID)
-        )
-            .withChild(
-                ImmutableNodes.leafNode(GRAND_CHILD_NAME_QNAME,
-                    SECOND_GRAND_CHILD_NAME)
-            );
-
-        firstChildBuilder
-            .withChild(
-                ImmutableNodes.leafNode(CHILD_NUMBER_QNAME, FIRST_CHILD_ID))
-            .withChild(
-                ImmutableNodes.leafNode(CHILD_NAME_QNAME, FIRST_CHILD_NAME))
-            .withChild(
-                mapNodeBuilder(GRAND_CHILDREN_QNAME).withChild(
-                    firstGrandChildBuilder.build()).build()
-            );
-
-
-        secondChildBuilder
-            .withChild(
-                ImmutableNodes.leafNode(CHILD_NUMBER_QNAME, SECOND_CHILD_ID))
-            .withChild(
-                ImmutableNodes.leafNode(CHILD_NAME_QNAME, SECOND_CHILD_NAME))
-            .withChild(
-                mapNodeBuilder(GRAND_CHILDREN_QNAME).withChild(
-                    firstGrandChildBuilder.build()).build()
-            );
-
-        childrenBuilder.withChild(firstChildBuilder.build());
-        childrenBuilder.withChild(secondChildBuilder.build());
-
-        return familyContainerBuilder.withChild(childrenBuilder.build())
-            .build();
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/ShardManagerMessagesTest.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/ShardManagerMessagesTest.java
deleted file mode 100644 (file)
index b0758da..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.opendaylight.controller.protobuff.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.protobuff.messages.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-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/test/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessagesTest.java
deleted file mode 100644 (file)
index 2b1ee56..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.opendaylight.controller.protobuff.messages.transaction;
-
-/**
- * @author: syedbahm
- * Date: 7/7/14
- */
-public class ShardTransactionMessagesTest {
-
-
-}
index ce3bfe9a4c81a65decaf51625c7505c07cafc05e..a2bee8ffee7295c8c086365fafa1651235f4efdc 100644 (file)
       <groupId>com.typesafe.akka</groupId>
       <artifactId>akka-testkit_${scala.version}</artifactId>
     </dependency>
-
+    <dependency>
+      <groupId>com.typesafe.akka</groupId>
+      <artifactId>akka-osgi_${scala.version}</artifactId>
+    </dependency>
     <!-- SAL Dependencies -->
 
     <dependency>
index 9824889b8023d4e31e20d835731c59ef7047c314..2be8ba47b99f9881304f58eeee3dede71497821c 100644 (file)
@@ -2,8 +2,10 @@ package org.opendaylight.controller.config.yang.config.remote_rpc_connector;
 
 import org.opendaylight.controller.remote.rpc.RemoteRpcProviderFactory;
 import org.opendaylight.controller.sal.core.api.Broker;
+import org.osgi.framework.BundleContext;
 
 public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModule {
+  private BundleContext bundleContext;
   public RemoteRPCBrokerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
     super(identifier, dependencyResolver);
   }
@@ -20,6 +22,10 @@ public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.ya
   @Override
   public java.lang.AutoCloseable createInstance() {
     Broker broker = getDomBrokerDependency();
-    return RemoteRpcProviderFactory.createInstance(broker);
+    return RemoteRpcProviderFactory.createInstance(broker, bundleContext);
+  }
+
+  public void setBundleContext(BundleContext bundleContext) {
+    this.bundleContext = bundleContext;
   }
 }
index 330845b14fc28bedbc9268467a2fa5075addc5a4..f97338d32971c277de5f258c15c94102f94120a6 100644 (file)
 package org.opendaylight.controller.config.yang.config.remote_rpc_connector;
 
 
+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 RemoteRPCBrokerModuleFactory extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModuleFactory {
+  @Override
+  public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+    RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName,dependencyResolver,bundleContext);
+    module.setBundleContext(bundleContext);
+    return module;
+  }
 
+  @Override
+  public Module createModule(String instanceName, DependencyResolver dependencyResolver,
+                             DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
+    RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName, dependencyResolver,
+        old, bundleContext);
+    module.setBundleContext(bundleContext);
+    return module;
+  }
 }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorConstants.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorConstants.java
new file mode 100644 (file)
index 0000000..1f1a0f5
--- /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.remote.rpc;
+
+
+public class ActorConstants {
+  public static final String RPC_BROKER = "rpc-broker";
+  public static final String RPC_REGISTRY = "rpc-registry";
+  public static final String RPC_MANAGER = "rpc";
+
+  public static final String RPC_BROKER_PATH= "/user/rpc/rpc-broker";
+  public static final String RPC_REGISTRY_PATH = "/user/rpc/rpc-registry";
+}
index 4a6124a3bc37fbf2a46079dd82df6f1d3ba80283..f1ca3ccd505e1b1732ad906f75f3662368fdc4a2 100644 (file)
@@ -9,25 +9,38 @@
 package org.opendaylight.controller.remote.rpc;
 
 import akka.actor.ActorSystem;
-import akka.actor.Props;
-import com.google.common.base.Function;
+import akka.osgi.BundleDelegatingClassLoader;
 import com.typesafe.config.ConfigFactory;
+import org.osgi.framework.BundleContext;
 
-import javax.annotation.Nullable;
 
 public class ActorSystemFactory {
-    private static final ActorSystem actorSystem = (new Function<Void, ActorSystem>(){
+ private static volatile ActorSystem actorSystem = null;
 
-        @Nullable @Override public ActorSystem apply(@Nullable Void aVoid) {
-                ActorSystem system =
-                    ActorSystem.create("opendaylight-rpc", ConfigFactory
-                        .load().getConfig("odl-cluster"));
-                system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
-                return system;
-        }
-    }).apply(null);
+  public static final ActorSystem getInstance(){
+     return actorSystem;
+  }
 
-    public static final ActorSystem getInstance(){
-        return actorSystem;
+  /**
+   * This method should be called only once during initialization
+   *
+   * @param bundleContext
+   */
+  public static final void createInstance(final BundleContext bundleContext) {
+    if(actorSystem == null) {
+      // Create an OSGi bundle classloader for actor system
+      BundleDelegatingClassLoader classLoader = new BundleDelegatingClassLoader(bundleContext.getBundle(),
+          Thread.currentThread().getContextClassLoader());
+      synchronized (ActorSystemFactory.class) {
+        // Double check
+        if (actorSystem == null) {
+          ActorSystem system = ActorSystem.create("opendaylight-cluster-rpc",
+              ConfigFactory.load().getConfig("odl-cluster-rpc"), classLoader);
+          actorSystem = system;
+        }
+      }
+    } else {
+      throw new IllegalStateException("Actor system should be created only once. Use getInstance method to access existing actor system");
     }
+  }
 }
index 3df572d7c27226511eaa08e096d4477807099f6f..ac50b8fe5b0fcdcbfb9f78ef495308586a4a313c 100644 (file)
@@ -68,7 +68,7 @@ public class RemoteRpcProvider implements AutoCloseable, Provider, SchemaContext
     SchemaService schemaService = brokerSession.getService(SchemaService.class);
     schemaContext = schemaService.getGlobalContext();
 
-    rpcManager = actorSystem.actorOf(RpcManager.props(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry), "rpc");
+    rpcManager = actorSystem.actorOf(RpcManager.props(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry), ActorConstants.RPC_MANAGER);
 
     LOG.debug("Rpc actors are created.");
   }
index 4c40ca177756877f121f0c5187b747241342655c..fc75f7747a0d25361c96f96e77aac30538bb05a5 100644 (file)
@@ -11,9 +11,12 @@ package org.opendaylight.controller.remote.rpc;
 
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.osgi.framework.BundleContext;
 
 public class RemoteRpcProviderFactory {
-    public static RemoteRpcProvider createInstance(final Broker broker){
+    public static RemoteRpcProvider createInstance(final Broker broker, final BundleContext bundleContext){
+
+      ActorSystemFactory.createInstance(bundleContext);
       RemoteRpcProvider rpcProvider =
           new RemoteRpcProvider(ActorSystemFactory.getInstance(), (RpcProvisionRegistry) broker);
       broker.registerProvider(rpcProvider);
index 4925a17c137f12512a598f28240f907216356acc..5c56455bd0c208a40709b4a221fb6a22ed0b65a1 100644 (file)
@@ -72,14 +72,14 @@ public class RpcManager extends AbstractUntypedActor {
   private void createRpcActors() {
     LOG.debug("Create rpc registry and broker actors");
 
-    rpcRegistry = getContext().actorOf(RpcRegistry.props(clusterWrapper), "rpc-registry");
-    rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), "rpc-broker");
+    rpcRegistry = getContext().actorOf(RpcRegistry.props(clusterWrapper), ActorConstants.RPC_REGISTRY);
+    rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), ActorConstants.RPC_BROKER);
   }
 
   private void startListeners() {
     LOG.debug("Registers rpc listeners");
 
-    String rpcBrokerPath = clusterWrapper.getAddress().toString() + "/user/rpc/rpc-broker";
+    String rpcBrokerPath = clusterWrapper.getAddress().toString() + ActorConstants.RPC_BROKER_PATH;
     rpcListener = new RpcListener(rpcRegistry, rpcBrokerPath);
     routeChangeListener = new RoutedRpcListener(rpcRegistry, rpcBrokerPath);
     rpcImplementation = new RemoteRpcImplementation(rpcBroker, schemaContext);
index 7cb505aa98d3d8c81c70cae5bfd5292f4da5ffd2..e36060cc13ece309f04f10adebdb74a62f158146 100644 (file)
@@ -14,6 +14,7 @@ import akka.cluster.ClusterEvent;
 import akka.cluster.Member;
 import akka.japi.Creator;
 import org.opendaylight.controller.remote.rpc.AbstractUntypedActor;
+import org.opendaylight.controller.remote.rpc.ActorConstants;
 import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
 import org.opendaylight.controller.remote.rpc.messages.AddRpc;
 import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
@@ -171,7 +172,7 @@ public class RpcRegistry extends AbstractUntypedActor {
         }
         if(i == index) {
           if(!currentNodeAddress.equals(member.address())) {
-            actor = this.context().actorSelection(member.address() + "/user/rpc-registry");
+            actor = this.context().actorSelection(member.address() + ActorConstants.RPC_REGISTRY_PATH);
             break;
           } else if(index < memberSize-1){ // pick the next element in the set
             index++;
@@ -180,7 +181,7 @@ public class RpcRegistry extends AbstractUntypedActor {
         i++;
       }
       if(actor == null && previousMember != null) {
-        actor = this.context().actorSelection(previousMember.address() + "/user/rpc-registry");
+        actor = this.context().actorSelection(previousMember.address() + ActorConstants.RPC_REGISTRY_PATH);
       }
     }
     return actor;
index 127aa0732b5634bde6de07937ee098e2ba77e97b..b4cca1ab485c3e99373dfd731166c6615e3903d3 100644 (file)
@@ -33,6 +33,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Attr;
@@ -155,7 +156,7 @@ public class XmlDocumentUtils {
     }
 
     final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(schema.getType());
-    if (baseType instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) {
+    if (baseType instanceof InstanceIdentifierType) {
       logger.debug("toSimpleNodeWithType: base type of node is instance identifier, deserializing element", xmlElement);
       value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx);
 
@@ -184,7 +185,8 @@ public class XmlDocumentUtils {
       value = codec.deserialize(text);
     }
 
-    if (schema.getType() instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) {
+    final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(schema.getType());
+    if (baseType instanceof InstanceIdentifierType) {
       logger.debug("toSimpleNodeWithType: base type of node is instance identifier, deserializing element", xmlElement);
       value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx);
     }
index 6088dd0e0ea517c27bd74e79272a92f4b5b7ef1d..daac89c4c8adaef39047034138a8318e639f54c8 100644 (file)
@@ -1,4 +1,43 @@
-odl-cluster{
+
+odl-cluster-data {
+  akka {
+    cluster {
+        roles = [
+          "member-1"
+        ]
+    }
+    actor {
+      provider = "akka.cluster.ClusterActorRefProvider"
+      serializers {
+                java = "akka.serialization.JavaSerializer"
+                proto = "akka.remote.serialization.ProtobufSerializer"
+              }
+
+              serialization-bindings {
+                  "com.google.protobuf.Message" = proto
+
+              }
+    }
+    remote {
+      log-remote-lifecycle-events = off
+      netty.tcp {
+        hostname = "127.0.0.1"
+        port = 2550
+           maximum-frame-size = 2097152
+           send-buffer-size = 52428800
+           receive-buffer-size = 52428800
+      }
+    }
+
+    cluster {
+      seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"]
+
+      auto-down-unreachable-after = 10s
+    }
+  }
+}
+
+odl-cluster-rpc {
   akka {
     actor {
       provider = "akka.cluster.ClusterActorRefProvider"
@@ -7,15 +46,15 @@ odl-cluster{
     remote {
       log-remote-lifecycle-events = off
       netty.tcp {
-        hostname = "192.168.141.141"
+        hostname = "127.0.0.1"
         port = 2551
       }
     }
 
     cluster {
-      seed-nodes = ["akka.tcp://opendaylight-rpc@192.168.141.141:2551"]
+      seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"]
 
       auto-down-unreachable-after = 10s
     }
   }
-}
\ No newline at end of file
+}
index 09fb5b3677538442f154f4ca4a16cbdc4cf05647..e61cafa70b40c83f922460572ee232f5043ed4ea 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-util</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-remote</artifactId>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-core-spi</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-composite-node</artifactId>
+      <version>0.6.2-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 
   <build>
index 582c657868d5d16e0b2213aba36216e59538cb4e..52115a8f32f5ca5c04a5fb0d7c994456cc114544 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.config.yang.md.sal.rest.connector;
 
 import org.opendaylight.controller.sal.rest.impl.RestconfProviderImpl;
 
+
 public class RestConnectorModule extends org.opendaylight.controller.config.yang.md.sal.rest.connector.AbstractRestConnectorModule {
 
     public RestConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@@ -28,3 +29,4 @@ public class RestConnectorModule extends org.opendaylight.controller.config.yang
         return instance;
     }
 }
+
index a6c4ea5ab8d7877930983ed782d4cbc318def278..9c149a21e60e70ff88c0371e936e3844c05b5985 100644 (file)
@@ -23,6 +23,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 
 /**
  * The URI hierarchy for the RESTCONF resources consists of an entry point container, 4 top-level resources, and 1
@@ -30,15 +31,18 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  * <ul>
  * <li><b>/restconf</b> - {@link #getRoot()}
  * <ul>
- * <li><b>/config</b> - {@link #readConfigurationData(String)} {@link #updateConfigurationData(String, CompositeNode)}
- * {@link #createConfigurationData(CompositeNode)} {@link #createConfigurationData(String, CompositeNode)}
+ *      <li><b>/config</b> - {@link #readConfigurationData(String)}
+ *                              {@link #updateConfigurationData(String, CompositeNode)}
+ *                              {@link #createConfigurationData(CompositeNode)}
+ *                              {@link #createConfigurationData(String, CompositeNode)}
  * {@link #deleteConfigurationData(String)}
  * <li><b>/operational</b> - {@link #readOperationalData(String)}
  * <li>/modules - {@link #getModules()}
  * <ul>
  * <li>/module
  * </ul>
- * <li><b>/operations</b> - {@link #invokeRpc(String, CompositeNode)} {@link #invokeRpc(String, CompositeNode)}
+ *      <li><b>/operations</b> - {@link #invokeRpc(String, CompositeNode)}
+ *                               {@link #invokeRpc(String, CompositeNode)}
  * <li>/version (field)
  * </ul>
  * </ul>
@@ -119,19 +123,19 @@ public interface RestconfService {
     @Path("/config/{identifier:.+}")
     @Consumes({ Draft02.MediaTypes.DATA + JSON, Draft02.MediaTypes.DATA + XML, MediaType.APPLICATION_JSON,
             MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-    public Response updateConfigurationData(@Encoded @PathParam("identifier") String identifier, CompositeNode payload);
+    public Response updateConfigurationData(@Encoded @PathParam("identifier") String identifier, Node<?> payload);
 
     @POST
     @Path("/config/{identifier:.+}")
     @Consumes({ Draft02.MediaTypes.DATA + JSON, Draft02.MediaTypes.DATA + XML, MediaType.APPLICATION_JSON,
             MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-    public Response createConfigurationData(@Encoded @PathParam("identifier") String identifier, CompositeNode payload);
+    public Response createConfigurationData(@Encoded @PathParam("identifier") String identifier, Node<?> payload);
 
     @POST
     @Path("/config")
     @Consumes({ Draft02.MediaTypes.DATA + JSON, Draft02.MediaTypes.DATA + XML, MediaType.APPLICATION_JSON,
             MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-    public Response createConfigurationData(CompositeNode payload);
+    public Response createConfigurationData(Node<?> payload);
 
     @DELETE
     @Path("/config/{identifier:.+}")
index 34aa829b6f5a50e7511583485d33693155d123d8..863de10325bab60e59fa5ea578bf5f31f2d0f3a1 100644 (file)
@@ -19,7 +19,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import javax.activation.UnsupportedDataTypeException;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
@@ -52,9 +52,9 @@ import org.slf4j.LoggerFactory;
 
 class JsonMapper {
     private static final Logger LOG = LoggerFactory.getLogger(JsonMapper.class);
-    private final MountInstance mountPoint;
+    private final DOMMountPoint mountPoint;
 
-    public JsonMapper(final MountInstance mountPoint) {
+    public JsonMapper(final DOMMountPoint mountPoint) {
         this.mountPoint = mountPoint;
     }
 
index 2f3499e26968e17e9fa5f662ab66063965657815..caff848180e84400c5a810bfd1939da1e295a22c 100644 (file)
@@ -22,14 +22,14 @@ import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Provider
 @Consumes({ Draft02.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.OPERATION + RestconfService.JSON,
         MediaType.APPLICATION_JSON })
-public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
+public enum JsonToCompositeNodeProvider implements MessageBodyReader<Node<?>> {
     INSTANCE;
 
     private final static Logger LOG = LoggerFactory.getLogger(JsonToCompositeNodeProvider.class);
@@ -41,7 +41,7 @@ public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNo
     }
 
     @Override
-    public CompositeNode readFrom(final Class<CompositeNode> type, final Type genericType,
+    public Node<?> readFrom(final Class<Node<?>> type, final Type genericType,
             final Annotation[] annotations, final MediaType mediaType,
             final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws IOException,
             WebApplicationException {
index adb176a65d5d123dabf6cd4a6404e0358baf249f..2fa99819d5f833a27c0de9d6fa02053e955b87ce 100644 (file)
@@ -9,25 +9,24 @@ package org.opendaylight.controller.sal.rest.impl;
 
 import java.util.Collection;
 import java.util.Collections;
-
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountService;
 import org.opendaylight.controller.sal.rest.api.RestConnector;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 
 public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnector {
 
     public final static String NOT_INITALIZED_MSG = "Restconf is not initialized yet. Please try again later";
 
-    private ListenerRegistration<SchemaServiceListener> listenerRegistration;
+    private ListenerRegistration<SchemaContextListener> listenerRegistration;
     private PortNumber port;
     public void setWebsocketPort(PortNumber port) {
         this.port = port;
@@ -37,15 +36,15 @@ public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnec
 
     @Override
     public void onSessionInitiated(ProviderSession session) {
-        DataBrokerService dataService = session.getService(DataBrokerService.class);
+        final DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class);
 
         BrokerFacade.getInstance().setContext(session);
-        BrokerFacade.getInstance().setDataService(dataService);
+        BrokerFacade.getInstance().setDomDataBroker( domDataBroker);
 
         SchemaService schemaService = session.getService(SchemaService.class);
-        listenerRegistration = schemaService.registerSchemaServiceListener(ControllerContext.getInstance());
+        listenerRegistration = schemaService.registerSchemaContextListener(ControllerContext.getInstance());
         ControllerContext.getInstance().setSchemas(schemaService.getGlobalContext());
-        ControllerContext.getInstance().setMountService(session.getService(MountService.class));
+        ControllerContext.getInstance().setMountService(session.getService(DOMMountPointService.class));
 
         webSocketServerThread = new Thread(WebSocketServer.createInstance(port.getValue().intValue()));
         webSocketServerThread.setName("Web socket server on port " + port);
index 31e9c96462541e75205d9ef9c6aac9508abc6e43..d56a32e36ee084c7180b37e7d444f77fedded580 100644 (file)
@@ -23,25 +23,25 @@ import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Provider
 @Consumes({ Draft02.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.OPERATION + RestconfService.XML,
         MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
+public enum XmlToCompositeNodeProvider implements MessageBodyReader<Node<?>> {
     INSTANCE;
-
     private final static Logger LOG = LoggerFactory.getLogger(XmlToCompositeNodeProvider.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,
+    public Node<?> readFrom(final Class<Node<?>> type, final Type genericType, final Annotation[] annotations,
             MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
             throws IOException, WebApplicationException {
         XmlToCompositeNodeReader xmlReader = new XmlToCompositeNodeReader();
index 413823f52081ebb235cc33db3530e2bdbbf7c149..5944d6003e9e1e33dba8a0b482a60de5f01ac4c0 100644 (file)
@@ -33,10 +33,11 @@ public class XmlToCompositeNodeReader {
     private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
     private XMLEventReader eventReader;
 
-    public CompositeNodeWrapper read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException,
-            IOException {
-        // Get an XML stream which can be marked, and reset, so we can check and
-        // see if there is any content being provided.
+    public Node<?> read(InputStream entityStream) throws XMLStreamException,
+                                                                      UnsupportedFormatException,
+                                                                      IOException {
+        //Get an XML stream which can be marked, and reset, so we can check and see if there is
+        //any content being provided.
         entityStream = getMarkableStream(entityStream);
 
         if (isInputStreamEmpty(entityStream)) {
@@ -52,12 +53,8 @@ public class XmlToCompositeNodeReader {
             }
         }
 
-        if (eventReader.hasNext() && !isCompositeNodeEvent(eventReader.peek())) {
-            throw new UnsupportedFormatException("Root element of XML has to be composite element.");
-        }
-
         final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
-        CompositeNodeWrapper root = null;
+        NodeWrapper<?> root = null;
         NodeWrapper<?> element = null;
         while (eventReader.hasNext()) {
             final XMLEvent event = eventReader.nextEvent();
@@ -70,17 +67,15 @@ public class XmlToCompositeNodeReader {
                 }
                 NodeWrapper<?> newNode = null;
                 if (isCompositeNodeEvent(event)) {
+                    newNode = resolveCompositeNodeFromStartElement(startElement);
                     if (root == null) {
-                        root = resolveCompositeNodeFromStartElement(startElement);
-                        newNode = root;
-                    } else {
-                        newNode = resolveCompositeNodeFromStartElement(startElement);
+                        root = newNode;
                     }
                 } else if (isSimpleNodeEvent(event)) {
+                    newNode = resolveSimpleNodeFromStartElement(startElement);
                     if (root == null) {
-                        throw new UnsupportedFormatException("Root element of XML has to be composite element.");
+                        root = newNode;
                     }
-                    newNode = resolveSimpleNodeFromStartElement(startElement);
                 }
 
                 if (newNode != null) {
@@ -98,7 +93,7 @@ public class XmlToCompositeNodeReader {
             throw new UnsupportedFormatException("XML should contain only one root element");
         }
 
-        return root;
+        return (Node<?>) root;
     }
 
     /**
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToNormalizedNodeReaderWithSchema.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToNormalizedNodeReaderWithSchema.java
new file mode 100644 (file)
index 0000000..935d96c
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.rest.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+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.IdentityValuesDTO;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.RestCodec;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public class XmlToNormalizedNodeReaderWithSchema {
+
+    private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+    private XMLEventReader eventReader;
+    private InstanceIdWithSchemaNode iiWithSchema;
+
+    public XmlToNormalizedNodeReaderWithSchema(final InstanceIdWithSchemaNode iiWithSchema) {
+        this.iiWithSchema = iiWithSchema;
+    }
+
+    public Node<?> read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException, IOException {
+        // Get an XML stream which can be marked, and reset, so we can check and see if there is
+        // any content being provided.
+        entityStream = getMarkableStream(entityStream);
+
+        if (isInputStreamEmpty(entityStream)) {
+            return null;
+        }
+
+        eventReader = xmlInputFactory.createXMLEventReader(entityStream);
+        if (eventReader.hasNext()) {
+            XMLEvent element = eventReader.peek();
+            if (element.isStartDocument()) {
+                eventReader.nextEvent();
+            }
+        }
+
+        final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
+        NodeWrapper<?> root = null;
+        NodeWrapper<?> element = null;
+        Stack<DataSchemaNode> processingQueueSchema = new Stack<>();
+
+        while (eventReader.hasNext()) {
+            final XMLEvent event = eventReader.nextEvent();
+
+            if (event.isStartElement()) {
+                final StartElement startElement = event.asStartElement();
+                CompositeNodeWrapper compParentNode = null;
+                if (!processingQueue.isEmpty() && processingQueue.peek() instanceof CompositeNodeWrapper) {
+                    compParentNode = (CompositeNodeWrapper) processingQueue.peek();
+                    findSchemaNodeForElement(startElement, processingQueueSchema);
+                } else {
+                    processingQueueSchema = checkElementAndSchemaNodeNameAndNamespace(startElement,
+                            iiWithSchema.getSchemaNode());
+                    DataSchemaNode currentSchemaNode = processingQueueSchema.peek();
+                    if (!(currentSchemaNode instanceof ListSchemaNode)
+                            && !(currentSchemaNode instanceof ContainerSchemaNode)) {
+                        throw new UnsupportedFormatException(
+                                "Top level element has to be of type list or container schema node.");
+                    }
+                }
+
+                NodeWrapper<?> newNode = null;
+                if (isCompositeNodeEvent(event)) {
+                    newNode = resolveCompositeNodeFromStartElement(processingQueueSchema.peek().getQName());
+                    if (root == null) {
+                        root = newNode;
+                    }
+                } else if (isSimpleNodeEvent(event)) {
+                    newNode = resolveSimpleNodeFromStartElement(processingQueueSchema.peek(), getValueOf(startElement));
+                    if (root == null) {
+                        root = newNode;
+                    }
+                }
+
+                if (newNode != null) {
+                    processingQueue.push(newNode);
+                    if (compParentNode != null) {
+                        compParentNode.addValue(newNode);
+                    }
+                }
+            } else if (event.isEndElement()) {
+                element = processingQueue.pop();
+//                if(((EndElement)event).getName().getLocalPart().equals
+                processingQueueSchema.pop();
+            }
+        }
+
+        if (!root.getLocalName().equals(element.getLocalName())) {
+            throw new UnsupportedFormatException("XML should contain only one root element");
+        }
+
+        return root.unwrap();
+    }
+
+    private void findSchemaNodeForElement(StartElement element, Stack<DataSchemaNode> processingQueueSchema) {
+        DataSchemaNode currentSchemaNode = processingQueueSchema.peek();
+        if (currentSchemaNode instanceof DataNodeContainer) {
+            final URI realNamespace = getNamespaceFor(element);
+            final String realName = getLocalNameFor(element);
+            Map<URI, DataSchemaNode> childNamesakes = resolveChildsWithNameAsElement(
+                    ((DataNodeContainer) currentSchemaNode), realName);
+            DataSchemaNode childDataSchemaNode = childNamesakes.get(realNamespace);
+            if (childDataSchemaNode == null) {
+                throw new RestconfDocumentedException("Element " + realName + " has namespace " + realNamespace
+                        + ". Available namespaces are: " + childNamesakes.keySet(), ErrorType.APPLICATION,
+                        ErrorTag.INVALID_VALUE);
+            }
+            processingQueueSchema.push(childDataSchemaNode);
+        } else {
+            throw new RestconfDocumentedException("Element " + processingQueueSchema.peek().getQName().getLocalName()
+                    + " should be data node container .", ErrorType.APPLICATION, ErrorTag.INVALID_VALUE);
+        }
+
+    }
+
+    /**
+     * Returns map of data schema node which are accesible by URI which have equal name
+     */
+    private Map<URI, DataSchemaNode> resolveChildsWithNameAsElement(final DataNodeContainer dataNodeContainer,
+            final String realName) {
+        final Map<URI, DataSchemaNode> namespaceToDataSchemaNode = new HashMap<URI, DataSchemaNode>();
+        for (DataSchemaNode dataSchemaNode : dataNodeContainer.getChildNodes()) {
+            if (dataSchemaNode.equals(realName)) {
+                namespaceToDataSchemaNode.put(dataSchemaNode.getQName().getNamespace(), dataSchemaNode);
+            }
+        }
+        return namespaceToDataSchemaNode;
+    }
+
+    private final Stack<DataSchemaNode> checkElementAndSchemaNodeNameAndNamespace(final StartElement startElement,
+            final DataSchemaNode node) {
+        checkArgument(startElement != null, "Start Element cannot be NULL!");
+        final String expectedName = node.getQName().getLocalName();
+        final String xmlName = getLocalNameFor(startElement);
+        final URI expectedNamespace = node.getQName().getNamespace();
+        final URI xmlNamespace = getNamespaceFor(startElement);
+        if (!expectedName.equals(xmlName)) {
+            throw new RestconfDocumentedException("Xml element name: " + xmlName + "\nSchema node name: "
+                    + expectedName, org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType.APPLICATION,
+                    ErrorTag.INVALID_VALUE);
+        }
+
+        if (xmlNamespace != null && !expectedNamespace.equals(xmlNamespace)) {
+            throw new RestconfDocumentedException("Xml element ns: " + xmlNamespace + "\nSchema node ns: "
+                    + expectedNamespace,
+                    org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType.APPLICATION,
+                    ErrorTag.INVALID_VALUE);
+        }
+        Stack<DataSchemaNode> processingQueueSchema = new Stack<>();
+        processingQueueSchema.push(node);
+        return processingQueueSchema;
+    }
+
+    /**
+     * If the input stream is not markable, then it wraps the input stream with a buffered stream, which is mark able.
+     * That way we can check if the stream is empty safely.
+     *
+     * @param entityStream
+     * @return
+     */
+    private InputStream getMarkableStream(InputStream entityStream) {
+        if (!entityStream.markSupported()) {
+            entityStream = new BufferedInputStream(entityStream);
+        }
+        return entityStream;
+    }
+
+    private boolean isInputStreamEmpty(final InputStream entityStream) throws IOException {
+        boolean isEmpty = false;
+        entityStream.mark(1);
+        if (entityStream.read() == -1) {
+            isEmpty = true;
+        }
+        entityStream.reset();
+        return isEmpty;
+    }
+
+    private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
+        checkArgument(event != null, "XML Event cannot be NULL!");
+        if (event.isStartElement()) {
+            XMLEvent innerEvent = skipCommentsAndWhitespace();
+            if (innerEvent != null && (innerEvent.isCharacters() || innerEvent.isEndElement())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
+        checkArgument(event != null, "XML Event cannot be NULL!");
+        if (event.isStartElement()) {
+            XMLEvent innerEvent = skipCommentsAndWhitespace();
+            if (innerEvent != null) {
+                if (innerEvent.isStartElement()) {
+                    return true;
+                }
+            }
+        }
+        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 QName qName) {
+        // checkArgument(startElement != null, "Start Element cannot be NULL!");
+        CompositeNodeWrapper compositeNodeWrapper = new CompositeNodeWrapper("dummy");
+        compositeNodeWrapper.setQname(qName);
+        return compositeNodeWrapper;
+
+    }
+
+    private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final DataSchemaNode node, final String value)
+            throws XMLStreamException {
+        // checkArgument(startElement != null, "Start Element cannot be NULL!");
+        Object deserializedValue = null;
+
+        if (node instanceof LeafSchemaNode) {
+            TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(((LeafSchemaNode) node).getType());
+            deserializedValue = RestCodec.from(baseType, iiWithSchema.getMountPoint()).deserialize(value);
+        } else if (node instanceof LeafListSchemaNode) {
+            TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(((LeafListSchemaNode) node).getType());
+            deserializedValue = RestCodec.from(baseType, iiWithSchema.getMountPoint()).deserialize(value);
+        }
+        // String data;
+        // if (data == null) {
+        // return new EmptyNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
+        // }
+        SimpleNodeWrapper simpleNodeWrapper = new SimpleNodeWrapper("dummy", deserializedValue);
+        simpleNodeWrapper.setQname(node.getQName());
+        return simpleNodeWrapper;
+    }
+
+    private String getValueOf(final StartElement startElement) throws XMLStreamException {
+        String data = null;
+        if (eventReader.hasNext()) {
+            final XMLEvent innerEvent = eventReader.peek();
+            if (innerEvent.isCharacters()) {
+                final Characters chars = innerEvent.asCharacters();
+                if (!chars.isWhiteSpace()) {
+                    data = innerEvent.asCharacters().getData();
+                    data = data + getAdditionalData(eventReader.nextEvent());
+                }
+            } else if (innerEvent.isEndElement()) {
+                if (startElement.getLocation().getCharacterOffset() == innerEvent.getLocation().getCharacterOffset()) {
+                    data = null;
+                } else {
+                    data = "";
+                }
+            }
+        }
+        return data == null ? null : data.trim();
+    }
+
+    private String getAdditionalData(final XMLEvent event) throws XMLStreamException {
+        String data = "";
+        if (eventReader.hasNext()) {
+            final XMLEvent innerEvent = eventReader.peek();
+            if (innerEvent.isCharacters() && !innerEvent.isEndElement()) {
+                final Characters chars = innerEvent.asCharacters();
+                if (!chars.isWhiteSpace()) {
+                    data = innerEvent.asCharacters().getData();
+                    data = data + getAdditionalData(eventReader.nextEvent());
+                }
+            }
+        }
+        return data;
+    }
+
+    private String getLocalNameFor(final StartElement startElement) {
+        return startElement.getName().getLocalPart();
+    }
+
+    private URI getNamespaceFor(final StartElement startElement) {
+        String namespaceURI = startElement.getName().getNamespaceURI();
+        return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
+    }
+
+    private Object resolveValueOfElement(final String value, final StartElement startElement) {
+        // it could be instance-identifier Built-In Type
+        if (value.startsWith("/")) {
+            IdentityValuesDTO iiValue = RestUtil.asInstanceIdentifier(value, new RestUtil.PrefixMapingFromXml(
+                    startElement));
+            if (iiValue != null) {
+                return iiValue;
+            }
+        }
+        // it could be identityref Built-In Type
+        String[] namespaceAndValue = value.split(":");
+        if (namespaceAndValue.length == 2) {
+            String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
+            if (namespace != null && !namespace.isEmpty()) {
+                return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0], value);
+            }
+        }
+        // it is not "prefix:value" but just "value"
+        return value;
+    }
+
+}
index 861aaac3d81552957b5798c3b775501d830fadce..e8701f37e5846e72e9c177ca2188969c7fb9a9da 100644 (file)
@@ -7,38 +7,50 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
-import com.google.common.util.concurrent.Futures;
-
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
 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.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+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.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.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BrokerFacade implements DataReader<YangInstanceIdentifier, CompositeNode> {
+public class BrokerFacade {
     private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class);
 
     private final static BrokerFacade INSTANCE = new BrokerFacade();
-
-    private volatile DataBrokerService dataService;
     private volatile ConsumerSession context;
+    private DOMDataBroker domDataBroker;
 
     private BrokerFacade() {
     }
@@ -47,154 +59,213 @@ public class BrokerFacade implements DataReader<YangInstanceIdentifier, Composit
         this.context = context;
     }
 
-    public void setDataService(final DataBrokerService dataService) {
-        this.dataService = dataService;
-    }
-
     public static BrokerFacade getInstance() {
         return BrokerFacade.INSTANCE;
     }
 
     private void checkPreconditions() {
-        if (context == null || dataService == null) {
+        if (context == null || domDataBroker == null) {
             throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE);
         }
     }
 
-    @Override
-    public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
-        this.checkPreconditions();
-
-        LOG.trace("Read Configuration via Restconf: {}", path);
+    // READ configuration
+    public NormalizedNode<?, ?> readConfigurationData(final YangInstanceIdentifier path) {
+        checkPreconditions();
+        return readDataViaTransaction(domDataBroker.newReadOnlyTransaction(), CONFIGURATION, path);
+    }
 
-        return dataService.readConfigurationData(path);
+    public NormalizedNode<?, ?> readConfigurationData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path) {
+        final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
+        if (domDataBrokerService.isPresent()) {
+            return readDataViaTransaction(domDataBrokerService.get().newReadOnlyTransaction(), CONFIGURATION, path);
+        }
+        throw new RestconfDocumentedException("DOM data broker service isn't available for mount point.");
     }
 
-    public CompositeNode readConfigurationDataBehindMountPoint(final MountInstance mountPoint,
-            final YangInstanceIdentifier path) {
-        this.checkPreconditions();
+    // READ operational
+    public NormalizedNode<?, ?> readOperationalData(final YangInstanceIdentifier path) {
+        checkPreconditions();
+        return readDataViaTransaction(domDataBroker.newReadOnlyTransaction(), OPERATIONAL, path);
+    }
 
-        LOG.trace("Read Configuration via Restconf: {}", path);
+    public NormalizedNode<?, ?> readOperationalData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path) {
+        final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
+        if (domDataBrokerService.isPresent()) {
+            return readDataViaTransaction(domDataBrokerService.get().newReadOnlyTransaction(), OPERATIONAL, path);
+        }
+        throw new RestconfDocumentedException("DOM data broker service isn't available for mount point.");
+    }
 
-        return mountPoint.readConfigurationData(path);
+    // PUT configuration
+    public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataPut(
+            final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload) {
+        checkPreconditions();
+        DataNormalizationOperation<?> rootOp = ControllerContext.getInstance().getRootOperation();
+        return putDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, rootOp);
     }
 
-    @Override
-    public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
-        this.checkPreconditions();
+    public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataPut(
+            final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload) {
+        final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
+        if (domDataBrokerService.isPresent()) {
+            DataNormalizationOperation<?> rootOp = new DataNormalizer(mountPoint.getSchemaContext()).getRootOperation();
+            return putDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path,
+                    payload, rootOp);
+        }
+        throw new RestconfDocumentedException("DOM data broker service isn't available for mount point.");
+    }
 
-        BrokerFacade.LOG.trace("Read Operational via Restconf: {}", path);
+    // POST configuration
+    public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataPost(
+            final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload) {
+        checkPreconditions();
+        DataNormalizationOperation<?> rootOp = ControllerContext.getInstance().getRootOperation();
+        return postDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, rootOp);
+    }
 
-        return dataService.readOperationalData(path);
+    public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataPost(
+            final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload) {
+        final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
+        if (domDataBrokerService.isPresent()) {
+            DataNormalizationOperation<?> rootOp = new DataNormalizer(mountPoint.getSchemaContext()).getRootOperation();
+            return postDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path,
+                    payload, rootOp);
+        }
+        throw new RestconfDocumentedException("DOM data broker service isn't available for mount point.");
     }
 
-    public CompositeNode readOperationalDataBehindMountPoint(final MountInstance mountPoint,
+    // DELETE configuration
+    public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataDelete(
             final YangInstanceIdentifier path) {
-        this.checkPreconditions();
-
-        BrokerFacade.LOG.trace("Read Operational via Restconf: {}", path);
+        checkPreconditions();
+        return deleteDataViaTransaction(domDataBroker.newWriteOnlyTransaction(), CONFIGURATION, path);
+    }
 
-        return mountPoint.readOperationalData(path);
+    public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataDelete(
+            final DOMMountPoint mountPoint, final YangInstanceIdentifier path) {
+        final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
+        if (domDataBrokerService.isPresent()) {
+            return deleteDataViaTransaction(domDataBrokerService.get().newWriteOnlyTransaction(), CONFIGURATION, path);
+        }
+        throw new RestconfDocumentedException("DOM data broker service isn't available for mount point.");
     }
 
+    // RPC
     public Future<RpcResult<CompositeNode>> invokeRpc(final QName type, final CompositeNode payload) {
         this.checkPreconditions();
 
         return context.rpc(type, payload);
     }
 
-    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut(final YangInstanceIdentifier path,
-            final CompositeNode payload) {
+    public void registerToListenDataChanges(final LogicalDatastoreType datastore, final DataChangeScope scope,
+            final ListenerAdapter listener) {
         this.checkPreconditions();
 
-        final DataModificationTransaction transaction = dataService.beginTransaction();
-        BrokerFacade.LOG.trace("Put Configuration via Restconf: {}", path);
-        transaction.putConfigurationData(path, payload);
-        return transaction.commit();
-    }
+        if (listener.isListening()) {
+            return;
+        }
 
-    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPutBehindMountPoint(
-            final MountInstance mountPoint, final YangInstanceIdentifier path, final CompositeNode payload) {
-        this.checkPreconditions();
+        YangInstanceIdentifier path = listener.getPath();
+        final ListenerRegistration<DOMDataChangeListener> registration = domDataBroker.registerDataChangeListener(
+                datastore, path, listener, scope);
 
-        final DataModificationTransaction transaction = mountPoint.beginTransaction();
-        BrokerFacade.LOG.trace("Put Configuration via Restconf: {}", path);
-        transaction.putConfigurationData(path, payload);
-        return transaction.commit();
+        listener.setRegistration(registration);
     }
 
-    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPost(final YangInstanceIdentifier path,
-            final CompositeNode payload) {
-        this.checkPreconditions();
-
-        final DataModificationTransaction transaction = dataService.beginTransaction();
-        /* check for available Node in Configuration DataStore by path */
-        CompositeNode availableNode = transaction.readConfigurationData(path);
-        if (availableNode != null) {
-            String errMsg = "Post Configuration via Restconf was not executed because data already exists";
-            BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
-
-            throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
-                    ErrorTag.DATA_EXISTS);
+    private NormalizedNode<?, ?> readDataViaTransaction(final DOMDataReadTransaction transaction,
+            LogicalDatastoreType datastore, YangInstanceIdentifier path) {
+        LOG.trace("Read " + datastore.name() + " via Restconf: {}", path);
+        final ListenableFuture<Optional<NormalizedNode<?, ?>>> listenableFuture = transaction.read(datastore, path);
+        if (listenableFuture != null) {
+            Optional<NormalizedNode<?, ?>> optional;
+            try {
+                LOG.debug("Reading result data from transaction.");
+                optional = listenableFuture.get();
+            } catch (InterruptedException | ExecutionException e) {
+                throw new RestconfDocumentedException("Problem to get data from transaction.", e.getCause());
+
+            }
+            if (optional != null) {
+                if (optional.isPresent()) {
+                    return optional.get();
+                }
+            }
         }
-        BrokerFacade.LOG.trace("Post Configuration via Restconf: {}", path);
-        transaction.putConfigurationData(path, payload);
-        return transaction.commit();
+        return null;
     }
 
-    public Future<RpcResult<TransactionStatus>> commitConfigurationDataPostBehindMountPoint(
-            final MountInstance mountPoint, final YangInstanceIdentifier path, final CompositeNode payload) {
-        this.checkPreconditions();
-
-        final DataModificationTransaction transaction = mountPoint.beginTransaction();
-        /* check for available Node in Configuration DataStore by path */
-        CompositeNode availableNode = transaction.readConfigurationData(path);
-        if (availableNode != null) {
-            String errMsg = "Post Configuration via Restconf was not executed because data already exists";
-            BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
-
-            throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
-                    ErrorTag.DATA_EXISTS);
+    private CheckedFuture<Void, TransactionCommitFailedException> postDataViaTransaction(
+            final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
+            final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, DataNormalizationOperation<?> root) {
+        ListenableFuture<Optional<NormalizedNode<?, ?>>> futureDatastoreData = rWTransaction.read(datastore, path);
+        try {
+            final Optional<NormalizedNode<?, ?>> optionalDatastoreData = futureDatastoreData.get();
+            if (optionalDatastoreData.isPresent() && payload.equals(optionalDatastoreData.get())) {
+                String errMsg = "Post Configuration via Restconf was not executed because data already exists";
+                LOG.trace(errMsg + ":{}", path);
+                throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
+                        ErrorTag.DATA_EXISTS);
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.trace("It wasn't possible to get data loaded from datastore at path " + path);
         }
-        BrokerFacade.LOG.trace("Post Configuration via Restconf: {}", path);
-        transaction.putConfigurationData(path, payload);
-        return transaction.commit();
-    }
 
-    public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete(final YangInstanceIdentifier path) {
-        this.checkPreconditions();
-        return deleteDataAtTarget(path, dataService.beginTransaction());
+        ensureParentsByMerge(datastore, path, rWTransaction, root);
+        rWTransaction.merge(datastore, path, payload);
+        LOG.trace("Post " + datastore.name() + " via Restconf: {}", path);
+        return rWTransaction.submit();
     }
 
-    public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
-            final MountInstance mountPoint, final YangInstanceIdentifier path) {
-        this.checkPreconditions();
-        return deleteDataAtTarget(path, mountPoint.beginTransaction());
+    private CheckedFuture<Void, TransactionCommitFailedException> putDataViaTransaction(
+            final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore,
+            final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, DataNormalizationOperation<?> root) {
+        LOG.trace("Put " + datastore.name() + " via Restconf: {}", path);
+        ensureParentsByMerge(datastore, path, writeTransaction, root);
+        writeTransaction.put(datastore, path, payload);
+        return writeTransaction.submit();
     }
 
-    private Future<RpcResult<TransactionStatus>> deleteDataAtTarget(final YangInstanceIdentifier path,
-            final DataModificationTransaction transaction) {
-        LOG.info("Delete Configuration via Restconf: {}", path);
-        CompositeNode redDataAtPath = transaction.readConfigurationData(path);
-        if (redDataAtPath == null) {
-            return Futures.immediateFuture(RpcResultBuilder.<TransactionStatus>
-                                                    success(TransactionStatus.COMMITED).build());
-        }
-        transaction.removeConfigurationData(path);
-        return transaction.commit();
+    private CheckedFuture<Void, TransactionCommitFailedException> deleteDataViaTransaction(
+            final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType datastore,
+            YangInstanceIdentifier path) {
+        LOG.info("Delete " + datastore.name() + " via Restconf: {}", path);
+        writeTransaction.delete(datastore, path);
+        return writeTransaction.submit();
     }
 
-    public void registerToListenDataChanges(final ListenerAdapter listener) {
-        this.checkPreconditions();
+    public void setDomDataBroker(DOMDataBroker domDataBroker) {
+        this.domDataBroker = domDataBroker;
+    }
 
-        if (listener.isListening()) {
-            return;
+    private final void ensureParentsByMerge(final LogicalDatastoreType store,
+            final YangInstanceIdentifier normalizedPath, final DOMDataReadWriteTransaction rwTx,
+            final DataNormalizationOperation<?> root) {
+        List<PathArgument> currentArguments = new ArrayList<>();
+        Iterator<PathArgument> iterator = normalizedPath.getPathArguments().iterator();
+        DataNormalizationOperation<?> currentOp = root;
+        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);
+            YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments);
+
+            final Optional<NormalizedNode<?, ?>> datastoreData;
+            try {
+                datastoreData = rwTx.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 (!datastoreData.isPresent() && iterator.hasNext()) {
+                rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
+            }
         }
-
-        YangInstanceIdentifier path = listener.getPath();
-        final ListenerRegistration<DataChangeListener> registration = dataService.registerDataChangeListener(path,
-                listener);
-
-        listener.setRegistration(registration);
     }
 }
index dad7a2cda2ff3f647d58d66fcd6a37dd36b10c62..93e6a2c0e98504e169703423837177078992c2a4 100644 (file)
@@ -9,15 +9,13 @@ 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.HashBiMap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
-
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLDecoder;
@@ -29,24 +27,27 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
-
 import javax.ws.rs.core.Response.Status;
-
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.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.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.impl.RestUtil;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
@@ -83,21 +84,20 @@ public class ControllerContext implements SchemaContextListener {
 
     private static final Splitter SLASH_SPLITTER = Splitter.on('/');
 
-    private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
-
-    private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
-
     private final AtomicReference<Map<QName, RpcDefinition>> qnameToRpc =
             new AtomicReference<>(Collections.<QName, RpcDefinition>emptyMap());
 
     private volatile SchemaContext globalSchema;
-    private volatile MountService mountService;
+    private volatile DOMMountPointService mountService;
+
+    private DataNormalizer dataNormalizer;
 
     public void setGlobalSchema(final SchemaContext globalSchema) {
         this.globalSchema = globalSchema;
+        this.dataNormalizer = new DataNormalizer(globalSchema);
     }
 
-    public void setMountService(final MountService mountService) {
+    public void setMountService(final DOMMountPointService mountService) {
         this.mountService = mountService;
     }
 
@@ -143,7 +143,7 @@ public class ControllerContext implements SchemaContextListener {
         }
 
         InstanceIdentifierBuilder builder = YangInstanceIdentifier.builder();
-        Module latestModule = this.getLatestModule(globalSchema, startModule);
+        Module latestModule = globalSchema.findModuleByName(startModule, null);
         InstanceIdWithSchemaNode iiWithSchemaNode = this.collectPathArguments(builder, pathArgs, latestModule, null,
                 toMountPointIdentifier);
 
@@ -175,59 +175,38 @@ public class ControllerContext implements SchemaContextListener {
 
         return list;
     }
-
-    private Module getLatestModule(final SchemaContext schema, final String moduleName) {
-        Preconditions.checkArgument(schema != null);
-        Preconditions.checkArgument(moduleName != null && !moduleName.isEmpty());
-
-        Predicate<Module> filter = new Predicate<Module>() {
-            @Override
-            public boolean apply(final Module m) {
-                return Objects.equal(m.getName(), moduleName);
-            }
-        };
-
-        Iterable<Module> modules = Iterables.filter(schema.getModules(), filter);
-        return this.filterLatestModule(modules);
-    }
-
-    private Module filterLatestModule(final Iterable<Module> modules) {
-        Module latestModule = modules.iterator().hasNext() ? modules.iterator().next() : null;
-        for (final Module module : modules) {
-            if (module.getRevision().after(latestModule.getRevision())) {
-                latestModule = module;
-            }
-        }
-        return latestModule;
-    }
-
     public Module findModuleByName(final String moduleName) {
         this.checkPreconditions();
         Preconditions.checkArgument(moduleName != null && !moduleName.isEmpty());
-        return this.getLatestModule(globalSchema, moduleName);
+        return globalSchema.findModuleByName(moduleName, null);
     }
 
-    public Module findModuleByName(final MountInstance mountPoint, final String moduleName) {
+    public Module findModuleByName(final DOMMountPoint mountPoint, final String moduleName) {
         Preconditions.checkArgument(moduleName != null && mountPoint != null);
 
         final SchemaContext mountPointSchema = mountPoint.getSchemaContext();
-        return mountPointSchema == null ? null : this.getLatestModule(mountPointSchema, moduleName);
+        if (mountPointSchema == null) {
+            return null;
+        }
+
+        return mountPointSchema.findModuleByName(moduleName, null);
     }
 
     public Module findModuleByNamespace(final URI namespace) {
         this.checkPreconditions();
         Preconditions.checkArgument(namespace != null);
-
-        final Set<Module> moduleSchemas = globalSchema.findModuleByNamespace(namespace);
-        return moduleSchemas == null ? null : this.filterLatestModule(moduleSchemas);
+        return globalSchema.findModuleByNamespaceAndRevision(namespace, null);
     }
 
-    public Module findModuleByNamespace(final MountInstance mountPoint, final URI namespace) {
+    public Module findModuleByNamespace(final DOMMountPoint mountPoint, final URI namespace) {
         Preconditions.checkArgument(namespace != null && mountPoint != null);
 
         final SchemaContext mountPointSchema = mountPoint.getSchemaContext();
-        Set<Module> moduleSchemas = mountPointSchema == null ? null : mountPointSchema.findModuleByNamespace(namespace);
-        return moduleSchemas == null ? null : this.filterLatestModule(moduleSchemas);
+        if (mountPointSchema == null) {
+            return null;
+        }
+
+        return mountPointSchema.findModuleByNamespaceAndRevision(namespace, null);
     }
 
     public Module findModuleByNameAndRevision(final QName module) {
@@ -237,7 +216,7 @@ public class ControllerContext implements SchemaContextListener {
         return globalSchema.findModuleByName(module.getLocalName(), module.getRevision());
     }
 
-    public Module findModuleByNameAndRevision(final MountInstance mountPoint, final QName module) {
+    public Module findModuleByNameAndRevision(final DOMMountPoint mountPoint, final QName module) {
         this.checkPreconditions();
         Preconditions.checkArgument(module != null && module.getLocalName() != null && module.getRevision() != null
                 && mountPoint != null);
@@ -294,42 +273,26 @@ public class ControllerContext implements SchemaContextListener {
     public String findModuleNameByNamespace(final URI namespace) {
         this.checkPreconditions();
 
-        String moduleName = this.uriToModuleName.get(namespace);
-        if (moduleName == null) {
-            final Module module = this.findModuleByNamespace(namespace);
-            if (module != null) {
-                moduleName = module.getName();
-                this.uriToModuleName.put(namespace, moduleName);
-            }
-        }
-
-        return moduleName;
+        final Module module = this.findModuleByNamespace(namespace);
+        return module == null ? null : module.getName();
     }
 
-    public String findModuleNameByNamespace(final MountInstance mountPoint, final URI namespace) {
+    public String findModuleNameByNamespace(final DOMMountPoint mountPoint, final URI namespace) {
         final Module module = this.findModuleByNamespace(mountPoint, namespace);
         return module == null ? null : module.getName();
     }
 
     public URI findNamespaceByModuleName(final String moduleName) {
-        URI namespace = this.moduleNameToUri.get(moduleName);
-        if (namespace == null) {
-            Module module = this.findModuleByName(moduleName);
-            if (module != null) {
-                URI _namespace = module.getNamespace();
-                namespace = _namespace;
-                this.uriToModuleName.put(namespace, moduleName);
-            }
-        }
-        return namespace;
+        final Module module = this.findModuleByName(moduleName);
+        return module == null ? null : module.getNamespace();
     }
 
-    public URI findNamespaceByModuleName(final MountInstance mountPoint, final String moduleName) {
+    public URI findNamespaceByModuleName(final DOMMountPoint mountPoint, final String moduleName) {
         final Module module = this.findModuleByName(mountPoint, moduleName);
         return module == null ? null : module.getNamespace();
     }
 
-    public Set<Module> getAllModules(final MountInstance mountPoint) {
+    public Set<Module> getAllModules(final DOMMountPoint mountPoint) {
         this.checkPreconditions();
 
         SchemaContext schemaContext = mountPoint == null ? null : mountPoint.getSchemaContext();
@@ -341,52 +304,36 @@ public class ControllerContext implements SchemaContextListener {
         return globalSchema.getModules();
     }
 
+    private static final CharSequence toRestconfIdentifier(final SchemaContext context, final QName qname) {
+        final Module schema = context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
+        return schema == null ? null : schema.getName() + ':' + qname.getLocalName();
+    }
+
     public CharSequence toRestconfIdentifier(final QName qname) {
         this.checkPreconditions();
 
-        String module = this.uriToModuleName.get(qname.getNamespace());
-        if (module == null) {
-            final Module moduleSchema = globalSchema.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                    qname.getRevision());
-            if (moduleSchema == null) {
-                return null;
-            }
-
-            this.uriToModuleName.put(qname.getNamespace(), moduleSchema.getName());
-            module = moduleSchema.getName();
-        }
-
-        StringBuilder builder = new StringBuilder();
-        builder.append(module);
-        builder.append(":");
-        builder.append(qname.getLocalName());
-        return builder.toString();
+        return toRestconfIdentifier(globalSchema, qname);
     }
 
-    public CharSequence toRestconfIdentifier(final MountInstance mountPoint, final QName qname) {
+    public CharSequence toRestconfIdentifier(final DOMMountPoint mountPoint, final QName qname) {
         if (mountPoint == null) {
             return null;
         }
 
-        SchemaContext schemaContext = mountPoint.getSchemaContext();
-
-        final Module moduleSchema = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                qname.getRevision());
-        if (moduleSchema == null) {
-            return null;
-        }
-
-        StringBuilder builder = new StringBuilder();
-        builder.append(moduleSchema.getName());
-        builder.append(":");
-        builder.append(qname.getLocalName());
-        return builder.toString();
+        return toRestconfIdentifier(mountPoint.getSchemaContext(), qname);
     }
 
     public Module getRestconfModule() {
         return findModuleByNameAndRevision(Draft02.RestConfModule.IETF_RESTCONF_QNAME);
     }
 
+    private static final Predicate<GroupingDefinition> ERRORS_GROUPING_FILTER = new Predicate<GroupingDefinition>() {
+        @Override
+        public boolean apply(final GroupingDefinition g) {
+            return Draft02.RestConfModule.ERRORS_GROUPING_SCHEMA_NODE.equals(g.getQName().getLocalName());
+        }
+    };
+
     public DataSchemaNode getRestconfModuleErrorsSchemaNode() {
         Module restconfModule = getRestconfModule();
         if (restconfModule == null) {
@@ -395,22 +342,22 @@ public class ControllerContext implements SchemaContextListener {
 
         Set<GroupingDefinition> groupings = restconfModule.getGroupings();
 
-        final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
-            @Override
-            public boolean apply(final GroupingDefinition g) {
-                return Objects.equal(g.getQName().getLocalName(), Draft02.RestConfModule.ERRORS_GROUPING_SCHEMA_NODE);
-            }
-        };
-
-        Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
+        Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, ERRORS_GROUPING_FILTER);
 
         final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
 
-        List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+        List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
                 Draft02.RestConfModule.ERRORS_CONTAINER_SCHEMA_NODE);
         return Iterables.getFirst(instanceDataChildrenByName, null);
     }
 
+    private static final Predicate<GroupingDefinition> GROUPING_FILTER = new Predicate<GroupingDefinition>() {
+        @Override
+        public boolean apply(final GroupingDefinition g) {
+            return Draft02.RestConfModule.RESTCONF_GROUPING_SCHEMA_NODE.equals(g.getQName().getLocalName());
+        }
+    };
+
     public DataSchemaNode getRestconfModuleRestConfSchemaNode(final Module inRestconfModule, final String schemaNodeName) {
         Module restconfModule = inRestconfModule;
         if (restconfModule == null) {
@@ -422,50 +369,41 @@ public class ControllerContext implements SchemaContextListener {
         }
 
         Set<GroupingDefinition> groupings = restconfModule.getGroupings();
-
-        final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
-            @Override
-            public boolean apply(final GroupingDefinition g) {
-                return Objects.equal(g.getQName().getLocalName(), Draft02.RestConfModule.RESTCONF_GROUPING_SCHEMA_NODE);
-            }
-        };
-
-        Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
-
+        Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, GROUPING_FILTER);
         final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
 
-        List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+        List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
                 Draft02.RestConfModule.RESTCONF_CONTAINER_SCHEMA_NODE);
         final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
 
         if (Objects.equal(schemaNodeName, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
             final DataSchemaNode modules = Iterables.getFirst(instances, null);
-            instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+            instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
                     Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
             final DataSchemaNode modules = Iterables.getFirst(instances, null);
-            instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+            instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
                     Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         } else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
-            List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+            List<DataSchemaNode> instances = findInstanceDataChildrenByName(
                     ((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
             return Iterables.getFirst(instances, null);
         }
@@ -508,9 +446,9 @@ public class ControllerContext implements SchemaContextListener {
         DataSchemaNode ret = container.getDataChildByName(name);
         if (ret == null) {
             for (final DataSchemaNode node : container.getChildNodes()) {
-                if ((node instanceof ChoiceCaseNode)) {
-                    final ChoiceCaseNode caseNode = ((ChoiceCaseNode) node);
-                    DataSchemaNode childByQName = ControllerContext.childByQName(caseNode, name);
+                if ((node instanceof ChoiceNode)) {
+                    final ChoiceNode choiceNode = ((ChoiceNode) node);
+                    DataSchemaNode childByQName = ControllerContext.childByQName(choiceNode, name);
                     if (childByQName != null) {
                         return childByQName;
                     }
@@ -525,7 +463,7 @@ public class ControllerContext implements SchemaContextListener {
     }
 
     private InstanceIdWithSchemaNode collectPathArguments(final InstanceIdentifierBuilder builder,
-            final List<String> strings, final DataNodeContainer parentNode, final MountInstance mountPoint,
+            final List<String> strings, final DataNodeContainer parentNode, final DOMMountPoint mountPoint,
             final boolean returnJustMountPoint) {
         Preconditions.<List<String>> checkNotNull(strings);
 
@@ -557,12 +495,13 @@ public class ControllerContext implements SchemaContextListener {
                 }
 
                 final YangInstanceIdentifier partialPath = builder.toInstance();
-                final MountInstance mount = mountService.getMountPoint(partialPath);
-                if (mount == null) {
+                final Optional<DOMMountPoint> mountOpt = mountService.getMountPoint(partialPath);
+                if (!mountOpt.isPresent()) {
                     LOG.debug("Instance identifier to missing mount point: {}", partialPath);
                     throw new RestconfDocumentedException("Mount point does not exist.", ErrorType.PROTOCOL,
                             ErrorTag.UNKNOWN_ELEMENT);
                 }
+                DOMMountPoint mount = mountOpt.get();
 
                 final SchemaContext mountPointSchema = mount.getSchemaContext();
                 if (mountPointSchema == null) {
@@ -587,8 +526,7 @@ public class ControllerContext implements SchemaContextListener {
                             ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
                 }
 
-                final Module moduleBehindMountPoint = this
-                        .getLatestModule(mountPointSchema, moduleNameBehindMountPoint);
+                final Module moduleBehindMountPoint = mountPointSchema.findModuleByName(moduleNameBehindMountPoint, null);
                 if (moduleBehindMountPoint == null) {
                     throw new RestconfDocumentedException("\"" + moduleName
                             + "\" module does not exist in mount point.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
@@ -601,21 +539,25 @@ public class ControllerContext implements SchemaContextListener {
 
             Module module = null;
             if (mountPoint == null) {
-                module = this.getLatestModule(globalSchema, moduleName);
+                module = globalSchema.findModuleByName(moduleName, null);
                 if (module == null) {
                     throw new RestconfDocumentedException("\"" + moduleName + "\" module does not exist.",
                             ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
                 }
             } else {
                 SchemaContext schemaContext = mountPoint.getSchemaContext();
-                module = schemaContext == null ? null : this.getLatestModule(schemaContext, moduleName);
+                if (schemaContext != null) {
+                    module = schemaContext.findModuleByName(moduleName, null);
+                } else {
+                    module = null;
+                }
                 if (module == null) {
                     throw new RestconfDocumentedException("\"" + moduleName
                             + "\" module does not exist in mount point.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
                 }
             }
 
-            targetNode = this.findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
+            targetNode = findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
             if (targetNode == null) {
                 throw new RestconfDocumentedException("URI has bad format. Possible reasons:\n" + " 1. \"" + head
                         + "\" was not found in parent data node.\n" + " 2. \"" + head
@@ -623,7 +565,7 @@ public class ControllerContext implements SchemaContextListener {
                         ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
             }
         } else {
-            final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(parentNode, nodeName);
+            final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(parentNode, nodeName);
             if (potentialSchemaNodes.size() > 1) {
                 final StringBuilder strBuilder = new StringBuilder();
                 for (final DataSchemaNode potentialNodeSchema : potentialSchemaNodes) {
@@ -693,11 +635,11 @@ public class ControllerContext implements SchemaContextListener {
         return new InstanceIdWithSchemaNode(builder.toInstance(), targetNode, mountPoint);
     }
 
-    public DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
+    public static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
             final URI namespace) {
         Preconditions.<URI> checkNotNull(namespace);
 
-        final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(container, name);
+        final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(container, name);
 
         Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
             @Override
@@ -710,16 +652,23 @@ public class ControllerContext implements SchemaContextListener {
         return Iterables.getFirst(result, null);
     }
 
-    public List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
+    public static List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
         Preconditions.<DataNodeContainer> checkNotNull(container);
         Preconditions.<String> checkNotNull(name);
 
         List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<DataSchemaNode>();
-        this.collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
+        collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
         return instantiatedDataNodeContainers;
     }
 
-    private void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
+    private static final Function<ChoiceNode, Set<ChoiceCaseNode>> CHOICE_FUNCTION = new Function<ChoiceNode, Set<ChoiceCaseNode>>() {
+        @Override
+        public Set<ChoiceCaseNode> apply(final ChoiceNode node) {
+            return node.getCases();
+        }
+    };
+
+    private static void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
             final DataNodeContainer container, final String name) {
 
         Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
@@ -734,37 +683,28 @@ public class ControllerContext implements SchemaContextListener {
         // Can't combine this loop with the filter above because the filter is
         // lazily-applied by Iterables.filter.
         for (final DataSchemaNode potentialNode : nodes) {
-            if (this.isInstantiatedDataSchema(potentialNode)) {
+            if (isInstantiatedDataSchema(potentialNode)) {
                 potentialSchemaNodes.add(potentialNode);
             }
         }
 
-        Iterable<ChoiceNode> choiceNodes = Iterables.<ChoiceNode> filter(container.getChildNodes(), ChoiceNode.class);
-
-        final Function<ChoiceNode, Set<ChoiceCaseNode>> choiceFunction = new Function<ChoiceNode, Set<ChoiceCaseNode>>() {
-            @Override
-            public Set<ChoiceCaseNode> apply(final ChoiceNode node) {
-                return node.getCases();
-            }
-        };
-
-        Iterable<Set<ChoiceCaseNode>> map = Iterables.<ChoiceNode, Set<ChoiceCaseNode>> transform(choiceNodes,
-                choiceFunction);
+        Iterable<ChoiceNode> choiceNodes = Iterables.filter(container.getChildNodes(), ChoiceNode.class);
+        Iterable<Set<ChoiceCaseNode>> map = Iterables.transform(choiceNodes, CHOICE_FUNCTION);
 
         final Iterable<ChoiceCaseNode> allCases = Iterables.<ChoiceCaseNode> concat(map);
         for (final ChoiceCaseNode caze : allCases) {
-            this.collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
+            collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
         }
     }
 
-    public boolean isInstantiatedDataSchema(final DataSchemaNode node) {
+    public static boolean isInstantiatedDataSchema(final DataSchemaNode node) {
         return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode
                 || node instanceof ContainerSchemaNode || node instanceof ListSchemaNode
                 || node instanceof AnyXmlSchemaNode;
     }
 
     private void addKeyValue(final HashMap<QName, Object> map, final DataSchemaNode node, final String uriValue,
-            final MountInstance mountPoint) {
+            final DOMMountPoint mountPoint) {
         Preconditions.<String> checkNotNull(uriValue);
         Preconditions.checkArgument((node instanceof LeafSchemaNode));
 
@@ -891,11 +831,7 @@ public class ControllerContext implements SchemaContextListener {
     }
 
     private CharSequence convertToRestconfIdentifier(final NodeIdentifier argument, final ContainerSchemaNode node) {
-        StringBuilder builder = new StringBuilder();
-        builder.append("/");
-        QName nodeType = argument.getNodeType();
-        builder.append(this.toRestconfIdentifier(nodeType));
-        return builder.toString();
+        return "/" + this.toRestconfIdentifier(argument.getNodeType());
     }
 
     private CharSequence convertToRestconfIdentifier(final NodeIdentifierWithPredicates argument,
@@ -905,9 +841,9 @@ public class ControllerContext implements SchemaContextListener {
         final Map<QName, Object> keyValues = argument.getKeyValues();
 
         StringBuilder builder = new StringBuilder();
-        builder.append("/");
+        builder.append('/');
         builder.append(nodeIdentifier);
-        builder.append("/");
+        builder.append('/');
 
         List<QName> keyDefinition = node.getKeyDefinition();
         boolean hasElements = false;
@@ -915,7 +851,7 @@ public class ControllerContext implements SchemaContextListener {
             if (!hasElements) {
                 hasElements = true;
             } else {
-                builder.append("/");
+                builder.append('/');
             }
 
             try {
@@ -947,4 +883,35 @@ public class ControllerContext implements SchemaContextListener {
                     + Arrays.<Object> asList(container, name).toString());
         }
     }
+
+    public Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalized(final YangInstanceIdentifier legacy,
+            final CompositeNode compositeNode) {
+        try {
+            return dataNormalizer.toNormalized(legacy, compositeNode);
+        } catch (NullPointerException e) {
+            throw new RestconfDocumentedException("Data normalizer isn't set. Normalization isn't possible", e);
+        }
+    }
+
+    public YangInstanceIdentifier toNormalized(final YangInstanceIdentifier legacy) {
+        try {
+            return dataNormalizer.toNormalized(legacy);
+        } catch (NullPointerException e) {
+            throw new RestconfDocumentedException("Data normalizer isn't set. Normalization isn't possible", e);
+        }
+    }
+
+    public CompositeNode toLegacy(final YangInstanceIdentifier instanceIdentifier,
+            final NormalizedNode<?,?> normalizedNode) {
+        try {
+            return dataNormalizer.toLegacy(instanceIdentifier, normalizedNode);
+        } catch (NullPointerException e) {
+            throw new RestconfDocumentedException("Data normalizer isn't set. Normalization isn't possible", e);
+        }
+    }
+
+    public DataNormalizationOperation<?> getRootOperation() {
+        return dataNormalizer.getRootOperation();
+    }
+
 }
index 12c1ba66ecc3df3ad2d5c838a1ee916d85a21f5c..b58a6eeaea9393750dfacfc12f0355a5c6662310 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
@@ -15,10 +15,10 @@ public class InstanceIdWithSchemaNode {
 
     private final YangInstanceIdentifier instanceIdentifier;
     private final DataSchemaNode schemaNode;
-    private final MountInstance mountPoint;
+    private final DOMMountPoint mountPoint;
 
     public InstanceIdWithSchemaNode(YangInstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode,
-            MountInstance mountPoint) {
+            DOMMountPoint mountPoint) {
         this.instanceIdentifier = instanceIdentifier;
         this.schemaNode = schemaNode;
         this.mountPoint = mountPoint;
@@ -32,7 +32,7 @@ public class InstanceIdWithSchemaNode {
         return schemaNode;
     }
 
-    public MountInstance getMountPoint() {
+    public DOMMountPoint getMountPoint() {
         return mountPoint;
     }
 
index ff90dd8439582969d8db755c2ae08f4e91129cc5..665fafacc893b7b05235daaa34f8e709d6f2702f 100644 (file)
@@ -12,7 +12,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.sal.rest.impl.RestUtil;
 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.Predicate;
@@ -47,7 +47,7 @@ public class RestCodec {
     }
 
     public static final Codec<Object, Object> from(final TypeDefinition<?> typeDefinition,
-            final MountInstance mountPoint) {
+            final DOMMountPoint mountPoint) {
         return new ObjectCodec(typeDefinition, mountPoint);
     }
 
@@ -62,7 +62,7 @@ public class RestCodec {
 
         private final TypeDefinition<?> type;
 
-        private ObjectCodec(final TypeDefinition<?> typeDefinition, final MountInstance mountPoint) {
+        private ObjectCodec(final TypeDefinition<?> typeDefinition, final DOMMountPoint mountPoint) {
             type = RestUtil.resolveBaseTypeFrom(typeDefinition);
             if (type instanceof IdentityrefTypeDefinition) {
                 identityrefCodec = new IdentityrefCodecImpl(mountPoint);
@@ -158,9 +158,9 @@ public class RestCodec {
 
         private final Logger logger = LoggerFactory.getLogger(IdentityrefCodecImpl.class);
 
-        private final MountInstance mountPoint;
+        private final DOMMountPoint mountPoint;
 
-        public IdentityrefCodecImpl(final MountInstance mountPoint) {
+        public IdentityrefCodecImpl(final DOMMountPoint mountPoint) {
             this.mountPoint = mountPoint;
         }
 
@@ -200,9 +200,9 @@ public class RestCodec {
 
     public static class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec<IdentityValuesDTO> {
         private final Logger logger = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class);
-        private final MountInstance mountPoint;
+        private final DOMMountPoint mountPoint;
 
-        public InstanceIdentifierCodecImpl(final MountInstance mountPoint) {
+        public InstanceIdentifierCodecImpl(final DOMMountPoint mountPoint) {
             this.mountPoint = mountPoint;
         }
 
@@ -244,7 +244,7 @@ public class RestCodec {
             for (int i = 0; i < identities.size(); i++) {
                 IdentityValue identityValue = identities.get(i);
                 URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), mountPoint);
-                DataSchemaNode node = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace(
+                DataSchemaNode node = ControllerContext.findInstanceDataChildByNameAndNamespace(
                         parentContainer, identityValue.getValue(), validNamespace);
                 if (node == null) {
                     logger.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes());
@@ -271,7 +271,7 @@ public class RestCodec {
                         Map<QName, Object> predicatesMap = new HashMap<>();
                         for (Predicate predicate : identityValue.getPredicates()) {
                             validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), mountPoint);
-                            DataSchemaNode listKey = ControllerContext.getInstance()
+                            DataSchemaNode listKey = ControllerContext
                                     .findInstanceDataChildByNameAndNamespace(listNode, predicate.getName().getValue(),
                                             validNamespace);
                             predicatesMap.put(listKey.getQName(), predicate.getValue());
@@ -286,7 +286,7 @@ public class RestCodec {
                 }
                 result.add(pathArgument);
                 if (i < identities.size() - 1) { // last element in instance-identifier can be other than
-                                                 // DataNodeContainer
+                    // DataNodeContainer
                     if (node instanceof DataNodeContainer) {
                         parentContainer = (DataNodeContainer) node;
                     } else {
@@ -318,7 +318,7 @@ public class RestCodec {
         }
     }
 
-    private static Module getModuleByNamespace(final String namespace, final MountInstance mountPoint) {
+    private static Module getModuleByNamespace(final String namespace, final DOMMountPoint mountPoint) {
         URI validNamespace = resolveValidNamespace(namespace, mountPoint);
 
         Module module = null;
@@ -334,7 +334,7 @@ public class RestCodec {
         return module;
     }
 
-    private static URI resolveValidNamespace(final String namespace, final MountInstance mountPoint) {
+    private static URI resolveValidNamespace(final String namespace, final DOMMountPoint mountPoint) {
         URI validNamespace;
         if (mountPoint != null) {
             validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(mountPoint, namespace);
index 4c005c6ae5e9e109604a1890cd5ee0c5f81d264a..73ca02c505f47741ca4e38c071a780a0f32e1cdf 100644 (file)
@@ -15,6 +15,7 @@ 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;
@@ -24,17 +25,20 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.Future;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
+
 import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
@@ -47,16 +51,19 @@ import org.opendaylight.controller.sal.streams.listeners.Notificator;
 import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 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.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
@@ -76,6 +83,8 @@ import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.EmptyType;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class RestconfImpl implements RestconfService {
     private enum UriParameters {
@@ -84,7 +93,7 @@ public class RestconfImpl implements RestconfService {
 
         private String uriParameterName;
 
-        UriParameters(String uriParameterName) {
+        UriParameters(final String uriParameterName) {
             this.uriParameterName = uriParameterName;
         }
 
@@ -96,6 +105,8 @@ public class RestconfImpl implements RestconfService {
 
     private final static RestconfImpl INSTANCE = new RestconfImpl();
 
+    private static final int NOTIFICATION_PORT = 8181;
+
     private static final int CHAR_NOT_FOUND = -1;
 
     private final static String MOUNT_POINT_MODULE_NAME = "ietf-netconf";
@@ -110,6 +121,30 @@ public class RestconfImpl implements RestconfService {
 
     private ControllerContext controllerContext;
 
+    private static final Logger LOG = LoggerFactory.getLogger(RestconfImpl.class);
+
+    private static final DataChangeScope DEFAULT_SCOPE = DataChangeScope.BASE;
+
+    private static final LogicalDatastoreType DEFAULT_DATASTORE = LogicalDatastoreType.CONFIGURATION;
+
+    private static final URI NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT = URI.create("urn:sal:restconf:event:subscription");
+
+    private static final Date EVENT_SUBSCRIPTION_AUGMENT_REVISION;
+
+    private static final String DATASTORE_PARAM_NAME = "datastore";
+
+    private static final String SCOPE_PARAM_NAME = "scope";
+
+    static {
+        try {
+            EVENT_SUBSCRIPTION_AUGMENT_REVISION = new SimpleDateFormat("yyyy-MM-dd").parse("2014-07-08");
+        } catch (ParseException e) {
+            throw new RestconfDocumentedException(
+                    "It wasn't possible to convert revision date of sal-remote-augment to date", ErrorType.APPLICATION,
+                    ErrorTag.OPERATION_FAILED);
+        }
+    }
+
     public void setBroker(final BrokerFacade broker) {
         this.broker = broker;
     }
@@ -168,7 +203,7 @@ public class RestconfImpl implements RestconfService {
     @Override
     public StructuredData getModules(final String identifier, final UriInfo uriInfo) {
         Set<Module> modules = null;
-        MountInstance mountPoint = null;
+        DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
@@ -199,7 +234,7 @@ public class RestconfImpl implements RestconfService {
     public StructuredData getModule(final String identifier, final UriInfo uriInfo) {
         final QName moduleNameAndRevision = this.getModuleNameAndRevision(identifier);
         Module module = null;
-        MountInstance mountPoint = null;
+        DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
@@ -230,7 +265,7 @@ public class RestconfImpl implements RestconfService {
     @Override
     public StructuredData getOperations(final String identifier, final UriInfo uriInfo) {
         Set<Module> modules = null;
-        MountInstance mountPoint = null;
+        DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier);
             mountPoint = mountPointIdentifier.getMountPoint();
@@ -245,7 +280,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
-            final MountInstance mountPoint, boolean prettyPrint) {
+            final DOMMountPoint mountPoint, final boolean prettyPrint) {
         final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
         Module restconfModule = this.getRestconfModule();
         final DataSchemaNode operationsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
@@ -321,31 +356,31 @@ public class RestconfImpl implements RestconfService {
 
     private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
         final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
-        List<DataSchemaNode> instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "name");
         final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues
-                .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
+        .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "description");
         final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
                 "DESCRIPTION_PLACEHOLDER"));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "replay-support");
         final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<Boolean> createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
                 Boolean.valueOf(true)));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
         final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
                 null, ""));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "events");
         final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(eventsSchemaNode.getQName(), null, ""));
@@ -355,26 +390,26 @@ 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(
+        List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "name");
         final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null,
                 module.getName()));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "revision");
         final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         Date _revision = module.getRevision();
         moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
                 REVISION_FORMAT.format(_revision)));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "namespace");
         final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
                 module.getNamespace().toString()));
 
-        instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) moduleSchemaNode), "feature");
         final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
         for (final FeatureDefinition feature : module.getFeatures()) {
@@ -405,7 +440,7 @@ public class RestconfImpl implements RestconfService {
         return callRpc(rpc, payload, parsePrettyPrintParameter(uriInfo));
     }
 
-    private void validateInput(final DataSchemaNode inputSchema, final CompositeNode payload) {
+    private void validateInput(final DataSchemaNode inputSchema, final Node<?> payload) {
         if (inputSchema != null && payload == null) {
             // expected a non null payload
             throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
@@ -416,6 +451,7 @@ public class RestconfImpl implements RestconfService {
         // else
         // {
         // TODO: Validate "mandatory" and "config" values here??? Or should those be
+        // those be
         // validate in a more central location inside MD-SAL core.
         // }
     }
@@ -436,7 +472,16 @@ public class RestconfImpl implements RestconfService {
         String streamName = null;
         if (!Iterables.isEmpty(pathIdentifier.getPathArguments())) {
             String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
-            streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
+
+            LogicalDatastoreType datastore = parseEnumTypeParameter(value, LogicalDatastoreType.class,
+                    DATASTORE_PARAM_NAME);
+            datastore = datastore == null ? DEFAULT_DATASTORE : datastore;
+
+            DataChangeScope scope = parseEnumTypeParameter(value, DataChangeScope.class, SCOPE_PARAM_NAME);
+            scope = scope == null ? DEFAULT_SCOPE : scope;
+
+            streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier + "/datastore=" + datastore
+                    + "/scope=" + scope);
         }
 
         if (Strings.isNullOrEmpty(streamName)) {
@@ -453,7 +498,7 @@ public class RestconfImpl implements RestconfService {
         final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(rpc.getOutput().getQName(),
                 null, output, null, null);
 
-        if (!Notificator.existListenerFor(pathIdentifier)) {
+        if (!Notificator.existListenerFor(streamName)) {
             Notificator.createListener(pathIdentifier, streamName);
         }
 
@@ -470,7 +515,7 @@ public class RestconfImpl implements RestconfService {
 
     private RpcExecutor resolveIdentifierInInvokeRpc(final String identifier) {
         String identifierEncoded = null;
-        MountInstance mountPoint = null;
+        DOMMountPoint mountPoint = null;
         if (identifier.contains(ControllerContext.MOUNT)) {
             // mounted RPC call - look up mount instance.
             InstanceIdWithSchemaNode mountPointId = controllerContext.toMountPointIdentifier(identifier);
@@ -529,7 +574,7 @@ public class RestconfImpl implements RestconfService {
         return null;
     }
 
-    private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload, boolean prettyPrint) {
+    private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload, final boolean prettyPrint) {
         if (rpcExecutor == null) {
             throw new RestconfDocumentedException("RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT);
         }
@@ -582,18 +627,23 @@ public class RestconfImpl implements RestconfService {
 
     @Override
     public StructuredData readConfigurationData(final String identifier, final UriInfo uriInfo) {
-        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
-        CompositeNode data = null;
-        MountInstance mountPoint = iiWithData.getMountPoint();
+        final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier);
+        DOMMountPoint mountPoint = iiWithData.getMountPoint();
+        NormalizedNode<?, ?> data = null;
+        YangInstanceIdentifier normalizedII;
         if (mountPoint != null) {
-            data = broker.readConfigurationDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
+            normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+            data = broker.readConfigurationData(mountPoint, normalizedII);
         } else {
-            data = broker.readConfigurationData(iiWithData.getInstanceIdentifier());
+            normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
+            data = broker.readConfigurationData(normalizedII);
         }
 
-        data = pruneDataAtDepth(data, parseDepthParameter(uriInfo));
-        boolean prettyPrintMode = parsePrettyPrintParameter(uriInfo);
-        return new StructuredData(data, iiWithData.getSchemaNode(), iiWithData.getMountPoint(), prettyPrintMode);
+        final CompositeNode compositeNode = datastoreNormalizedNodeToCompositeNode(data, iiWithData.getSchemaNode());
+        final CompositeNode prunedCompositeNode = pruneDataAtDepth(compositeNode, parseDepthParameter(uriInfo));
+
+        final boolean prettyPrintMode = parsePrettyPrintParameter(uriInfo);
+        return new StructuredData(prunedCompositeNode, iiWithData.getSchemaNode(), mountPoint, prettyPrintMode);
     }
 
     @SuppressWarnings("unchecked")
@@ -640,52 +690,57 @@ public class RestconfImpl implements RestconfService {
 
     @Override
     public StructuredData readOperationalData(final String identifier, final UriInfo info) {
-        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
-        CompositeNode data = null;
-        MountInstance mountPoint = iiWithData.getMountPoint();
+        final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier);
+        DOMMountPoint mountPoint = iiWithData.getMountPoint();
+        NormalizedNode<?, ?> data = null;
+        YangInstanceIdentifier normalizedII;
         if (mountPoint != null) {
-            data = broker.readOperationalDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
+            normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+            data = broker.readOperationalData(mountPoint, normalizedII);
         } else {
-            data = broker.readOperationalData(iiWithData.getInstanceIdentifier());
+            normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
+            data = broker.readOperationalData(normalizedII);
         }
 
-        data = pruneDataAtDepth(data, parseDepthParameter(info));
-        boolean prettyPrintMode = parsePrettyPrintParameter(info);
-        return new StructuredData(data, iiWithData.getSchemaNode(), mountPoint, prettyPrintMode);
+        final CompositeNode compositeNode = datastoreNormalizedNodeToCompositeNode(data, iiWithData.getSchemaNode());
+        final CompositeNode prunedCompositeNode = pruneDataAtDepth(compositeNode, parseDepthParameter(info));
+
+        final boolean prettyPrintMode = parsePrettyPrintParameter(info);
+        return new StructuredData(prunedCompositeNode, iiWithData.getSchemaNode(), mountPoint, prettyPrintMode);
     }
 
-    private boolean parsePrettyPrintParameter(UriInfo info) {
+    private boolean parsePrettyPrintParameter(final UriInfo info) {
         String param = info.getQueryParameters(false).getFirst(UriParameters.PRETTY_PRINT.toString());
         return Boolean.parseBoolean(param);
     }
 
     @Override
-    public Response updateConfigurationData(final String identifier, final CompositeNode payload) {
+    public Response updateConfigurationData(final String identifier, final Node<?> payload) {
         final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
 
         validateInput(iiWithData.getSchemaNode(), payload);
 
-        MountInstance mountPoint = iiWithData.getMountPoint();
+        DOMMountPoint mountPoint = iiWithData.getMountPoint();
         final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint);
-        validateListKeysEqualityInPayloadAndUri(iiWithData, payload);
-        RpcResult<TransactionStatus> status = null;
+        validateListKeysEqualityInPayloadAndUri(iiWithData, value);
+        final NormalizedNode<?, ?> datastoreNormalizedNode = compositeNodeToDatastoreNormalizedNode(value,
+                iiWithData.getSchemaNode());
+
+        YangInstanceIdentifier normalizedII;
 
         try {
             if (mountPoint != null) {
-                status = broker.commitConfigurationDataPutBehindMountPoint(mountPoint,
-                        iiWithData.getInstanceIdentifier(), value).get();
+                normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataPut(mountPoint, normalizedII, datastoreNormalizedNode).get();
             } else {
-                status = broker.commitConfigurationDataPut(iiWithData.getInstanceIdentifier(), value).get();
+                normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataPut(normalizedII, datastoreNormalizedNode).get();
             }
         } catch (Exception e) {
             throw new RestconfDocumentedException("Error updating data", e);
         }
 
-        if (status.getResult() == TransactionStatus.COMMITED) {
-            return Response.status(Status.OK).build();
-        }
-
-        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+        return Response.status(Status.OK).build();
     }
 
     /**
@@ -734,7 +789,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     @Override
-    public Response createConfigurationData(final String identifier, final CompositeNode payload) {
+    public Response createConfigurationData(final String identifier, final Node<?> payload) {
         if (payload == null) {
             throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
         }
@@ -765,50 +820,43 @@ public class RestconfImpl implements RestconfService {
             final InstanceIdWithSchemaNode incompleteInstIdWithData = this.controllerContext
                     .toInstanceIdentifier(identifier);
             final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
-            MountInstance mountPoint = incompleteInstIdWithData.getMountPoint();
-            final Module module = this.findModule(mountPoint, payload);
+            DOMMountPoint mountPoint = incompleteInstIdWithData.getMountPoint();
+            final Module module = findModule(mountPoint, payload);
             if (module == null) {
                 throw new RestconfDocumentedException("Module was not found for \"" + payloadNS + "\"",
                         ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
             }
 
             String payloadName = this.getName(payload);
-            final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+            final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(
                     parentSchema, payloadName, module.getNamespace());
             value = this.normalizeNode(payload, schemaNode, mountPoint);
 
-            iiWithData = this.addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
+            iiWithData = addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
         }
 
-        RpcResult<TransactionStatus> status = null;
-        MountInstance mountPoint = iiWithData.getMountPoint();
+        final NormalizedNode<?, ?> datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value,
+                iiWithData.getSchemaNode());
+        DOMMountPoint mountPoint = iiWithData.getMountPoint();
+        YangInstanceIdentifier normalizedII;
+
         try {
             if (mountPoint != null) {
-                Future<RpcResult<TransactionStatus>> future = broker.commitConfigurationDataPostBehindMountPoint(
-                        mountPoint, iiWithData.getInstanceIdentifier(), value);
-                status = future == null ? null : future.get();
+                normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataPost(mountPoint, normalizedII, datastoreNormalizedData);
             } else {
-                Future<RpcResult<TransactionStatus>> future = broker.commitConfigurationDataPost(
-                        iiWithData.getInstanceIdentifier(), value);
-                status = future == null ? null : future.get();
+                normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataPost(normalizedII, datastoreNormalizedData);
             }
         } catch (Exception e) {
             throw new RestconfDocumentedException("Error creating data", e);
         }
 
-        if (status == null) {
-            return Response.status(Status.ACCEPTED).build();
-        }
-
-        if (status.getResult() == TransactionStatus.COMMITED) {
-            return Response.status(Status.NO_CONTENT).build();
-        }
-
-        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+        return Response.status(Status.NO_CONTENT).build();
     }
 
     @Override
-    public Response createConfigurationData(final CompositeNode payload) {
+    public Response createConfigurationData(final Node<?> payload) {
         if (payload == null) {
             throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
         }
@@ -828,62 +876,60 @@ public class RestconfImpl implements RestconfService {
         }
 
         String payloadName = this.getName(payload);
-        final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(module,
+        final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(module,
                 payloadName, module.getNamespace());
         final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
         final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
-        RpcResult<TransactionStatus> status = null;
-        MountInstance mountPoint = iiWithData.getMountPoint();
+        final NormalizedNode<?, ?> datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value, schemaNode);
+        DOMMountPoint mountPoint = iiWithData.getMountPoint();
+        YangInstanceIdentifier normalizedII;
 
         try {
             if (mountPoint != null) {
-                Future<RpcResult<TransactionStatus>> future = broker.commitConfigurationDataPostBehindMountPoint(
-                        mountPoint, iiWithData.getInstanceIdentifier(), value);
-                status = future == null ? null : future.get();
+                normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataPost(mountPoint, normalizedII, datastoreNormalizedData);
+
             } else {
-                Future<RpcResult<TransactionStatus>> future = broker.commitConfigurationDataPost(
-                        iiWithData.getInstanceIdentifier(), value);
-                status = future == null ? null : future.get();
+                normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataPost(normalizedII, datastoreNormalizedData);
             }
         } catch (Exception e) {
             throw new RestconfDocumentedException("Error creating data", e);
         }
 
-        if (status == null) {
-            return Response.status(Status.ACCEPTED).build();
-        }
-
-        if (status.getResult() == TransactionStatus.COMMITED) {
-            return Response.status(Status.NO_CONTENT).build();
-        }
-
-        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+        return Response.status(Status.NO_CONTENT).build();
     }
 
     @Override
     public Response deleteConfigurationData(final String identifier) {
-        final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
-        RpcResult<TransactionStatus> status = null;
-        MountInstance mountPoint = iiWithData.getMountPoint();
+        final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier);
+        DOMMountPoint mountPoint = iiWithData.getMountPoint();
+        YangInstanceIdentifier normalizedII;
 
         try {
             if (mountPoint != null) {
-                status = broker.commitConfigurationDataDeleteBehindMountPoint(mountPoint,
-                        iiWithData.getInstanceIdentifier()).get();
+                normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataDelete(mountPoint, normalizedII);
             } else {
-                status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier()).get();
+                normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
+                broker.commitConfigurationDataDelete(normalizedII).get();
             }
         } catch (Exception e) {
             throw new RestconfDocumentedException("Error creating data", e);
         }
 
-        if (status.getResult() == TransactionStatus.COMMITED) {
-            return Response.status(Status.OK).build();
-        }
-
-        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+        return Response.status(Status.OK).build();
     }
 
+    /**
+     * Subscribes to some path in schema context (stream) to listen on changes on this stream.
+     *
+     * Additional parameters for subscribing to stream are loaded via rpc input parameters:
+     * <ul>
+     * <li>datastore</li> - default CONFIGURATION (other values of {@link LogicalDatastoreType} enum type)
+     * <li>scope</li> - default BASE (other values of {@link DataChangeScope})
+     * </ul>
+     */
     @Override
     public Response subscribeToStream(final String identifier, final UriInfo uriInfo) {
         final String streamName = Notificator.createStreamNameFromUri(identifier);
@@ -896,18 +942,98 @@ public class RestconfImpl implements RestconfService {
             throw new RestconfDocumentedException("Stream was not found.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
         }
 
-        broker.registerToListenDataChanges(listener);
+        Map<String, String> paramToValues = resolveValuesFromUri(identifier);
+        LogicalDatastoreType datastore = parserURIEnumParameter(LogicalDatastoreType.class,
+                paramToValues.get(DATASTORE_PARAM_NAME));
+        if (datastore == null) {
+            throw new RestconfDocumentedException("Stream name doesn't contains datastore value (pattern /datastore=)",
+                    ErrorType.APPLICATION, ErrorTag.MISSING_ATTRIBUTE);
+        }
+        DataChangeScope scope = parserURIEnumParameter(DataChangeScope.class, paramToValues.get(SCOPE_PARAM_NAME));
+        if (scope == null) {
+            throw new RestconfDocumentedException("Stream name doesn't contains datastore value (pattern /scope=)",
+                    ErrorType.APPLICATION, ErrorTag.MISSING_ATTRIBUTE);
+        }
+
+        broker.registerToListenDataChanges(datastore, scope, listener);
 
         final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
-        UriBuilder port = uriBuilder.port(WebSocketServer.getInstance().getPort());
+        int notificationPort = NOTIFICATION_PORT;
+        try {
+            WebSocketServer webSocketServerInstance = WebSocketServer.getInstance();
+            notificationPort = webSocketServerInstance.getPort();
+        } catch (NullPointerException e) {
+            WebSocketServer.createInstance(NOTIFICATION_PORT);
+        }
+        UriBuilder port = uriBuilder.port(notificationPort);
         final URI uriToWebsocketServer = port.replacePath(streamName).build();
 
         return Response.status(Status.OK).location(uriToWebsocketServer).build();
     }
 
-    private Module findModule(final MountInstance mountPoint, final CompositeNode data) {
-        if (data instanceof CompositeNodeWrapper) {
-            return findModule(mountPoint, (CompositeNodeWrapper) data);
+    /**
+     * Load parameter for subscribing to stream from input composite node
+     *
+     * @param compNode
+     *            contains value
+     * @return enum object if its string value is equal to {@code paramName}. In other cases null.
+     */
+    private <T> T parseEnumTypeParameter(final CompositeNode compNode, final Class<T> classDescriptor,
+            final String paramName) {
+        QNameModule salRemoteAugment = QNameModule.create(NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT,
+                EVENT_SUBSCRIPTION_AUGMENT_REVISION);
+        SimpleNode<?> simpleNode = compNode.getFirstSimpleByName(QName.create(salRemoteAugment, paramName));
+        if (simpleNode == null) {
+            return null;
+        }
+        Object rawValue = simpleNode.getValue();
+        if (!(rawValue instanceof String)) {
+            return null;
+        }
+
+        return resolveAsEnum(classDescriptor, (String) rawValue);
+    }
+
+    /**
+     * Checks whether {@code value} is one of the string representation of enumeration {@code classDescriptor}
+     *
+     * @return enum object if string value of {@code classDescriptor} enumeration is equal to {@code value}. Other cases
+     *         null.
+     */
+    private <T> T parserURIEnumParameter(final Class<T> classDescriptor, final String value) {
+        if (Strings.isNullOrEmpty(value)) {
+            return null;
+        }
+        return resolveAsEnum(classDescriptor, value);
+    }
+
+    private <T> T resolveAsEnum(final Class<T> classDescriptor, final String value) {
+        T[] enumConstants = classDescriptor.getEnumConstants();
+        if (enumConstants != null) {
+            for (T enm : classDescriptor.getEnumConstants()) {
+                if (((Enum<?>) enm).name().equals(value)) {
+                    return enm;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Map<String, String> resolveValuesFromUri(final String uri) {
+        Map<String, String> result = new HashMap<>();
+        String[] tokens = uri.split("/");
+        for (int i = 1; i < tokens.length; i++) {
+            String[] parameterTokens = tokens[i].split("=");
+            if (parameterTokens.length == 2) {
+                result.put(parameterTokens[0], parameterTokens[1]);
+            }
+        }
+        return result;
+    }
+
+    private Module findModule(final DOMMountPoint mountPoint, final Node<?> data) {
+        if (data instanceof NodeWrapper) {
+            return findModule(mountPoint, (NodeWrapper<?>) data);
         } else if (data != null) {
             URI namespace = data.getNodeType().getNamespace();
             if (mountPoint != null) {
@@ -921,7 +1047,7 @@ public class RestconfImpl implements RestconfService {
         }
     }
 
-    private Module findModule(final MountInstance mountPoint, final CompositeNodeWrapper data) {
+    private Module findModule(final DOMMountPoint mountPoint, final NodeWrapper<?> data) {
         URI namespace = data.getNamespace();
         Preconditions.<URI> checkNotNull(namespace);
 
@@ -956,15 +1082,10 @@ public class RestconfImpl implements RestconfService {
             iiBuilder = YangInstanceIdentifier.builder(iiOriginal);
         }
 
-        if ((schemaOfData instanceof ListSchemaNode)) {
-            HashMap<QName, Object> keys = this.resolveKeysFromData(((ListSchemaNode) schemaOfData), data);
-            iiBuilder.nodeWithKey(schemaOfData.getQName(), keys);
-        } else {
-            iiBuilder.node(schemaOfData.getQName());
-        }
+        iiBuilder.node(schemaOfData.getQName());
 
         YangInstanceIdentifier instance = iiBuilder.toInstance();
-        MountInstance mountPoint = null;
+        DOMMountPoint mountPoint = null;
         if (identifierWithSchemaNode != null) {
             mountPoint = identifierWithSchemaNode.getMountPoint();
         }
@@ -972,45 +1093,17 @@ public class RestconfImpl implements RestconfService {
         return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint);
     }
 
-    private HashMap<QName, Object> resolveKeysFromData(final ListSchemaNode listNode, final CompositeNode dataNode) {
-        final HashMap<QName, Object> keyValues = new HashMap<QName, Object>();
-        List<QName> _keyDefinition = listNode.getKeyDefinition();
-        for (final QName key : _keyDefinition) {
-            SimpleNode<? extends Object> head = null;
-            String localName = key.getLocalName();
-            List<SimpleNode<? extends Object>> simpleNodesByName = dataNode.getSimpleNodesByName(localName);
-            if (simpleNodesByName != null) {
-                head = Iterables.getFirst(simpleNodesByName, null);
-            }
-
-            Object dataNodeKeyValueObject = null;
-            if (head != null) {
-                dataNodeKeyValueObject = head.getValue();
-            }
-
-            if (dataNodeKeyValueObject == null) {
-                throw new RestconfDocumentedException("Data contains list \"" + dataNode.getNodeType().getLocalName()
-                        + "\" which does not contain key: \"" + key.getLocalName() + "\"", ErrorType.PROTOCOL,
-                        ErrorTag.INVALID_VALUE);
-            }
-
-            keyValues.put(key, dataNodeKeyValueObject);
-        }
-
-        return keyValues;
-    }
-
     private boolean endsWithMountPoint(final String identifier) {
         return identifier.endsWith(ControllerContext.MOUNT) || identifier.endsWith(ControllerContext.MOUNT + "/");
     }
 
-    private boolean representsMountPointRootData(final CompositeNode data) {
+    private boolean representsMountPointRootData(final Node<?> data) {
         URI namespace = this.namespace(data);
         return (SchemaContext.NAME.getNamespace().equals(namespace) /*
-                                                                     * || MOUNT_POINT_MODULE_NAME .equals( namespace .
-                                                                     * toString( ) )
-                                                                     */)
-                && SchemaContext.NAME.getLocalName().equals(this.localName(data));
+         * || MOUNT_POINT_MODULE_NAME .equals( namespace .
+         * toString( ) )
+         */)
+         && SchemaContext.NAME.getLocalName().equals(this.localName(data));
     }
 
     private String addMountPointIdentifier(final String identifier) {
@@ -1022,8 +1115,7 @@ public class RestconfImpl implements RestconfService {
         return identifier + "/" + ControllerContext.MOUNT;
     }
 
-    private CompositeNode normalizeNode(final CompositeNode node, final DataSchemaNode schema,
-            final MountInstance mountPoint) {
+    private CompositeNode normalizeNode(final Node<?> node, final DataSchemaNode schema, final DOMMountPoint mountPoint) {
         if (schema == null) {
             QName nodeType = node == null ? null : node.getNodeType();
             String localName = nodeType == null ? null : nodeType.getLocalName();
@@ -1037,24 +1129,32 @@ public class RestconfImpl implements RestconfService {
                     ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
         }
 
-        if ((node instanceof CompositeNodeWrapper)) {
-            boolean isChangeAllowed = ((CompositeNodeWrapper) node).isChangeAllowed();
+        if ((node instanceof NodeWrapper<?>)) {
+            NodeWrapper<?> nodeWrap = (NodeWrapper<?>) node;
+            boolean isChangeAllowed = ((NodeWrapper<?>) node).isChangeAllowed();
             if (isChangeAllowed) {
+                nodeWrap = topLevelElementAsCompositeNodeWrapper((NodeWrapper<?>) node, schema);
                 try {
-                    this.normalizeNode(((CompositeNodeWrapper) node), schema, null, mountPoint);
+                    this.normalizeNode(nodeWrap, schema, null, mountPoint);
                 } catch (IllegalArgumentException e) {
                     throw new RestconfDocumentedException(e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
                 }
+                if (nodeWrap instanceof CompositeNodeWrapper) {
+                    return ((CompositeNodeWrapper) nodeWrap).unwrap();
+                }
             }
+        }
 
-            return ((CompositeNodeWrapper) node).unwrap();
+        if (node instanceof CompositeNode) {
+            return (CompositeNode) node;
         }
 
-        return node;
+        throw new RestconfDocumentedException("Top level element is not interpreted as composite node.",
+                ErrorType.APPLICATION, ErrorTag.INVALID_VALUE);
     }
 
     private void normalizeNode(final NodeWrapper<? extends Object> nodeBuilder, final DataSchemaNode schema,
-            final QName previousAugment, final MountInstance mountPoint) {
+            final QName previousAugment, final DOMMountPoint mountPoint) {
         if (schema == null) {
             throw new RestconfDocumentedException("Data has bad format.\n\"" + nodeBuilder.getLocalName()
                     + "\" does not exist in yang schema.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
@@ -1111,7 +1211,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     private void normalizeSimpleNode(final SimpleNodeWrapper simpleNode, final DataSchemaNode schema,
-            final MountInstance mountPoint) {
+            final DOMMountPoint mountPoint) {
         final Object value = simpleNode.getValue();
         Object inputValue = value;
         TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
@@ -1133,11 +1233,11 @@ public class RestconfImpl implements RestconfService {
     }
 
     private void normalizeCompositeNode(final CompositeNodeWrapper compositeNodeBuilder,
-            final DataNodeContainer schema, final MountInstance mountPoint, final QName currentAugment) {
+            final DataNodeContainer schema, final DOMMountPoint mountPoint, final QName currentAugment) {
         final List<NodeWrapper<?>> children = compositeNodeBuilder.getValues();
         checkNodeMultiplicityAccordingToSchema(schema, children);
         for (final NodeWrapper<? extends Object> child : children) {
-            final List<DataSchemaNode> potentialSchemaNodes = this.controllerContext.findInstanceDataChildrenByName(
+            final List<DataSchemaNode> potentialSchemaNodes = ControllerContext.findInstanceDataChildrenByName(
                     schema, child.getLocalName());
 
             if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
@@ -1214,7 +1314,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     private QName normalizeNodeName(final NodeWrapper<? extends Object> nodeBuilder, final DataSchemaNode schema,
-            final QName previousAugment, final MountInstance mountPoint) {
+            final QName previousAugment, final DOMMountPoint mountPoint) {
         QName validQName = schema.getQName();
         QName currentAugment = previousAugment;
         if (schema.isAugmenting()) {
@@ -1232,15 +1332,16 @@ public class RestconfImpl implements RestconfService {
         }
 
         if (nodeBuilder.getNamespace() == null || Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace())
-                || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*
-                                                                                     * || Note : this check is wrong -
-                                                                                     * can never be true as it compares
-                                                                                     * a URI with a String not sure what
-                                                                                     * the intention is so commented out
-                                                                                     * ... Objects . equal ( nodeBuilder
-                                                                                     * . getNamespace ( ) ,
-                                                                                     * MOUNT_POINT_MODULE_NAME )
-                                                                                     */) {
+                || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName)) {
+            /*
+             * || Note : this check is wrong -
+             * can never be true as it compares
+             * a URI with a String not sure what
+             * the intention is so commented out
+             * ... Objects . equal ( nodeBuilder
+             * . getNamespace ( ) ,
+             * MOUNT_POINT_MODULE_NAME )
+             */
 
             nodeBuilder.setQname(validQName);
         }
@@ -1248,9 +1349,9 @@ public class RestconfImpl implements RestconfService {
         return currentAugment;
     }
 
-    private URI namespace(final CompositeNode data) {
-        if (data instanceof CompositeNodeWrapper) {
-            return ((CompositeNodeWrapper) data).getNamespace();
+    private URI namespace(final Node<?> data) {
+        if (data instanceof NodeWrapper) {
+            return ((NodeWrapper<?>) data).getNamespace();
         } else if (data != null) {
             return data.getNodeType().getNamespace();
         } else {
@@ -1258,9 +1359,9 @@ public class RestconfImpl implements RestconfService {
         }
     }
 
-    private String localName(final CompositeNode data) {
-        if (data instanceof CompositeNodeWrapper) {
-            return ((CompositeNodeWrapper) data).getLocalName();
+    private String localName(final Node<?> data) {
+        if (data instanceof NodeWrapper) {
+            return ((NodeWrapper<?>) data).getLocalName();
         } else if (data != null) {
             return data.getNodeType().getLocalName();
         } else {
@@ -1268,9 +1369,9 @@ public class RestconfImpl implements RestconfService {
         }
     }
 
-    private String getName(final CompositeNode data) {
-        if (data instanceof CompositeNodeWrapper) {
-            return ((CompositeNodeWrapper) data).getLocalName();
+    private String getName(final Node<?> data) {
+        if (data instanceof NodeWrapper) {
+            return ((NodeWrapper<?>) data).getLocalName();
         } else if (data != null) {
             return data.getNodeType().getLocalName();
         } else {
@@ -1307,4 +1408,89 @@ public class RestconfImpl implements RestconfService {
             throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object> asList(node).toString());
         }
     }
+
+    private CompositeNode datastoreNormalizedNodeToCompositeNode(final NormalizedNode<?, ?> dataNode, final DataSchemaNode schema) {
+        Node<?> nodes = null;
+        if (dataNode == null) {
+            throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING,
+                    "No data was found."));
+        }
+        nodes = DataNormalizer.toLegacy(dataNode);
+        if (nodes != null) {
+            if (nodes instanceof CompositeNode) {
+                return (CompositeNode) nodes;
+            } else {
+                LOG.error("The node " + dataNode.getNodeType() + " couldn't be transformed to compositenode.");
+            }
+        } else {
+            LOG.error("Top level node isn't of type Container or List schema node but "
+                    + schema.getClass().getSimpleName());
+        }
+
+        throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                "It wasn't possible to correctly interpret data."));
+    }
+
+    private NormalizedNode<?, ?> compositeNodeToDatastoreNormalizedNode(final CompositeNode compNode, final DataSchemaNode schema) {
+        List<Node<?>> lst = new ArrayList<Node<?>>();
+        lst.add(compNode);
+        if (schema instanceof ContainerSchemaNode) {
+            return CnSnToNormalizedNodeParserFactory.getInstance().getContainerNodeParser()
+                    .parse(lst, (ContainerSchemaNode) schema);
+        } else if (schema instanceof ListSchemaNode) {
+            return CnSnToNormalizedNodeParserFactory.getInstance().getMapEntryNodeParser()
+                    .parse(lst, (ListSchemaNode) schema);
+        }
+
+        LOG.error("Top level isn't of type container, list, leaf schema node but " + schema.getClass().getSimpleName());
+
+        throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                "It wasn't possible to translate specified data to datastore readable form."));
+    }
+
+    private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode(final InstanceIdWithSchemaNode iiWithSchemaNode) {
+        return normalizeInstanceIdentifierWithSchemaNode(iiWithSchemaNode, false);
+    }
+
+    private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode(
+            final InstanceIdWithSchemaNode iiWithSchemaNode, final boolean unwrapLastListNode) {
+        return new InstanceIdWithSchemaNode(instanceIdentifierToReadableFormForNormalizeNode(
+                iiWithSchemaNode.getInstanceIdentifier(), unwrapLastListNode), iiWithSchemaNode.getSchemaNode(),
+                iiWithSchemaNode.getMountPoint());
+    }
+
+    private YangInstanceIdentifier instanceIdentifierToReadableFormForNormalizeNode(final YangInstanceIdentifier instIdentifier,
+            final boolean unwrapLastListNode) {
+        Preconditions.checkNotNull(instIdentifier, "Instance identifier can't be null");
+        final List<PathArgument> result = new ArrayList<PathArgument>();
+        final Iterator<PathArgument> iter = instIdentifier.getPathArguments().iterator();
+        while (iter.hasNext()) {
+            final PathArgument pathArgument = iter.next();
+            if (pathArgument instanceof NodeIdentifierWithPredicates && (iter.hasNext() || unwrapLastListNode)) {
+                result.add(new YangInstanceIdentifier.NodeIdentifier(pathArgument.getNodeType()));
+            }
+            result.add(pathArgument);
+        }
+        return YangInstanceIdentifier.create(result);
+    }
+
+    private CompositeNodeWrapper topLevelElementAsCompositeNodeWrapper(final NodeWrapper<?> node,
+            final DataSchemaNode schemaNode) {
+        if (node instanceof CompositeNodeWrapper) {
+            return (CompositeNodeWrapper) node;
+        } else if (node instanceof SimpleNodeWrapper && isDataContainerNode(schemaNode)) {
+            final SimpleNodeWrapper simpleNodeWrapper = (SimpleNodeWrapper) node;
+            return new CompositeNodeWrapper(namespace(simpleNodeWrapper), localName(simpleNodeWrapper));
+        }
+
+        throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                "Top level element has to be composite node or has to represent data container node."));
+    }
+
+    private boolean isDataContainerNode(final DataSchemaNode schemaNode) {
+        if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode) {
+            return true;
+        }
+        return false;
+    }
 }
index c745a8009deac75a70a7249626b07f56457d9243..29354349671943d2c3e67e16188c06ae9dd3bc55 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
@@ -15,14 +15,14 @@ public class StructuredData {
 
     private final CompositeNode data;
     private final DataSchemaNode schema;
-    private final MountInstance mountPoint;
+    private final DOMMountPoint mountPoint;
     private final boolean prettyPrintMode;
 
-    public StructuredData(final CompositeNode data, final DataSchemaNode schema, final MountInstance mountPoint) {
+    public StructuredData(final CompositeNode data, final DataSchemaNode schema, final DOMMountPoint mountPoint) {
         this(data, schema, mountPoint, false);
     }
 
-    public StructuredData(final CompositeNode data, final DataSchemaNode schema, final MountInstance mountPoint,
+    public StructuredData(final CompositeNode data, final DataSchemaNode schema, final DOMMountPoint mountPoint,
             final boolean preattyPrintMode) {
         this.data = data;
         this.schema = schema;
@@ -38,7 +38,7 @@ public class StructuredData {
         return schema;
     }
 
-    public MountInstance getMountPoint() {
+    public DOMMountPoint getMountPoint() {
         return mountPoint;
     }
 
index 36502656c22834829deaaa73f01defce0be1885d..efb3e0a1d3924d914afe4dcc286ad783d94de8e0 100644 (file)
@@ -7,9 +7,12 @@
  */
 package org.opendaylight.controller.sal.restconf.rpc.impl;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import java.util.concurrent.Future;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
@@ -21,9 +24,9 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
  *
  */
 public class MountPointRpcExecutor extends AbstractRpcExecutor {
-    private final MountInstance mountPoint;
+    private final DOMMountPoint mountPoint;
 
-    public MountPointRpcExecutor(RpcDefinition rpcDef, MountInstance mountPoint) {
+    public MountPointRpcExecutor(RpcDefinition rpcDef, DOMMountPoint mountPoint) {
         super(rpcDef);
         this.mountPoint = mountPoint;
         Preconditions.checkNotNull(mountPoint, "MountInstance can not be null.");
@@ -31,6 +34,10 @@ public class MountPointRpcExecutor extends AbstractRpcExecutor {
 
     @Override
     protected Future<RpcResult<CompositeNode>> invokeRpcUnchecked(CompositeNode rpcRequest) {
-        return mountPoint.rpc(getRpcDefinition().getQName(), rpcRequest);
+        Optional<RpcProvisionRegistry> service = mountPoint.getService(RpcProvisionRegistry.class);
+        if (service.isPresent()) {
+            return service.get().invokeRpc(getRpcDefinition().getQName(), rpcRequest);
+        }
+        throw new RestconfDocumentedException("Rpc service is missing.");
     }
 }
\ No newline at end of file
index 2b7b0246e35ac2356ce90f87126d5e4f43076a2c..a6e02632ce6fd15eeb57127b5af34a772626a6c6 100644 (file)
@@ -38,8 +38,8 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
 import org.opendaylight.controller.sal.rest.impl.XmlMapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -49,6 +49,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,7 +60,7 @@ import org.w3c.dom.Node;
 /**
  * {@link ListenerAdapter} is responsible to track events, which occurred by changing data in data source.
  */
-public class ListenerAdapter implements DataChangeListener {
+public class ListenerAdapter implements DOMDataChangeListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(ListenerAdapter.class);
     private static final DocumentBuilderFactory DBF = DocumentBuilderFactory.newInstance();
@@ -70,7 +71,7 @@ public class ListenerAdapter implements DataChangeListener {
     private final SimpleDateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
 
     private final YangInstanceIdentifier path;
-    private ListenerRegistration<DataChangeListener> registration;
+    private ListenerRegistration<DOMDataChangeListener> registration;
     private final String streamName;
     private Set<Channel> subscribers = new ConcurrentSet<>();
     private final EventBus eventBus;
@@ -95,10 +96,11 @@ public class ListenerAdapter implements DataChangeListener {
     }
 
     @Override
-    public void onDataChanged(final DataChangeEvent<YangInstanceIdentifier, CompositeNode> change) {
-        if (!change.getCreatedConfigurationData().isEmpty() || !change.getCreatedOperationalData().isEmpty()
-                || !change.getUpdatedConfigurationData().isEmpty() || !change.getUpdatedOperationalData().isEmpty()
-                || !change.getRemovedConfigurationData().isEmpty() || !change.getRemovedOperationalData().isEmpty()) {
+    public void onDataChanged(AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
+        // TODO Auto-generated method stub
+
+        if (!change.getCreatedData().isEmpty() || !change.getUpdatedData().isEmpty()
+                || !change.getRemovedPaths().isEmpty()) {
             String xml = prepareXmlFrom(change);
             Event event = new Event(EventType.NOTIFY);
             event.setData(xml);
@@ -216,7 +218,7 @@ public class ListenerAdapter implements DataChangeListener {
      *            DataChangeEvent
      * @return Data in printable form.
      */
-    private String prepareXmlFrom(final DataChangeEvent<YangInstanceIdentifier, CompositeNode> change) {
+    private String prepareXmlFrom(AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
         Document doc = createDocument();
         Element notificationElement = doc.createElementNS("urn:ietf:params:xml:ns:netconf:notification:1.0",
                 "notification");
@@ -262,7 +264,6 @@ public class ListenerAdapter implements DataChangeListener {
 
     /**
      * Creates {@link Document} document.
-     *
      * @return {@link Document} document.
      */
     private Document createDocument() {
@@ -287,23 +288,15 @@ public class ListenerAdapter implements DataChangeListener {
      */
     private void addValuesToDataChangedNotificationEventElement(final Document doc,
             final Element dataChangedNotificationEventElement,
-            final DataChangeEvent<YangInstanceIdentifier, CompositeNode> change) {
-        addValuesFromDataToElement(doc, change.getCreatedConfigurationData(), dataChangedNotificationEventElement,
-                Store.CONFIG, Operation.CREATED);
-        addValuesFromDataToElement(doc, change.getCreatedOperationalData(), dataChangedNotificationEventElement,
-                Store.OPERATION, Operation.CREATED);
-        if (change.getCreatedConfigurationData().isEmpty()) {
-            addValuesFromDataToElement(doc, change.getUpdatedConfigurationData(), dataChangedNotificationEventElement,
-                    Store.CONFIG, Operation.UPDATED);
-        }
-        if (change.getCreatedOperationalData().isEmpty()) {
-            addValuesFromDataToElement(doc, change.getUpdatedOperationalData(), dataChangedNotificationEventElement,
-                    Store.OPERATION, Operation.UPDATED);
+            AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
+        addValuesFromDataToElement(doc, change.getCreatedData().keySet(), dataChangedNotificationEventElement,
+                Operation.CREATED);
+        if (change.getCreatedData().isEmpty()) {
+            addValuesFromDataToElement(doc, change.getUpdatedData().keySet(), dataChangedNotificationEventElement,
+                    Operation.UPDATED);
         }
-        addValuesFromDataToElement(doc, change.getRemovedConfigurationData(), dataChangedNotificationEventElement,
-                Store.CONFIG, Operation.DELETED);
-        addValuesFromDataToElement(doc, change.getRemovedOperationalData(), dataChangedNotificationEventElement,
-                Store.OPERATION, Operation.DELETED);
+        addValuesFromDataToElement(doc, change.getRemovedPaths(), dataChangedNotificationEventElement,
+                Operation.DELETED);
     }
 
     /**
@@ -320,13 +313,13 @@ public class ListenerAdapter implements DataChangeListener {
      * @param operation
      *            {@link Operation}
      */
-    private void addValuesFromDataToElement(final Document doc, final Set<YangInstanceIdentifier> data,
-            final Element element, final Store store, final Operation operation) {
+    private void addValuesFromDataToElement(Document doc, Set<YangInstanceIdentifier> data, Element element,
+            Operation operation) {
         if (data == null || data.isEmpty()) {
             return;
         }
         for (YangInstanceIdentifier path : data) {
-            Node node = createDataChangeEventElement(doc, path, null, store, operation);
+            Node node = createDataChangeEventElement(doc, path, null, operation);
             element.appendChild(node);
         }
     }
@@ -345,13 +338,13 @@ public class ListenerAdapter implements DataChangeListener {
      * @param operation
      *            {@link Operation}
      */
-    private void addValuesFromDataToElement(final Document doc, final Map<YangInstanceIdentifier, CompositeNode> data,
-            final Element element, final Store store, final Operation operation) {
+    private void addValuesFromDataToElement(Document doc, Map<YangInstanceIdentifier, CompositeNode> data, Element element,
+            Operation operation) {
         if (data == null || data.isEmpty()) {
             return;
         }
         for (Entry<YangInstanceIdentifier, CompositeNode> entry : data.entrySet()) {
-            Node node = createDataChangeEventElement(doc, entry.getKey(), entry.getValue(), store, operation);
+            Node node = createDataChangeEventElement(doc, entry.getKey(), entry.getValue(), operation);
             element.appendChild(node);
         }
     }
@@ -371,17 +364,17 @@ public class ListenerAdapter implements DataChangeListener {
      *            {@link Operation}
      * @return {@link Node} node represented by changed event element.
      */
-    private Node createDataChangeEventElement(final Document doc, final YangInstanceIdentifier path,
-            final CompositeNode data, final Store store, final Operation operation) {
+    private Node createDataChangeEventElement(Document doc, YangInstanceIdentifier path, CompositeNode data,
+            Operation operation) {
         Element dataChangeEventElement = doc.createElement("data-change-event");
 
         Element pathElement = doc.createElement("path");
         addPathAsValueToElement(path, pathElement);
         dataChangeEventElement.appendChild(pathElement);
 
-        Element storeElement = doc.createElement("store");
-        storeElement.setTextContent(store.value);
-        dataChangeEventElement.appendChild(storeElement);
+        // Element storeElement = doc.createElement("store");
+        // storeElement.setTextContent(store.value);
+        // dataChangeEventElement.appendChild(storeElement);
 
         Element operationElement = doc.createElement("operation");
         operationElement.setTextContent(operation.value);
@@ -530,7 +523,7 @@ public class ListenerAdapter implements DataChangeListener {
      * @param registration
      *            ListenerRegistration<DataChangeListener>
      */
-    public void setRegistration(final ListenerRegistration<DataChangeListener> registration) {
+    public void setRegistration(final ListenerRegistration<DOMDataChangeListener> registration) {
         this.registration = registration;
     }
 
index cf1bcd6a30b6c4d22464e3678f2c468a995479c8..17565a6b8c082d314f5b4e90715be18ca3536a8c 100644 (file)
@@ -15,12 +15,12 @@ import java.util.concurrent.locks.ReentrantLock;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
 /**
- * {@link Notificator} is responsible to create, remove and find {@link ListenerAdapter} listener.
+ * {@link Notificator} is responsible to create, remove and find
+ * {@link ListenerAdapter} listener.
  */
 public class Notificator {
 
     private static Map<String, ListenerAdapter> listenersByStreamName = new ConcurrentHashMap<>();
-    private static Map<YangInstanceIdentifier, ListenerAdapter> listenersByInstanceIdentifier = new ConcurrentHashMap<>();
     private static final Lock lock = new ReentrantLock();
 
     private Notificator() {
@@ -44,26 +44,14 @@ public class Notificator {
         return listenersByStreamName.get(streamName);
     }
 
-    /**
-     * Gets {@link ListenerAdapter} listener specified by {@link YangInstanceIdentifier} path.
-     *
-     * @param path
-     *            Path to data in data repository.
-     * @return ListenerAdapter
-     */
-    public static ListenerAdapter getListenerFor(YangInstanceIdentifier path) {
-        return listenersByInstanceIdentifier.get(path);
-    }
-
     /**
      * Checks if the listener specified by {@link YangInstanceIdentifier} path exist.
      *
-     * @param path
-     *            Path to data in data repository.
+     * @param streamName
      * @return True if the listener exist, false otherwise.
      */
-    public static boolean existListenerFor(YangInstanceIdentifier path) {
-        return listenersByInstanceIdentifier.containsKey(path);
+    public static boolean existListenerFor(String streamName) {
+        return listenersByStreamName.containsKey(streamName);
     }
 
     /**
@@ -79,7 +67,6 @@ public class Notificator {
         ListenerAdapter listener = new ListenerAdapter(path, streamName);
         try {
             lock.lock();
-            listenersByInstanceIdentifier.put(path, listener);
             listenersByStreamName.put(streamName, listener);
         } finally {
             lock.unlock();
@@ -89,16 +76,6 @@ public class Notificator {
 
     /**
      * Looks for listener determined by {@link YangInstanceIdentifier} path and removes it.
-     *
-     * @param path
-     *            InstanceIdentifier
-     */
-    public static void removeListener(YangInstanceIdentifier path) {
-        ListenerAdapter listener = listenersByInstanceIdentifier.get(path);
-        deleteListener(listener);
-    }
-
-    /**
      * Creates String representation of stream name from URI. Removes slash from URI in start and end position.
      *
      * @param uri
@@ -114,7 +91,7 @@ public class Notificator {
             result = result.substring(1);
         }
         if (result.endsWith("/")) {
-            result = result.substring(0, result.length());
+            result = result.substring(0, result.length()-1);
         }
         return result;
     }
@@ -123,7 +100,7 @@ public class Notificator {
      * Removes all listeners.
      */
     public static void removeAllListeners() {
-        for (ListenerAdapter listener : listenersByInstanceIdentifier.values()) {
+        for (ListenerAdapter listener : listenersByStreamName.values()) {
             try {
                 listener.close();
             } catch (Exception e) {
@@ -132,7 +109,6 @@ public class Notificator {
         try {
             lock.lock();
             listenersByStreamName = new ConcurrentHashMap<>();
-            listenersByInstanceIdentifier = new ConcurrentHashMap<>();
         } finally {
             lock.unlock();
         }
@@ -164,7 +140,6 @@ public class Notificator {
             }
             try {
                 lock.lock();
-                listenersByInstanceIdentifier.remove(listener.getPath());
                 listenersByStreamName.remove(listener.getStreamName());
             } finally {
                 lock.unlock();
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/yang/sal-remote-augment.yang b/opendaylight/md-sal/sal-rest-connector/src/main/yang/sal-remote-augment.yang
new file mode 100644 (file)
index 0000000..8393456
--- /dev/null
@@ -0,0 +1,31 @@
+module sal-remote-augment {
+
+    yang-version 1;
+    namespace "urn:sal:restconf:event:subscription";
+    prefix "salrmt-aug-ev-subscr";
+
+    import sal-remote {prefix salrmt; revision-date "2014-01-14";}
+
+    description
+        "Added input parameters to rpc create-data-change-event-subscription";
+
+    revision "2014-7-8" {
+    }
+
+    augment "/salrmt:create-data-change-event-subscription/salrmt:input" {
+        leaf datastore {
+            type enumeration {
+                enum OPERATIONAL;
+                enum CONFIGURATION;
+            }
+        }
+        leaf scope {
+            type enumeration {
+                enum BASE;
+                enum ONE;
+                enum SUBTREE;
+            }
+        }
+    }
+
+}
\ No newline at end of file
index 0f059f5024cdc7c70dc7042f488e9fa22c32da55..d9dc26d888acfb37a29a5d09b2b2245f163dd603 100644 (file)
@@ -35,6 +35,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
 public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
@@ -67,12 +68,12 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
      */
     @Test
     public void xmlAndYangTypesWithJsonReaderTest() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/cnsn-to-json/simple-yang-types/xml/data.xml",
+        Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-yang-types/xml/data.xml",
                 XmlToCompositeNodeProvider.INSTANCE);
-        TestUtils.normalizeCompositeNode(compositeNode, modules, searchedModuleName + ":" + searchedDataSchemaName);
+        TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
         String jsonOutput = null;
         try {
-            jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(compositeNode, modules, dataSchemaNode,
+            jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
                     StructuredDataToJsonProvider.INSTANCE);
         } catch (WebApplicationException | IOException e) {
         }
index 0d0ce5cdd36908e458e50ac242ef356d4008287e..632d2490ee2623272d7aff1a944a48a6d4ce353d 100644 (file)
@@ -17,7 +17,8 @@ import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataValidationException;
 
 public class CnSnJsonChoiceCaseTest extends YangAndXmlAndDataSchemaLoader {
 
@@ -31,7 +32,7 @@ public class CnSnJsonChoiceCaseTest extends YangAndXmlAndDataSchemaLoader {
      * return error because nodes has to be from one case below concrete choice.
      *
      */
-    @Test
+    @Test(expected=DataValidationException.class)
     public void nodeSchemasOnVariousChoiceCasePathTest() {
         testWrapper("/cnsn-to-json/choice/xml/data_various_path_err.xml", "choice-case-test:cont");
     }
@@ -42,7 +43,7 @@ public class CnSnJsonChoiceCaseTest extends YangAndXmlAndDataSchemaLoader {
      * choice.
      *
      */
-    @Test
+    @Test(expected=DataValidationException.class)
     public void nodeSchemasOnVariousChoiceCasePathAndMultipleChoicesTest() {
         testWrapper("/cnsn-to-json/choice/xml/data_more_choices_same_level_various_paths_err.xml",
                 "choice-case-test:cont");
@@ -116,10 +117,10 @@ public class CnSnJsonChoiceCaseTest extends YangAndXmlAndDataSchemaLoader {
     }
 
     private void testWrapper(String xmlPath, String pathToSchemaNode) {
-        CompositeNode compNode = TestUtils.readInputToCnSn(xmlPath, XmlToCompositeNodeProvider.INSTANCE);
-        TestUtils.normalizeCompositeNode(compNode, modules, pathToSchemaNode);
+        Node<?> node = TestUtils.readInputToCnSn(xmlPath, XmlToCompositeNodeProvider.INSTANCE);
+        TestUtils.normalizeCompositeNode(node, modules, pathToSchemaNode);
         try {
-            TestUtils.writeCompNodeWithSchemaContextToOutput(compNode, modules, dataSchemaNode,
+            TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
                     StructuredDataToJsonProvider.INSTANCE);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
index 4b8b71440a7688334897bafc3c3117e8e2dfb937..11051cc73324009bee596c209e1a51968f3635f0 100644 (file)
@@ -27,7 +27,7 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 
 public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader {
 
@@ -189,12 +189,12 @@ public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader
     @Test
     public void simpleYangDataTest() throws Exception {
 
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/data.xml",
+        Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/data.xml",
                 XmlToCompositeNodeProvider.INSTANCE);
 
-        TestUtils.normalizeCompositeNode(compositeNode, modules, "simple-data-types:cont");
+        TestUtils.normalizeCompositeNode(node, modules, "simple-data-types:cont");
 
-        String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(compositeNode, modules, dataSchemaNode,
+        String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
                 StructuredDataToJsonProvider.INSTANCE);
 
         assertNotNull(jsonOutput);
@@ -303,10 +303,10 @@ public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader
     public void testBadData() throws Exception {
 
         try {
-            CompositeNode compositeNode = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/bad-data.xml",
+            Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/bad-data.xml",
                     XmlToCompositeNodeProvider.INSTANCE);
 
-            TestUtils.normalizeCompositeNode(compositeNode, modules, "simple-data-types:cont");
+            TestUtils.normalizeCompositeNode(node, modules, "simple-data-types:cont");
             fail("Expected RestconfDocumentedException");
         } catch (RestconfDocumentedException e) {
             assertEquals("getErrorTag", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
index 50c834b1ffee46f96787d73ac47c9f6e49d6ffd4..3bd600dbf1a5b28335c0486add9145cef1cfda16 100644 (file)
@@ -21,7 +21,7 @@ import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
 import org.opendaylight.yangtools.yang.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.ConstraintDefinition;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -145,16 +145,15 @@ public class CnSnToJsonIncorrectTopLevelTest extends YangAndXmlAndDataSchemaLoad
     @Test
     public void incorrectTopLevelElementTest() {
 
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/data.xml",
-                XmlToCompositeNodeProvider.INSTANCE);
+        Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/data.xml", XmlToCompositeNodeProvider.INSTANCE);
         DataSchemaNode incorrectDataSchema = null;
         incorrectDataSchema = new IncorrectDataSchema();
 
-        TestUtils.normalizeCompositeNode(compositeNode, modules, "simple-data-types:cont");
+        TestUtils.normalizeCompositeNode(node, modules, "simple-data-types:cont");
 
         boolean exceptionRaised = false;
         try {
-            TestUtils.writeCompNodeWithSchemaContextToOutput(compositeNode, modules, incorrectDataSchema,
+            TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, incorrectDataSchema,
                     StructuredDataToJsonProvider.INSTANCE);
         } catch (UnsupportedDataTypeException e) {
             exceptionRaised = true;
index 6e41dcb57769b6fd633edb2bea9ea0ede1c9014a..b5d3528e95857cd95c9956522bf633f99edc6763 100644 (file)
@@ -20,7 +20,7 @@ import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 
 /**
  *
@@ -95,9 +95,9 @@ public class CnSnToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
 
     private String toJson(String xmlDataPath) {
         try {
-            CompositeNode compositeNode = TestUtils.readInputToCnSn(xmlDataPath, XmlToCompositeNodeProvider.INSTANCE);
-            TestUtils.normalizeCompositeNode(compositeNode, modules, searchedModuleName + ":" + searchedDataSchemaName);
-            return TestUtils.writeCompNodeWithSchemaContextToOutput(compositeNode, modules, dataSchemaNode,
+            Node<?> node = TestUtils.readInputToCnSn(xmlDataPath, XmlToCompositeNodeProvider.INSTANCE);
+            TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
+            return TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
                     StructuredDataToJsonProvider.INSTANCE);
         } catch (WebApplicationException | IOException e) {
         }
index eb6a5b9e00f7c7af65d2398bd2e21e87f650fe9f..72b9ed93d469642886064641fabfb18284244052 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 
 public class CnSnToJsonWithAugmentTest extends YangAndXmlAndDataSchemaLoader {
 
@@ -33,13 +33,13 @@ public class CnSnToJsonWithAugmentTest extends YangAndXmlAndDataSchemaLoader {
      */
     @Test
     public void augmentedElementsToJson() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/cnsn-to-json/augmentation/xml/data.xml",
+        Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/augmentation/xml/data.xml",
                 XmlToCompositeNodeProvider.INSTANCE);
-        TestUtils.normalizeCompositeNode(compositeNode, modules, searchedModuleName + ":" + searchedDataSchemaName);
+        TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
 
         String jsonOutput = null;
         try {
-            jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(compositeNode, modules, dataSchemaNode,
+            jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
                     StructuredDataToJsonProvider.INSTANCE);
         } catch (WebApplicationException | IOException e) {
         }
index 4210944de71a6791ef7426533465f8cd9c900c5e..3adfee7f5bf3d44ff9f6a164d4765f0deab8671b 100644 (file)
@@ -13,12 +13,12 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.google.common.util.concurrent.CheckedFuture;
 import java.io.FileNotFoundException;
 import java.net.URI;
 import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
@@ -28,13 +28,10 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.test.DummyFuture;
-import org.opendaylight.controller.sal.restconf.impl.test.DummyFuture.Builder;
-import org.opendaylight.controller.sal.restconf.impl.test.DummyRpcResult;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -62,11 +59,8 @@ public class RestPutListDataTest {
         restconfImpl = RestconfImpl.getInstance();
         restconfImpl.setBroker(brokerFacade);
         restconfImpl.setControllerContext(controllerContext);
-        Builder<TransactionStatus> futureBuilder = new DummyFuture.Builder<TransactionStatus>();
-        futureBuilder.rpcResult(new DummyRpcResult.Builder<TransactionStatus>().result(TransactionStatus.COMMITED)
-                .build());
-        when(brokerFacade.commitConfigurationDataPut(any(YangInstanceIdentifier.class), any(CompositeNode.class)))
-                .thenReturn(futureBuilder.build());
+        when(brokerFacade.commitConfigurationDataPut(any(YangInstanceIdentifier.class), any(NormalizedNode.class)))
+                .thenReturn(mock(CheckedFuture.class));
     }
 
     /**
index 23b040a9a3846b6e273dedcb0fcb42e8c36ff5f4..cda635e84713a86f6fbe1485b00d78e83889e6a2 100644 (file)
@@ -31,15 +31,16 @@ public class JsonIdentityrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
     @Test
     public void jsonIdentityrefToCompositeNode() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/identityref/json/data.json", false,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/identityref/json/data.json", false,
                 JsonToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        assertNotNull(node);
 
-        TestUtils.normalizeCompositeNode(compositeNode, modules, searchedModuleName + ":" + searchedDataSchemaName);
+        TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
 
-        assertEquals("cont", compositeNode.getNodeType().getLocalName());
+        assertEquals("cont", node.getNodeType().getLocalName());
 
-        List<Node<?>> childs = compositeNode.getValue();
+        assert(node instanceof CompositeNode);
+        List<Node<?>> childs = ((CompositeNode)node).getValue();
         assertEquals(1, childs.size());
         Node<?> nd = childs.iterator().next();
         assertTrue(nd instanceof CompositeNode);
index 913e9f2d707bd310feb103313d53d5c8a83928df..59696bc534803935ab5c0c0126d0a43fc2c75fa5 100644 (file)
@@ -32,15 +32,16 @@ public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
      */
     @Test
     public void jsonIdentityrefToCompositeNode() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/leafref/json/data.json", false,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/leafref/json/data.json", false,
                 JsonToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
-        TestUtils.normalizeCompositeNode(compositeNode, modules, searchedModuleName + ":" + searchedDataSchemaName);
+        assertNotNull(node);
+        TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
 
-        assertEquals("cont", compositeNode.getNodeType().getLocalName());
+        assertEquals("cont", node.getNodeType().getLocalName());
 
         SimpleNode<?> lf2 = null;
-        for (Node<?> childNode : compositeNode.getValue()) {
+        assertTrue(node instanceof CompositeNode);
+        for (Node<?> childNode : ((CompositeNode) node).getValue()) {
             if (childNode instanceof SimpleNode) {
                 if (childNode.getNodeType().getLocalName().equals("lf2")) {
                     lf2 = (SimpleNode<?>) childNode;
index 7b71e42ab8ed669516c4e724231628c8d6bd4908..3699e4924fe25ca2c8a4b1399fe005376de3a86d 100644 (file)
@@ -11,6 +11,7 @@ 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 java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -52,19 +53,21 @@ public class JsonToCnSnTest {
      */
     @Test
     public void multipleItemsInLeafList() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-leaflist-items.json", true,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-leaflist-items.json", true,
                 JsonToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        assertNotNull(node);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
         assertEquals(3, compositeNode.getValue().size());
 
         boolean lflst1_1 = false;
         boolean lflst1_2 = false;
         boolean lflst1_3 = false;
 
-        for (Node<?> node : compositeNode.getValue()) {
-            assertEquals("lflst1", node.getNodeType().getLocalName());
-            assertTrue(node instanceof SimpleNode<?>);
-            SimpleNode<?> simpleNode = (SimpleNode<?>) node;
+        for (Node<?> nd : compositeNode.getValue()) {
+            assertEquals("lflst1", nd.getNodeType().getLocalName());
+            assertTrue(nd instanceof SimpleNode<?>);
+            SimpleNode<?> simpleNode = (SimpleNode<?>) nd;
             if (simpleNode.getValue().equals("45")) {
                 lflst1_1 = true;
             } else if (simpleNode.getValue().equals("55")) {
@@ -86,9 +89,12 @@ public class JsonToCnSnTest {
      */
     @Test
     public void multipleItemsInListTest() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-items-in-list.json", true,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-items-in-list.json", true,
                 JsonToCompositeNodeProvider.INSTANCE);
 
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
+
         assertNotNull(compositeNode);
         assertEquals("lst", compositeNode.getNodeType().getLocalName());
 
@@ -97,9 +103,10 @@ public class JsonToCnSnTest {
 
     @Test
     public void nullArrayToSimpleNodeWithNullValueTest() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/array-with-null.json", true,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/array-with-null.json", true,
                 JsonToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
         assertNotNull(compositeNode.getValue());
@@ -163,10 +170,10 @@ public class JsonToCnSnTest {
      */
     @Test
     public void emptyDataReadTest() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/empty-data.json", true,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/empty-data.json", true,
                 JsonToCompositeNodeProvider.INSTANCE);
-
-        assertNotNull(compositeNode);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
 
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
         assertTrue(compositeNode instanceof CompositeNode);
@@ -189,9 +196,9 @@ public class JsonToCnSnTest {
     @Test
     public void testJsonBlankInput() throws Exception {
         InputStream inputStream = new ByteArrayInputStream("".getBytes());
-        CompositeNode compositeNode = JsonToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null,
-                inputStream);
-        assertNull(compositeNode);
+        Node<?> node =
+                JsonToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
+        assertNull( node );
     }
 
     /**
@@ -202,9 +209,10 @@ public class JsonToCnSnTest {
     @Test
     public void notSupplyNamespaceIfAlreadySupplied() {
 
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/simple-list.json", false,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/simple-list.json", false,
                 JsonToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
 
         // supplement namespaces according to first data schema -
         // "simple:data:types1"
@@ -223,15 +231,21 @@ public class JsonToCnSnTest {
         assertEquals("lst", compNode.getNodeType().getLocalName());
         verifyCompositeNode(compNode, "simple:list:yang1");
 
-        TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst");
+        try {
+            TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst");
+            fail("Conversion to normalized node shouldn't be successfull because of different namespaces");
+        } catch (IllegalStateException e) {
+        }
+//        veryfing has still meaning. despite exception, first phase where normalization of NodeWrappers is called passed successfuly.
         verifyCompositeNode(compNode, "simple:list:yang1");
     }
 
     @Test
     public void jsonIdentityrefToCompositeNode() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/identityref/json/data.json", false,
+        Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/identityref/json/data.json", false,
                 JsonToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
 
         Set<Module> modules = TestUtils.loadModulesFrom("/json-to-cnsn/identityref");
         assertEquals(2, modules.size());
@@ -298,8 +312,9 @@ public class JsonToCnSnTest {
 
     private CompositeNode loadAndNormalizeData(final String jsonPath, final String yangPath,
             final String topLevelElementName, final String moduleName) {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn(jsonPath, false, JsonToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        Node<?> node = TestUtils.readInputToCnSn(jsonPath, false, JsonToCompositeNodeProvider.INSTANCE);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
 
         Set<Module> modules = null;
         modules = TestUtils.loadModulesFrom(yangPath);
index 73f828c6466a886a2f5d7de7029c590389c5e662..146e88299ac6133e71fbf240cea3953956dbbd78 100644 (file)
@@ -12,29 +12,36 @@ 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.Matchers.eq;
 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.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
-import java.util.Map;
 import java.util.concurrent.Future;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+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.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.DOMMountPoint;
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
@@ -44,7 +51,9 @@ 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.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 
 /**
  * Unit tests for BrokerFacade.
@@ -54,73 +63,85 @@ import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 public class BrokerFacadeTest {
 
     @Mock
-    DataBrokerService dataBroker;
-
-    @Mock
-    DataModificationTransaction mockTransaction;
+    DOMDataBroker domDataBroker;
 
     @Mock
     ConsumerSession mockConsumerSession;
 
     @Mock
-    MountInstance mockMountInstance;
+    DOMMountPoint mockMountInstance;
 
     BrokerFacade brokerFacade = BrokerFacade.getInstance();
 
-    CompositeNode dataNode = TestUtils.readInputToCnSn("/parts/ietf-interfaces_interfaces.xml",
-            XmlToCompositeNodeProvider.INSTANCE);
+    CompositeNode dataNode;
 
-    QName qname = QName.create("node");
+    NormalizedNode<?, ?> dummyNode = createDummyNode("test:module", "2014-01-09", "interfaces");
+    CheckedFuture<Optional<NormalizedNode<?, ?>>,ReadFailedException> dummyNodeInFuture = wrapDummyNode(dummyNode);
+
+    QName qname = TestUtils.buildQName("interfaces","test:module", "2014-01-09");
 
     YangInstanceIdentifier instanceID = YangInstanceIdentifier.builder().node(qname).toInstance();
 
+    @Mock
+    DOMDataReadOnlyTransaction rTransaction;
+
+    @Mock
+    DOMDataWriteTransaction wTransaction;
+
+    @Mock
+    DOMDataReadWriteTransaction rwTransaction;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-
-        brokerFacade.setDataService(dataBroker);
+        // TODO it is started before every test method
+        brokerFacade.setDomDataBroker(domDataBroker);
         brokerFacade.setContext(mockConsumerSession);
-    }
+        when(domDataBroker.newReadOnlyTransaction()).thenReturn(rTransaction);
+        when(domDataBroker.newWriteOnlyTransaction()).thenReturn(wTransaction);
+        when(domDataBroker.newReadWriteTransaction()).thenReturn(rwTransaction);
 
-    @Test
-    public void testReadConfigurationData() {
-        when(dataBroker.readConfigurationData(instanceID)).thenReturn(dataNode);
+        dataNode = TestUtils.prepareCompositeNodeWithIetfInterfacesInterfacesData();
 
-        CompositeNode actualNode = brokerFacade.readConfigurationData(instanceID);
+        ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext("/full-versions/test-module"));
 
-        assertSame("readConfigurationData", dataNode, actualNode);
     }
 
-    @Test
-    public void testReadConfigurationDataBehindMountPoint() {
-        when(mockMountInstance.readConfigurationData(instanceID)).thenReturn(dataNode);
-
-        CompositeNode actualNode = brokerFacade.readConfigurationDataBehindMountPoint(mockMountInstance, instanceID);
+    private CheckedFuture<Optional<NormalizedNode<?, ?>>,ReadFailedException> wrapDummyNode(final NormalizedNode<?, ?> dummyNode) {
+        return  Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>> of(dummyNode));
+    }
 
-        assertSame("readConfigurationDataBehindMountPoint", dataNode, actualNode);
+    /**
+     * Value of this node shouldn't be important for testing purposes
+     */
+    private NormalizedNode<?, ?> createDummyNode(final String namespace, final String date, final String localName) {
+        return Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(QName.create(namespace, date, localName))).build();
     }
 
     @Test
-    public void testReadOperationalData() {
-        when(dataBroker.readOperationalData(instanceID)).thenReturn(dataNode);
+    public void testReadConfigurationData() {
+        when(rTransaction.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class))).thenReturn(
+                dummyNodeInFuture);
 
-        CompositeNode actualNode = brokerFacade.readOperationalData(instanceID);
+        NormalizedNode<?, ?> actualNode = brokerFacade.readConfigurationData(instanceID);
 
-        assertSame("readOperationalData", dataNode, actualNode);
+        assertSame("readConfigurationData", dummyNode, actualNode);
     }
 
     @Test
-    public void testReadOperationalDataBehindMountPoint() {
-        when(mockMountInstance.readOperationalData(instanceID)).thenReturn(dataNode);
+    public void testReadOperationalData() {
+        when(rTransaction.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class))).thenReturn(
+                dummyNodeInFuture);
 
-        CompositeNode actualNode = brokerFacade.readOperationalDataBehindMountPoint(mockMountInstance, instanceID);
+        NormalizedNode<?, ?> actualNode = brokerFacade.readOperationalData(instanceID);
 
-        assertSame("readOperationalDataBehindMountPoint", dataNode, actualNode);
+        assertSame("readOperationalData", dummyNode, actualNode);
     }
 
     @Test(expected = RestconfDocumentedException.class)
     public void testReadOperationalDataWithNoDataBroker() {
-        brokerFacade.setDataService(null);
+        brokerFacade.setDomDataBroker(null);
 
         brokerFacade.readOperationalData(instanceID);
     }
@@ -146,111 +167,49 @@ public class BrokerFacadeTest {
         brokerFacade.invokeRpc(qname, dataNode);
     }
 
+    @Ignore
     @Test
     public void testCommitConfigurationDataPut() {
-        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture(null);
-
-        when(dataBroker.beginTransaction()).thenReturn(mockTransaction);
-        mockTransaction.putConfigurationData(instanceID, dataNode);
-        when(mockTransaction.commit()).thenReturn(expFuture);
-
-        Future<RpcResult<TransactionStatus>> actualFuture = brokerFacade.commitConfigurationDataPut(instanceID,
-                dataNode);
+        CheckedFuture<Void, TransactionCommitFailedException> expFuture = mock(CheckedFuture.class);
 
-        assertSame("invokeRpc", expFuture, actualFuture);
+        when(wTransaction.submit()).thenReturn(expFuture);
 
-        InOrder inOrder = inOrder(dataBroker, mockTransaction);
-        inOrder.verify(dataBroker).beginTransaction();
-        inOrder.verify(mockTransaction).putConfigurationData(instanceID, dataNode);
-        inOrder.verify(mockTransaction).commit();
-    }
-
-    @Test
-    public void testCommitConfigurationDataPutBehindMountPoint() {
-        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture(null);
-
-        when(mockMountInstance.beginTransaction()).thenReturn(mockTransaction);
-        mockTransaction.putConfigurationData(instanceID, dataNode);
-        when(mockTransaction.commit()).thenReturn(expFuture);
+        Future<Void> actualFuture = brokerFacade.commitConfigurationDataPut(instanceID, dummyNode);
 
-        Future<RpcResult<TransactionStatus>> actualFuture = brokerFacade.commitConfigurationDataPutBehindMountPoint(
-                mockMountInstance, instanceID, dataNode);
-
-        assertSame("invokeRpc", expFuture, actualFuture);
+        assertSame("commitConfigurationDataPut", expFuture, actualFuture);
 
-        InOrder inOrder = inOrder(mockMountInstance, mockTransaction);
-        inOrder.verify(mockMountInstance).beginTransaction();
-        inOrder.verify(mockTransaction).putConfigurationData(instanceID, dataNode);
-        inOrder.verify(mockTransaction).commit();
+        InOrder inOrder = inOrder(domDataBroker, wTransaction);
+        inOrder.verify(domDataBroker).newWriteOnlyTransaction();
+        inOrder.verify(wTransaction).put(LogicalDatastoreType.CONFIGURATION, instanceID, dummyNode);
+        inOrder.verify(wTransaction).submit();
     }
 
     @Test
     public void testCommitConfigurationDataPost() {
-        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture(null);
+        CheckedFuture<Void, TransactionCommitFailedException> expFuture = mock(CheckedFuture.class);
 
-        Map<YangInstanceIdentifier, CompositeNode> nodeMap = new ImmutableMap.Builder<YangInstanceIdentifier, CompositeNode>()
-                .put(instanceID, dataNode).build();
+        NormalizedNode<?, ?> dummyNode2 = createDummyNode("dummy:namespace2", "2014-07-01", "dummy local name2");
+        when(rwTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
+                wrapDummyNode(dummyNode2));
+        when(rwTransaction.submit()).thenReturn(expFuture);
 
-        when(dataBroker.beginTransaction()).thenReturn(mockTransaction);
-        mockTransaction.putConfigurationData(instanceID, dataNode);
-        when(mockTransaction.getCreatedConfigurationData()).thenReturn(nodeMap);
-        when(mockTransaction.commit()).thenReturn(expFuture);
+        CheckedFuture<Void, TransactionCommitFailedException> actualFuture = brokerFacade.commitConfigurationDataPost(
+                instanceID, dummyNode);
 
-        Future<RpcResult<TransactionStatus>> actualFuture = brokerFacade.commitConfigurationDataPost(instanceID,
-                dataNode);
+        assertSame("commitConfigurationDataPost", expFuture, actualFuture);
 
-        assertSame("commitConfigurationDataPut", expFuture, actualFuture);
-
-        InOrder inOrder = inOrder(dataBroker, mockTransaction);
-        inOrder.verify(dataBroker).beginTransaction();
-        inOrder.verify(mockTransaction).putConfigurationData(instanceID, dataNode);
-        inOrder.verify(mockTransaction).commit();
+        InOrder inOrder = inOrder(domDataBroker, rwTransaction);
+        inOrder.verify(domDataBroker).newReadWriteTransaction();
+        inOrder.verify(rwTransaction).merge(LogicalDatastoreType.CONFIGURATION, instanceID, dummyNode);
+        inOrder.verify(rwTransaction).submit();
     }
 
     @Test(expected = RestconfDocumentedException.class)
     public void testCommitConfigurationDataPostAlreadyExists() {
-        when(dataBroker.beginTransaction()).thenReturn(mockTransaction);
-        mockTransaction.putConfigurationData(instanceID, dataNode);
-        when(mockTransaction.readConfigurationData(instanceID)).thenReturn(dataNode);
+        when(rwTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
+                dummyNodeInFuture);
         try {
-            brokerFacade.commitConfigurationDataPost(instanceID, dataNode);
-        } catch (RestconfDocumentedException e) {
-            assertEquals("getErrorTag", RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get(0).getErrorTag());
-            throw e;
-        }
-    }
-
-    @Test
-    public void testCommitConfigurationDataPostBehindMountPoint() {
-        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture(null);
-
-        Map<YangInstanceIdentifier, CompositeNode> nodeMap = new ImmutableMap.Builder<YangInstanceIdentifier, CompositeNode>()
-                .put(instanceID, dataNode).build();
-
-        when(mockMountInstance.beginTransaction()).thenReturn(mockTransaction);
-        mockTransaction.putConfigurationData(instanceID, dataNode);
-        when(mockTransaction.getCreatedConfigurationData()).thenReturn(nodeMap);
-        when(mockTransaction.commit()).thenReturn(expFuture);
-
-        Future<RpcResult<TransactionStatus>> actualFuture = brokerFacade.commitConfigurationDataPostBehindMountPoint(
-                mockMountInstance, instanceID, dataNode);
-
-        assertSame("commitConfigurationDataPostBehindMountPoint", expFuture, actualFuture);
-
-        InOrder inOrder = inOrder(mockMountInstance, mockTransaction);
-        inOrder.verify(mockMountInstance).beginTransaction();
-        inOrder.verify(mockTransaction).putConfigurationData(instanceID, dataNode);
-        inOrder.verify(mockTransaction).commit();
-    }
-
-    @Test(expected = RestconfDocumentedException.class)
-    public void testCommitConfigurationDataPostBehindMountPointAlreadyExists() {
-
-        when(mockMountInstance.beginTransaction()).thenReturn(mockTransaction);
-        mockTransaction.putConfigurationData(instanceID, dataNode);
-        when(mockTransaction.readConfigurationData(instanceID)).thenReturn(dataNode);
-        try {
-            brokerFacade.commitConfigurationDataPostBehindMountPoint(mockMountInstance, instanceID, dataNode);
+            brokerFacade.commitConfigurationDataPost(instanceID, dummyNode);
         } catch (RestconfDocumentedException e) {
             assertEquals("getErrorTag", RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get(0).getErrorTag());
             throw e;
@@ -259,43 +218,19 @@ public class BrokerFacadeTest {
 
     @Test
     public void testCommitConfigurationDataDelete() {
-        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture(null);
+        CheckedFuture<Void, TransactionCommitFailedException> expFuture = mock(CheckedFuture.class);
 
-        when(dataBroker.beginTransaction()).thenReturn(mockTransaction);
-        when(mockTransaction.readConfigurationData(any(YangInstanceIdentifier.class))).thenReturn(
-                ImmutableCompositeNode.builder().toInstance());
-        mockTransaction.removeConfigurationData(instanceID);
-        when(mockTransaction.commit()).thenReturn(expFuture);
+        when(wTransaction.submit()).thenReturn(expFuture);
 
-        Future<RpcResult<TransactionStatus>> actualFuture = brokerFacade.commitConfigurationDataDelete(instanceID);
+        CheckedFuture<Void, TransactionCommitFailedException> actualFuture = brokerFacade
+                .commitConfigurationDataDelete(instanceID);
 
         assertSame("commitConfigurationDataDelete", expFuture, actualFuture);
 
-        InOrder inOrder = inOrder(dataBroker, mockTransaction);
-        inOrder.verify(dataBroker).beginTransaction();
-        inOrder.verify(mockTransaction).removeConfigurationData(instanceID);
-        inOrder.verify(mockTransaction).commit();
-    }
-
-    @Test
-    public void testCommitConfigurationDataDeleteBehindMountPoint() {
-        Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture(null);
-
-        when(mockMountInstance.beginTransaction()).thenReturn(mockTransaction);
-        when(mockTransaction.readConfigurationData(any(YangInstanceIdentifier.class))).thenReturn(
-                ImmutableCompositeNode.builder().toInstance());
-        mockTransaction.removeConfigurationData(instanceID);
-        when(mockTransaction.commit()).thenReturn(expFuture);
-
-        Future<RpcResult<TransactionStatus>> actualFuture = brokerFacade.commitConfigurationDataDeleteBehindMountPoint(
-                mockMountInstance, instanceID);
-
-        assertSame("commitConfigurationDataDeleteBehindMountPoint", expFuture, actualFuture);
-
-        InOrder inOrder = inOrder(mockMountInstance, mockTransaction);
-        inOrder.verify(mockMountInstance).beginTransaction();
-        inOrder.verify(mockTransaction).removeConfigurationData(instanceID);
-        inOrder.verify(mockTransaction).commit();
+        InOrder inOrder = inOrder(domDataBroker, wTransaction);
+        inOrder.verify(domDataBroker).newWriteOnlyTransaction();
+        inOrder.verify(wTransaction).delete(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
+        inOrder.verify(wTransaction).submit();
     }
 
     @SuppressWarnings("unchecked")
@@ -303,16 +238,21 @@ public class BrokerFacadeTest {
     public void testRegisterToListenDataChanges() {
         ListenerAdapter listener = Notificator.createListener(instanceID, "stream");
 
-        ListenerRegistration<DataChangeListener> mockRegistration = mock(ListenerRegistration.class);
-        when(dataBroker.registerDataChangeListener(instanceID, listener)).thenReturn(mockRegistration);
+        ListenerRegistration<DOMDataChangeListener> mockRegistration = mock(ListenerRegistration.class);
+
+        when(
+                domDataBroker.registerDataChangeListener(any(LogicalDatastoreType.class), eq(instanceID), eq(listener),
+                        eq(DataChangeScope.BASE))).thenReturn(mockRegistration);
 
-        brokerFacade.registerToListenDataChanges(listener);
+        brokerFacade.registerToListenDataChanges(LogicalDatastoreType.CONFIGURATION, DataChangeScope.BASE, listener);
 
-        verify(dataBroker).registerDataChangeListener(instanceID, listener);
+        verify(domDataBroker).registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, instanceID, listener,
+                DataChangeScope.BASE);
 
         assertEquals("isListening", true, listener.isListening());
 
-        brokerFacade.registerToListenDataChanges(listener);
-        verifyNoMoreInteractions(dataBroker);
+        brokerFacade.registerToListenDataChanges(LogicalDatastoreType.CONFIGURATION, DataChangeScope.BASE, listener);
+        verifyNoMoreInteractions(domDataBroker);
+
     }
 }
index 9aab841546016a5cb09f669c168307b2aaf0f725..500baafab3476cba31ed159ec7b87c7cca66cdd5 100644 (file)
@@ -36,7 +36,8 @@ import javax.ws.rs.core.UriInfo;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
@@ -317,9 +318,10 @@ public class InvokeRpcMethodTest {
         RpcDefinition mockRpc = mock(RpcDefinition.class);
         when(mockRpc.getQName()).thenReturn(cancelToastQName);
 
-        MountInstance mockMountPoint = mock(MountInstance.class);
-        when(mockMountPoint.rpc(eq(cancelToastQName), any(CompositeNode.class))).thenReturn(mockListener);
-
+        DOMMountPoint mockMountPoint = mock(DOMMountPoint.class);
+        RpcProvisionRegistry mockedRpcProvisionRegistry = mock(RpcProvisionRegistry.class);
+        when(mockedRpcProvisionRegistry.invokeRpc(eq(cancelToastQName), any(CompositeNode.class))).thenReturn(mockListener);
+        when(mockMountPoint.getService(eq(RpcProvisionRegistry.class))).thenReturn(Optional.of(mockedRpcProvisionRegistry));
         when(mockMountPoint.getSchemaContext()).thenReturn(TestUtils.loadSchemaContext("/invoke-rpc"));
 
         InstanceIdWithSchemaNode mockedInstanceId = mock(InstanceIdWithSchemaNode.class);
index 5fbfc453523339500c46e5d751b7967db455c19d..478565f033df3a1c0a1b8e21cb1ce3fd4e5d9339 100644 (file)
@@ -21,7 +21,7 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException
 import org.opendaylight.controller.sal.restconf.impl.RestconfError;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
 /**
@@ -57,16 +57,16 @@ public class MultipleEqualNamesForDataNodesTest {
     }
 
     private void multipleEqualNameDataNodeTest(String path, ErrorType errorType, ErrorTag errorTag,
-            MessageBodyReader<CompositeNode> messageBodyReader) {
+            MessageBodyReader<Node<?>> messageBodyReader) {
         try {
-            CompositeNode compositeNode = TestUtils.readInputToCnSn(path, false, messageBodyReader);
-            assertNotNull(compositeNode);
+            Node<?> node = TestUtils.readInputToCnSn(path, false, messageBodyReader);
+            assertNotNull(node);
 
             Set<Module> modules = null;
             modules = TestUtils.loadModulesFrom("/equal-data-node-names/yang");
             assertNotNull(modules);
 
-            TestUtils.normalizeCompositeNode(compositeNode, modules, "equal-data-node-names" + ":" + "cont");
+            TestUtils.normalizeCompositeNode(node, modules, "equal-data-node-names" + ":" + "cont");
             fail("Exception RestconfDocumentedException should be raised");
         } catch (RestconfDocumentedException e) {
             List<RestconfError> errors = e.getErrors();
index 66ced818175e2435cda90e41a854214277c6403b..8d5cac02048c4fd6043dc56208c6f6e9146cc91f 100644 (file)
@@ -10,13 +10,14 @@ package org.opendaylight.controller.sal.restconf.impl.test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.google.common.util.concurrent.CheckedFuture;
 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;
@@ -24,13 +25,12 @@ import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -70,21 +70,14 @@ public class RestDeleteOperationTest extends JerseyTest {
     @Test
     public void deleteConfigStatusCodes() throws UnsupportedEncodingException {
         String uri = "/config/test-interface:interfaces";
-        Future<RpcResult<TransactionStatus>> dummyFuture = createFuture(TransactionStatus.COMMITED);
-        when(brokerFacade.commitConfigurationDataDelete(any(YangInstanceIdentifier.class))).thenReturn(dummyFuture);
+        when(brokerFacade.commitConfigurationDataDelete(any(YangInstanceIdentifier.class))).thenReturn(
+                mock(CheckedFuture.class));
         Response response = target(uri).request(MediaType.APPLICATION_XML).delete();
         assertEquals(200, response.getStatus());
 
-        dummyFuture = createFuture(TransactionStatus.FAILED);
-        when(brokerFacade.commitConfigurationDataDelete(any(YangInstanceIdentifier.class))).thenReturn(dummyFuture);
+        doThrow(RestconfDocumentedException.class).when(brokerFacade).commitConfigurationDataDelete(
+                any(YangInstanceIdentifier.class));
         response = target(uri).request(MediaType.APPLICATION_XML).delete();
         assertEquals(500, response.getStatus());
     }
-
-    private Future<RpcResult<TransactionStatus>> createFuture(TransactionStatus statusName) {
-        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(statusName)
-                .build();
-        return new DummyFuture.Builder<TransactionStatus>().rpcResult(rpcResult).build();
-    }
-
 }
index ac660e32bce0f654e8801a56c723f6ec6736c80c..539248a147cd4eea16dca9f4725cf26e9b185496 100644 (file)
@@ -18,8 +18,10 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import java.io.FileNotFoundException;
-import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -33,40 +35,43 @@ import java.util.Map;
 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.MultivaluedHashMap;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
-
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.Node;
+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.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+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.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -74,9 +79,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
 public class RestGetOperationTest extends JerseyTest {
 
     static class NodeData {
@@ -93,7 +95,7 @@ public class RestGetOperationTest extends JerseyTest {
     private static RestconfImpl restconfImpl;
     private static SchemaContext schemaContextYangsIetf;
     private static SchemaContext schemaContextTestModule;
-    private static CompositeNode answerFromGet;
+    private static NormalizedNode answerFromGet;
 
     private static SchemaContext schemaContextModules;
     private static SchemaContext schemaContextBehindMountPoint;
@@ -101,7 +103,7 @@ public class RestGetOperationTest extends JerseyTest {
     private static final String RESTCONF_NS = "urn:ietf:params:xml:ns:yang:ietf-restconf";
 
     @BeforeClass
-    public static void init() throws FileNotFoundException {
+    public static void init() throws FileNotFoundException, ParseException {
         schemaContextYangsIetf = TestUtils.loadSchemaContext("/full-versions/yangs");
         schemaContextTestModule = TestUtils.loadSchemaContext("/full-versions/test-module");
         ControllerContext controllerContext = ControllerContext.getInstance();
@@ -110,7 +112,7 @@ public class RestGetOperationTest extends JerseyTest {
         restconfImpl = RestconfImpl.getInstance();
         restconfImpl.setBroker(brokerFacade);
         restconfImpl.setControllerContext(controllerContext);
-        answerFromGet = prepareCompositeNodeWithIetfInterfacesInterfacesData();
+        answerFromGet = TestUtils.prepareNormalizedNodeWithIetfInterfacesInterfacesData();
 
         schemaContextModules = TestUtils.loadSchemaContext("/modules");
         schemaContextBehindMountPoint = TestUtils.loadSchemaContext("/modules/modules-behind-mount-point");
@@ -161,14 +163,13 @@ public class RestGetOperationTest extends JerseyTest {
      * MountPoint test. URI represents mount point.
      */
     @Test
-    public void getDataWithUrlMountPoint() throws UnsupportedEncodingException, URISyntaxException {
-        when(
-                brokerFacade.readConfigurationDataBehindMountPoint(any(MountInstance.class),
-                        any(YangInstanceIdentifier.class))).thenReturn(prepareCnDataForMountPointTest());
-        MountInstance mountInstance = mock(MountInstance.class);
+    public void getDataWithUrlMountPoint() throws UnsupportedEncodingException, URISyntaxException, ParseException {
+        when(brokerFacade.readConfigurationData(any(DOMMountPoint.class), any(YangInstanceIdentifier.class))).thenReturn(
+                prepareCnDataForMountPointTest(false));
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
@@ -188,20 +189,18 @@ public class RestGetOperationTest extends JerseyTest {
      * {@link BrokerFacade#readConfigurationDataBehindMountPoint(MountInstance, YangInstanceIdentifier)} which is called in
      * method {@link RestconfImpl#readConfigurationData}
      *
-     *
      * @throws ParseException
      */
     @Test
     public void getDataWithSlashesBehindMountPoint() throws UnsupportedEncodingException, URISyntaxException,
             ParseException {
         YangInstanceIdentifier awaitedInstanceIdentifier = prepareInstanceIdentifierForList();
-        when(
-                brokerFacade.readConfigurationDataBehindMountPoint(any(MountInstance.class),
-                        eq(awaitedInstanceIdentifier))).thenReturn(prepareCnDataForMountPointTest());
-        MountInstance mountInstance = mock(MountInstance.class);
+        when(brokerFacade.readConfigurationData(any(DOMMountPoint.class), eq(awaitedInstanceIdentifier))).thenReturn(
+                prepareCnDataForSlashesBehindMountPointTest());
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
@@ -219,24 +218,25 @@ public class RestGetOperationTest extends JerseyTest {
         QName qNameKeyList = QName.create(uri, revision, "lf11");
 
         parameters.add(new YangInstanceIdentifier.NodeIdentifier(qNameCont));
+        parameters.add(new YangInstanceIdentifier.NodeIdentifier(qNameList));
         parameters.add(new YangInstanceIdentifier.NodeIdentifierWithPredicates(qNameList, qNameKeyList,
                 "GigabitEthernet0/0/0/0"));
         return YangInstanceIdentifier.create(parameters);
     }
 
     @Test
-    public void getDataMountPointIntoHighestElement() throws UnsupportedEncodingException, URISyntaxException {
-        when(
-                brokerFacade.readConfigurationDataBehindMountPoint(any(MountInstance.class),
-                        any(YangInstanceIdentifier.class))).thenReturn(prepareCnDataForMountPointTest());
-        MountInstance mountInstance = mock(MountInstance.class);
+    public void getDataMountPointIntoHighestElement() throws UnsupportedEncodingException, URISyntaxException,
+            ParseException {
+        when(brokerFacade.readConfigurationData(any(DOMMountPoint.class), any(YangInstanceIdentifier.class))).thenReturn(
+                prepareCnDataForMountPointTest(true));
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -361,10 +361,10 @@ public class RestGetOperationTest extends JerseyTest {
         ControllerContext controllerContext = ControllerContext.getInstance();
         controllerContext.setGlobalSchema(schemaContextModules);
 
-        MountInstance mountInstance = mock(MountInstance.class);
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextBehindMountPoint);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         controllerContext.setMountService(mockMountService);
 
@@ -450,10 +450,10 @@ public class RestGetOperationTest extends JerseyTest {
         ControllerContext controllerContext = ControllerContext.getInstance();
         controllerContext.setGlobalSchema(schemaContextModules);
 
-        MountInstance mountInstance = mock(MountInstance.class);
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextBehindMountPoint);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         controllerContext.setMountService(mockMountService);
 
@@ -484,10 +484,10 @@ public class RestGetOperationTest extends JerseyTest {
         ControllerContext controllerContext = ControllerContext.getInstance();
         controllerContext.setGlobalSchema(schemaContextModules);
 
-        MountInstance mountInstance = mock(MountInstance.class);
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextBehindMountPoint);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         controllerContext.setMountService(mockMountService);
 
@@ -636,11 +636,30 @@ public class RestGetOperationTest extends JerseyTest {
         return target(uri).request(mediaType).get().getStatus();
     }
 
-    private CompositeNode prepareCnDataForMountPointTest() throws URISyntaxException {
-        CompositeNodeWrapper cont1 = new CompositeNodeWrapper(new URI("test:module"), "cont1");
-        SimpleNodeWrapper lf11 = new SimpleNodeWrapper(new URI("test:module"), "lf11", "lf11 value");
-        cont1.addValue(lf11);
-        return cont1.unwrap();
+    /**
+    container cont {
+        container cont1 {
+            leaf lf11 {
+                type string;
+            }
+    */
+    private NormalizedNode prepareCnDataForMountPointTest(boolean wrapToCont) throws URISyntaxException, ParseException {
+        String testModuleDate = "2014-01-09";
+        ContainerNode contChild = Builders
+                .containerBuilder()
+                .withNodeIdentifier(TestUtils.getNodeIdentifier("cont1", "test:module", testModuleDate))
+                .withChild(
+                        Builders.leafBuilder()
+                                .withNodeIdentifier(TestUtils.getNodeIdentifier("lf11", "test:module", testModuleDate))
+                                .withValue("lf11 value").build()).build();
+
+        if (wrapToCont) {
+            return Builders.containerBuilder()
+                    .withNodeIdentifier(TestUtils.getNodeIdentifier("cont", "test:module", testModuleDate))
+                    .withChild(contChild).build();
+        }
+        return contChild;
+
     }
 
     private void mockReadOperationalDataMethod() {
@@ -651,22 +670,17 @@ public class RestGetOperationTest extends JerseyTest {
         when(brokerFacade.readConfigurationData(any(YangInstanceIdentifier.class))).thenReturn(answerFromGet);
     }
 
-    private static CompositeNode prepareCompositeNodeWithIetfInterfacesInterfacesData() {
-        CompositeNode intface;
-        try {
-            intface = new CompositeNodeWrapper(new URI("interface"), "interface");
-            List<Node<?>> childs = new ArrayList<>();
-
-            childs.add(new SimpleNodeWrapper(new URI("name"), "name", "eth0"));
-            childs.add(new SimpleNodeWrapper(new URI("type"), "type", "ethernetCsmacd"));
-            childs.add(new SimpleNodeWrapper(new URI("enabled"), "enabled", Boolean.FALSE));
-            childs.add(new SimpleNodeWrapper(new URI("description"), "description", "some interface"));
-            intface.setValue(childs);
-            return intface;
-        } catch (URISyntaxException e) {
-        }
+    private NormalizedNode prepareCnDataForSlashesBehindMountPointTest() throws ParseException {
+        return ImmutableMapEntryNodeBuilder
+                .create()
+                .withNodeIdentifier(
+                        TestUtils.getNodeIdentifierPredicate("lst1", "test:module", "2014-01-09", "lf11",
+                                "GigabitEthernet0/0/0/0"))
+                .withChild(
+                        ImmutableLeafNodeBuilder.create()
+                                .withNodeIdentifier(TestUtils.getNodeIdentifier("lf11", "test:module", "2014-01-09"))
+                                .withValue("GigabitEthernet0/0/0/0").build()).build();
 
-        return null;
     }
 
     /**
@@ -682,6 +696,7 @@ public class RestGetOperationTest extends JerseyTest {
 
     private void getDataWithUriIncludeWhiteCharsParameter(final String target) throws UnsupportedEncodingException {
         mockReadConfigurationDataMethod();
+        mockReadOperationalDataMethod();
         String uri = "/" + target + "/ietf-interfaces:interfaces/interface/eth0";
         Response response = target(uri).queryParam("prettyPrint", "false").request("application/xml").get();
         String xmlData = response.readEntity(String.class);
@@ -726,7 +741,14 @@ public class RestGetOperationTest extends JerseyTest {
                         toSimpleNodeData(toNestedQName("depth3-leaf2"), "depth3-leaf2-value")),
                 toSimpleNodeData(toNestedQName("depth2-leaf1"), "depth2-leaf1-value")));
 
-        when(brokerFacade.readConfigurationData(any(YangInstanceIdentifier.class))).thenReturn(depth1Cont);
+        Module module = TestUtils.findModule(schemaContextModules.getModules(), "nested-module");
+        assertNotNull(module);
+
+        DataSchemaNode dataSchemaNode = TestUtils.resolveDataSchemaNode("depth1-cont", module);
+        assertNotNull(dataSchemaNode);
+
+        when(brokerFacade.readConfigurationData(any(YangInstanceIdentifier.class))).thenReturn(
+                TestUtils.compositeNodeToDatastoreNormalizedNode(depth1Cont, dataSchemaNode));
 
         // Test config with depth 1
 
@@ -852,7 +874,18 @@ public class RestGetOperationTest extends JerseyTest {
                         toSimpleNodeData(toNestedQName("depth4-leaf1"), "depth4-leaf1-value")),
                 toSimpleNodeData(toNestedQName("depth3-leaf1"), "depth3-leaf1-value")));
 
-        when(brokerFacade.readOperationalData(any(YangInstanceIdentifier.class))).thenReturn(depth2Cont1);
+        assertTrue(dataSchemaNode instanceof DataNodeContainer);
+        DataSchemaNode depth2cont1Schema = null;
+        for (DataSchemaNode childNode : ((DataNodeContainer) dataSchemaNode).getChildNodes()) {
+            if (childNode.getQName().getLocalName().equals("depth2-cont1")) {
+                depth2cont1Schema = childNode;
+                break;
+            }
+        }
+        assertNotNull(depth2Cont1);
+
+        when(brokerFacade.readOperationalData(any(YangInstanceIdentifier.class))).thenReturn(
+                TestUtils.compositeNodeToDatastoreNormalizedNode(depth2Cont1, depth2cont1Schema));
 
         response = target("/operational/nested-module:depth1-cont/depth2-cont1").queryParam("depth", "3")
                 .request("application/xml").get();
@@ -866,6 +899,9 @@ public class RestGetOperationTest extends JerseyTest {
                         expectLeaf("depth3-leaf1", "depth3-leaf1-value")));
     }
 
+    /**
+     * Tests behavior when invalid value of depth URI parameter
+     */
     @Test
     public void getDataWithInvalidDepthParameterTest() {
 
@@ -876,7 +912,7 @@ public class RestGetOperationTest extends JerseyTest {
         UriInfo mockInfo = mock(UriInfo.class);
         when(mockInfo.getQueryParameters(false)).thenAnswer(new Answer<MultivaluedMap<String, String>>() {
             @Override
-            public MultivaluedMap<String, String> answer(final InvocationOnMock invocation) {
+            public MultivaluedMap<String, String> answer(InvocationOnMock invocation) {
                 return paramMap;
             }
         });
@@ -892,6 +928,10 @@ public class RestGetOperationTest extends JerseyTest {
 
     private void getDataWithInvalidDepthParameterTest(final UriInfo uriInfo) {
         try {
+            QName qNameDepth1Cont = QName.create("urn:nested:module", "2014-06-3", "depth1-cont");
+            YangInstanceIdentifier ii = YangInstanceIdentifier.builder().node(qNameDepth1Cont).build();
+            NormalizedNode value = (NormalizedNode<?,?>)(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(qNameDepth1Cont)).build());
+            when(brokerFacade.readConfigurationData(eq(ii))).thenReturn(value);
             restconfImpl.readConfigurationData("nested-module:depth1-cont", uriInfo);
             fail("Expected RestconfDocumentedException");
         } catch (RestconfDocumentedException e) {
@@ -901,8 +941,9 @@ public class RestGetOperationTest extends JerseyTest {
     }
 
     private void verifyXMLResponse(final Response response, final NodeData nodeData) {
-
-        Document doc = TestUtils.loadDocumentFrom((InputStream) response.getEntity());
+        Document doc = response.readEntity(Document.class);
+//        Document doc = TestUtils.loadDocumentFrom((InputStream) response.getEntity());
+//        System.out.println();
         assertNotNull("Could not parse XML document", doc);
 
         // System.out.println(TestUtils.getDocumentInPrintableForm( doc ));
@@ -913,11 +954,11 @@ public class RestGetOperationTest extends JerseyTest {
     @SuppressWarnings("unchecked")
     private void verifyContainerElement(final Element element, final NodeData nodeData) {
 
-        assertEquals("Element local name", nodeData.key, element.getNodeName());
+        assertEquals("Element local name", nodeData.key, element.getLocalName());
 
         NodeList childNodes = element.getChildNodes();
         if (nodeData.data == null) { // empty container
-            assertTrue("Expected no child elements for \"" + element.getNodeName() + "\"", childNodes.getLength() == 0);
+            assertTrue("Expected no child elements for \"" + element.getLocalName() + "\"", childNodes.getLength() == 0);
             return;
         }
 
@@ -933,21 +974,21 @@ public class RestGetOperationTest extends JerseyTest {
             }
 
             Element actualElement = (Element) actualChild;
-            NodeData expChild = expChildMap.remove(actualElement.getNodeName());
+            NodeData expChild = expChildMap.remove(actualElement.getLocalName());
             assertNotNull(
-                    "Unexpected child element for parent \"" + element.getNodeName() + "\": "
-                            + actualElement.getNodeName(), expChild);
+                    "Unexpected child element for parent \"" + element.getLocalName() + "\": "
+                            + actualElement.getLocalName(), expChild);
 
             if (expChild.data == null || expChild.data instanceof List) {
                 verifyContainerElement(actualElement, expChild);
             } else {
-                assertEquals("Text content for element: " + actualElement.getNodeName(), expChild.data,
+                assertEquals("Text content for element: " + actualElement.getLocalName(), expChild.data,
                         actualElement.getTextContent());
             }
         }
 
         if (!expChildMap.isEmpty()) {
-            fail("Missing elements for parent \"" + element.getNodeName() + "\": " + expChildMap.keySet());
+            fail("Missing elements for parent \"" + element.getLocalName() + "\": " + expChildMap.keySet());
         }
     }
 
@@ -990,4 +1031,5 @@ public class RestGetOperationTest extends JerseyTest {
     private NodeData toSimpleNodeData(final QName key, final Object value) {
         return new NodeData(key, value);
     }
+
 }
index 979b58b78a184aacc28ceb82f7bd44f7f3315100..97cd67d34b70095a1571c1384e4a0e46c61f155a 100644 (file)
@@ -9,12 +9,16 @@ package org.opendaylight.controller.sal.restconf.impl.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 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.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,7 +31,6 @@ 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;
@@ -37,8 +40,8 @@ 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.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
@@ -48,14 +51,16 @@ import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 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.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -77,7 +82,7 @@ public class RestPostOperationTest extends JerseyTest {
     private static SchemaContext schemaContextTestModule;
     private static SchemaContext schemaContext;
 
-    private static MountService mountService;
+    private static DOMMountPointService mountService;
 
     @BeforeClass
     public static void init() throws URISyntaxException, IOException {
@@ -124,10 +129,9 @@ public class RestPostOperationTest extends JerseyTest {
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
         List<RpcError> rpcErrors = new ArrayList<>();
-        rpcErrors.add( RpcResultBuilder.newError( ErrorType.RPC, "tag1", "message1",
-                                                  "applicationTag1", "info1", null ) );
-        rpcErrors.add( RpcResultBuilder.newWarning( ErrorType.PROTOCOL, "tag2", "message2",
-                                                    "applicationTag2", "info2", null ) );
+        rpcErrors.add(RpcResultBuilder.newError(ErrorType.RPC, "tag1", "message1", "applicationTag1", "info1", null));
+        rpcErrors.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "tag2", "message2", "applicationTag2", "info2",
+                null));
         mockInvokeRpc(null, false, rpcErrors);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
@@ -138,28 +142,25 @@ public class RestPostOperationTest extends JerseyTest {
     @Test
     public void postConfigOnlyStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextYangsIetf);
-        mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
         String uri = "/config";
+        mockCommitConfigurationDataPostMethod(true);
         assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataAbsolutePath));
 
-        mockCommitConfigurationDataPostMethod(null);
-        assertEquals(202, post(uri, MediaType.APPLICATION_XML, xmlDataAbsolutePath));
-
-        mockCommitConfigurationDataPostMethod(TransactionStatus.FAILED);
+        mockCommitConfigurationDataPostMethod(false);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataAbsolutePath));
+
+        assertEquals(400, post(uri, MediaType.APPLICATION_XML, ""));
     }
 
     @Test
     public void postConfigStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextYangsIetf);
-        mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
         String uri = "/config/ietf-interfaces:interfaces";
-        assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
 
-        mockCommitConfigurationDataPostMethod(null);
-        assertEquals(202, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
+        mockCommitConfigurationDataPostMethod(true);
+        assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
 
-        mockCommitConfigurationDataPostMethod(TransactionStatus.FAILED);
+        mockCommitConfigurationDataPostMethod(false);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
 
         assertEquals(400, post(uri, MediaType.APPLICATION_JSON, ""));
@@ -168,18 +169,14 @@ public class RestPostOperationTest extends JerseyTest {
     @Test
     public void postDataViaUrlMountPoint() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextYangsIetf);
-        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
-                TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
-                rpcResult).build();
         when(
-                brokerFacade.commitConfigurationDataPostBehindMountPoint(any(MountInstance.class),
-                        any(YangInstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
+                brokerFacade.commitConfigurationDataPost(any(DOMMountPoint.class), any(YangInstanceIdentifier.class),
+                        any(NormalizedNode.class))).thenReturn(mock(CheckedFuture.class));
 
-        MountInstance mountInstance = mock(MountInstance.class);
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
@@ -207,18 +204,13 @@ public class RestPostOperationTest extends JerseyTest {
         mockInvokeRpc(result, sucessful, Collections.<RpcError> emptyList());
     }
 
-    private void mockCommitConfigurationDataPostMethod(TransactionStatus statusName) {
-        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(statusName)
-                .build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = null;
-        if (statusName != null) {
-            dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(rpcResult).build();
+    private void mockCommitConfigurationDataPostMethod(final boolean succesfulComit) {
+        if (succesfulComit) {
+            doReturn(mock(CheckedFuture.class)).when(brokerFacade).commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(NormalizedNode.class));
         } else {
-            dummyFuture = new DummyFuture.Builder<TransactionStatus>().build();
+            doThrow(RestconfDocumentedException.class).when(brokerFacade).commitConfigurationDataPost(
+                    any(YangInstanceIdentifier.class), any(NormalizedNode.class));
         }
-
-        when(brokerFacade.commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(CompositeNode.class)))
-                .thenReturn(dummyFuture);
     }
 
     @Test
@@ -226,14 +218,12 @@ public class RestPostOperationTest extends JerseyTest {
         initMocking();
         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
                 TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
-                rpcResult).build();
 
-        when(brokerFacade.commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(CompositeNode.class)))
-                .thenReturn(dummyFuture);
+        when(brokerFacade.commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(NormalizedNode.class)))
+                .thenReturn(mock(CheckedFuture.class));
 
         ArgumentCaptor<YangInstanceIdentifier> instanceIdCaptor = ArgumentCaptor.forClass(YangInstanceIdentifier.class);
-        ArgumentCaptor<CompositeNode> compNodeCaptor = ArgumentCaptor.forClass(CompositeNode.class);
+        ArgumentCaptor<NormalizedNode> compNodeCaptor = ArgumentCaptor.forClass(NormalizedNode.class);
 
         String URI_1 = "/config";
         assertEquals(204, post(URI_1, Draft02.MediaTypes.DATA + XML, xmlTestInterface));
@@ -253,20 +243,20 @@ public class RestPostOperationTest extends JerseyTest {
     public void createConfigurationDataNullTest() throws UnsupportedEncodingException {
         initMocking();
 
-        when(brokerFacade.commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(CompositeNode.class)))
+        when(brokerFacade.commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(NormalizedNode.class)))
                 .thenReturn(null);
 
         String URI_1 = "/config";
-        assertEquals(202, post(URI_1, Draft02.MediaTypes.DATA + XML, xmlTestInterface));
+        assertEquals(204, post(URI_1, Draft02.MediaTypes.DATA + XML, xmlTestInterface));
 
         String URI_2 = "/config/test-interface:interfaces";
-        assertEquals(202, post(URI_2, Draft02.MediaTypes.DATA + XML, xmlBlockData));
+        assertEquals(204, post(URI_2, Draft02.MediaTypes.DATA + XML, xmlBlockData));
     }
 
     private static void initMocking() {
         controllerContext = ControllerContext.getInstance();
         controllerContext.setSchemas(schemaContext);
-        mountService = mock(MountService.class);
+        mountService = mock(DOMMountPointService.class);
         controllerContext.setMountService(mountService);
         brokerFacade = mock(BrokerFacade.class);
         restconfImpl = RestconfImpl.getInstance();
index 5d837f42bd27dd58233aaed07546f1b2fb5e2f06..3284546dcbb32806563b2bb8b0959d7a3063a10d 100644 (file)
@@ -9,15 +9,18 @@ package org.opendaylight.controller.sal.restconf.impl.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 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;
@@ -26,9 +29,9 @@ import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
@@ -36,10 +39,10 @@ import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 public class RestPutOperationTest extends JerseyTest {
@@ -96,10 +99,10 @@ public class RestPutOperationTest extends JerseyTest {
     @Test
     public void putConfigStatusCodes() throws UnsupportedEncodingException {
         String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
-        mockCommitConfigurationDataPutMethod(TransactionStatus.COMMITED);
+        mockCommitConfigurationDataPutMethod(true);
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData));
 
-        mockCommitConfigurationDataPutMethod(TransactionStatus.FAILED);
+        mockCommitConfigurationDataPutMethod(false);
         assertEquals(500, put(uri, MediaType.APPLICATION_XML, xmlData));
 
         assertEquals(400, put(uri, MediaType.APPLICATION_JSON, ""));
@@ -117,18 +120,16 @@ public class RestPutOperationTest extends JerseyTest {
     public void testRpcResultCommitedToStatusCodesWithMountPoint() throws UnsupportedEncodingException,
             FileNotFoundException, URISyntaxException {
 
-        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
-                TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
-                rpcResult).build();
+        CheckedFuture<Void, TransactionCommitFailedException> dummyFuture = mock(CheckedFuture.class);
+
         when(
-                brokerFacade.commitConfigurationDataPutBehindMountPoint(any(MountInstance.class),
-                        any(YangInstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
+                brokerFacade.commitConfigurationDataPut(any(DOMMountPoint.class), any(YangInstanceIdentifier.class),
+                        any(NormalizedNode.class))).thenReturn(dummyFuture);
 
-        MountInstance mountInstance = mock(MountInstance.class);
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
@@ -141,18 +142,15 @@ public class RestPutOperationTest extends JerseyTest {
 
     @Test
     public void putDataMountPointIntoHighestElement() throws UnsupportedEncodingException, URISyntaxException {
-        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(
-                TransactionStatus.COMMITED).build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
-                rpcResult).build();
+        CheckedFuture<Void, TransactionCommitFailedException> dummyFuture = mock(CheckedFuture.class);
         when(
-                brokerFacade.commitConfigurationDataPutBehindMountPoint(any(MountInstance.class),
-                        any(YangInstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
+                brokerFacade.commitConfigurationDataPut(any(DOMMountPoint.class), any(YangInstanceIdentifier.class),
+                        any(NormalizedNode.class))).thenReturn(dummyFuture);
 
-        MountInstance mountInstance = mock(MountInstance.class);
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
-        MountService mockMountService = mock(MountService.class);
-        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        DOMMountPointService mockMountService = mock(DOMMountPointService.class);
+        when(mockMountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
@@ -164,13 +162,14 @@ public class RestPutOperationTest extends JerseyTest {
         return target(uri).request(mediaType).put(Entity.entity(data, mediaType)).getStatus();
     }
 
-    private void mockCommitConfigurationDataPutMethod(TransactionStatus statusName) {
-        RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(statusName)
-                .build();
-        Future<RpcResult<TransactionStatus>> dummyFuture = new DummyFuture.Builder<TransactionStatus>().rpcResult(
-                rpcResult).build();
-        when(brokerFacade.commitConfigurationDataPut(any(YangInstanceIdentifier.class), any(CompositeNode.class)))
-                .thenReturn(dummyFuture);
+    private void mockCommitConfigurationDataPutMethod(final boolean noErrors) {
+        if (noErrors) {
+            doReturn(mock(CheckedFuture.class)).when(brokerFacade).commitConfigurationDataPut(
+                    any(YangInstanceIdentifier.class), any(NormalizedNode.class));
+        } else {
+            doThrow(RestconfDocumentedException.class).when(brokerFacade).commitConfigurationDataPut(
+                    any(YangInstanceIdentifier.class), any(NormalizedNode.class));
+        }
     }
 
 }
index 236712b45499a70df1b1e69b7c19e3d094dc561b..906695b3aab9fbad4c7b38fc2fd30db95c7d2037 100644 (file)
@@ -15,16 +15,16 @@ import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import java.io.FileNotFoundException;
+import java.text.ParseException;
 import java.util.Set;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -54,12 +54,12 @@ public class RestconfImplTest {
     }
 
     @Test
-    public void testExample() throws FileNotFoundException {
-        CompositeNode loadedCompositeNode = TestUtils.readInputToCnSn("/parts/ietf-interfaces_interfaces.xml",
-                XmlToCompositeNodeProvider.INSTANCE);
+    public void testExample() throws FileNotFoundException, ParseException {
+        NormalizedNode normalizedNodeData = TestUtils.prepareNormalizedNodeWithIetfInterfacesInterfacesData();
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
-        when(brokerFacade.readOperationalData(any(YangInstanceIdentifier.class))).thenReturn(loadedCompositeNode);
-        assertEquals(loadedCompositeNode, brokerFacade.readOperationalData(null));
+        when(brokerFacade.readOperationalData(any(YangInstanceIdentifier.class))).thenReturn(normalizedNodeData);
+        assertEquals(normalizedNodeData,
+                brokerFacade.readOperationalData(null));
     }
 
 }
index 67d98f6b558db0a0915928ff869d2a0f123a5b45..c2b153f02bd27b6729dbba2a89a201a306763a99 100644 (file)
@@ -14,6 +14,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -25,8 +26,12 @@ import java.io.OutputStreamWriter;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.sql.Date;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -42,20 +47,34 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+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.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,7 +85,7 @@ public final class TestUtils {
 
     private static final Logger LOG = LoggerFactory.getLogger(TestUtils.class);
 
-    private final static YangModelParser parser = new YangParserImpl();
+    private final static YangContextParser parser = new YangParserImpl();
 
     private static Set<Module> loadModules(String resourceDirectory) throws FileNotFoundException {
         final File testDir = new File(resourceDirectory);
@@ -151,12 +170,12 @@ public final class TestUtils {
      * {@code dataSchemaNode}. The method {@link RestconfImpl#createConfigurationData createConfigurationData} is used
      * because it contains calling of method {code normalizeNode}
      */
-    public static void normalizeCompositeNode(CompositeNode compositeNode, Set<Module> modules, String schemaNodePath) {
+    public static void normalizeCompositeNode(Node<?> node, Set<Module> modules, String schemaNodePath) {
         RestconfImpl restconf = RestconfImpl.getInstance();
         ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext(modules));
 
         prepareMocksForRestconf(modules, restconf);
-        restconf.updateConfigurationData(schemaNodePath, compositeNode);
+        restconf.updateConfigurationData(schemaNodePath, node);
     }
 
     /**
@@ -229,33 +248,30 @@ public final class TestUtils {
 
         controllerContext.setSchemas(TestUtils.loadSchemaContext(modules));
 
-        when(mockedBrokerFacade.commitConfigurationDataPut(any(YangInstanceIdentifier.class), any(CompositeNode.class)))
-                .thenReturn(
-                        new DummyFuture.Builder().rpcResult(
-                                new DummyRpcResult.Builder<TransactionStatus>().result(TransactionStatus.COMMITED)
-                                        .build()).build());
+        when(mockedBrokerFacade.commitConfigurationDataPut(any(YangInstanceIdentifier.class), any(NormalizedNode.class)))
+                .thenReturn(mock(CheckedFuture.class));
 
         restconf.setControllerContext(controllerContext);
         restconf.setBroker(mockedBrokerFacade);
     }
 
-    public static CompositeNode readInputToCnSn(String path, boolean dummyNamespaces,
-            MessageBodyReader<CompositeNode> reader) throws WebApplicationException {
+    public static Node<?> readInputToCnSn(String path, boolean dummyNamespaces,
+            MessageBodyReader<Node<?>> reader) throws WebApplicationException {
 
         InputStream inputStream = TestUtils.class.getResourceAsStream(path);
         try {
-            CompositeNode compositeNode = reader.readFrom(null, null, null, null, null, inputStream);
-            assertTrue(compositeNode instanceof CompositeNodeWrapper);
+            final Node<?> node = reader.readFrom(null, null, null, null, null, inputStream);
+            assertTrue(node instanceof CompositeNodeWrapper);
             if (dummyNamespaces) {
                 try {
-                    TestUtils.addDummyNamespaceToAllNodes((CompositeNodeWrapper) compositeNode);
-                    return ((CompositeNodeWrapper) compositeNode).unwrap();
+                    TestUtils.addDummyNamespaceToAllNodes((CompositeNodeWrapper) node);
+                    return ((CompositeNodeWrapper) node).unwrap();
                 } catch (URISyntaxException e) {
                     LOG.error(e.getMessage());
                     assertTrue(e.getMessage(), false);
                 }
             }
-            return compositeNode;
+            return node;
         } catch (IOException e) {
             LOG.error(e.getMessage());
             assertTrue(e.getMessage(), false);
@@ -263,21 +279,33 @@ public final class TestUtils {
         return null;
     }
 
-    public static CompositeNode readInputToCnSn(String path, MessageBodyReader<CompositeNode> reader) {
+//    public static Node<?> readInputToCnSnNew(String path, MessageBodyReader<Node<?>> reader) throws WebApplicationException {
+//        InputStream inputStream = TestUtils.class.getResourceAsStream(path);
+//        try {
+//            return reader.readFrom(null, null, null, null, null, inputStream);
+//        } catch (IOException e) {
+//            LOG.error(e.getMessage());
+//            assertTrue(e.getMessage(), false);
+//        }
+//        return null;
+//    }
+
+    public static Node<?> readInputToCnSn(String path, MessageBodyReader<Node<?>> reader) {
         return readInputToCnSn(path, false, reader);
     }
 
-    public static String writeCompNodeWithSchemaContextToOutput(CompositeNode compositeNode, Set<Module> modules,
+    public static String writeCompNodeWithSchemaContextToOutput(Node<?> node, Set<Module> modules,
             DataSchemaNode dataSchemaNode, MessageBodyWriter<StructuredData> messageBodyWriter) throws IOException,
             WebApplicationException {
 
         assertNotNull(dataSchemaNode);
-        assertNotNull("Composite node can't be null", compositeNode);
+        assertNotNull("Composite node can't be null", node);
         ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
 
         ControllerContext.getInstance().setSchemas(loadSchemaContext(modules));
 
-        messageBodyWriter.writeTo(new StructuredData(compositeNode, dataSchemaNode, null), null, null, null, null,
+        assertTrue(node instanceof CompositeNode);
+        messageBodyWriter.writeTo(new StructuredData((CompositeNode)node, dataSchemaNode, null), null, null, null, null,
                 null, byteArrayOS);
 
         return byteArrayOS.toString();
@@ -312,4 +340,92 @@ public final class TestUtils {
         Matcher matcher = pattern.matcher(jsonOutput);
         return matcher.matches();
     }
+
+    public static NormalizedNode compositeNodeToDatastoreNormalizedNode(final CompositeNode compositeNode,
+            final DataSchemaNode schema) {
+        List<Node<?>> lst = new ArrayList<Node<?>>();
+        lst.add(compositeNode);
+        if (schema instanceof ContainerSchemaNode) {
+            return CnSnToNormalizedNodeParserFactory.getInstance().getContainerNodeParser()
+                    .parse(lst, (ContainerSchemaNode) schema);
+        } else if (schema instanceof ListSchemaNode) {
+            return CnSnToNormalizedNodeParserFactory.getInstance().getMapNodeParser()
+                    .parse(lst, (ListSchemaNode) schema);
+        }
+
+        LOG.error("Top level isn't of type container, list, leaf schema node but " + schema.getClass().getSimpleName());
+
+        throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+                "It wasn't possible to translate specified data to datastore readable form."));
+    }
+
+    public static YangInstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName, String namespace,
+            String revision) throws ParseException {
+        return new YangInstanceIdentifier.NodeIdentifier(QName.create(namespace, revision, localName));
+    }
+
+    public static YangInstanceIdentifier.NodeIdentifierWithPredicates getNodeIdentifierPredicate(String localName,
+            String namespace, String revision, Map<String, Object> keys) throws ParseException {
+        Map<QName, Object> predicate = new HashMap<>();
+        for (String key : keys.keySet()) {
+            predicate.put(QName.create(namespace, revision, key), keys.get(key));
+        }
+
+        return new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+
+        QName.create(namespace, revision, localName), predicate);
+    }
+
+    public static YangInstanceIdentifier.NodeIdentifierWithPredicates getNodeIdentifierPredicate(String localName,
+            String namespace, String revision, String... keysAndValues) throws ParseException {
+        java.util.Date date = new SimpleDateFormat("yyyy-MM-dd").parse(revision);
+        if (keysAndValues.length % 2 != 0) {
+            new IllegalArgumentException("number of keys argument have to be divisible by 2 (map)");
+        }
+        Map<QName, Object> predicate = new HashMap<>();
+
+        int i = 0;
+        while (i < keysAndValues.length) {
+            predicate.put(QName.create(namespace, revision, keysAndValues[i++]), keysAndValues[i++]);
+        }
+
+        return new YangInstanceIdentifier.NodeIdentifierWithPredicates(QName.create(namespace, revision, localName),
+                predicate);
+    }
+
+    public static CompositeNode prepareCompositeNodeWithIetfInterfacesInterfacesData() {
+        CompositeNodeBuilder<ImmutableCompositeNode> interfaceBuilder = ImmutableCompositeNode.builder();
+        interfaceBuilder.addLeaf(buildQName("name", "dummy", "2014-07-29"), "eth0");
+        interfaceBuilder.addLeaf(buildQName("type", "dummy", "2014-07-29"), "ethernetCsmacd");
+        interfaceBuilder.addLeaf(buildQName("enabled", "dummy", "2014-07-29"), "false");
+        interfaceBuilder.addLeaf(buildQName("description", "dummy", "2014-07-29"), "some interface");
+        return interfaceBuilder.toInstance();
+    }
+
+    static NormalizedNode prepareNormalizedNodeWithIetfInterfacesInterfacesData() throws ParseException {
+        String ietfInterfacesDate = "2013-07-04";
+        String namespace = "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+        DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryNode = ImmutableMapEntryNodeBuilder.create();
+
+        Map<String, Object> predicates = new HashMap<>();
+        predicates.put("name", "eth0");
+
+        mapEntryNode.withNodeIdentifier(getNodeIdentifierPredicate("interface", namespace, ietfInterfacesDate,
+                predicates));
+        mapEntryNode
+                .withChild(new ImmutableLeafNodeBuilder<String>()
+                        .withNodeIdentifier(getNodeIdentifier("name", namespace, ietfInterfacesDate)).withValue("eth0")
+                        .build());
+        mapEntryNode.withChild(new ImmutableLeafNodeBuilder<String>()
+                .withNodeIdentifier(getNodeIdentifier("type", namespace, ietfInterfacesDate))
+                .withValue("ethernetCsmacd").build());
+        mapEntryNode.withChild(new ImmutableLeafNodeBuilder<Boolean>()
+                .withNodeIdentifier(getNodeIdentifier("enabled", namespace, ietfInterfacesDate))
+                .withValue(Boolean.FALSE).build());
+        mapEntryNode.withChild(new ImmutableLeafNodeBuilder<String>()
+                .withNodeIdentifier(getNodeIdentifier("description", namespace, ietfInterfacesDate))
+                .withValue("some interface").build());
+
+        return mapEntryNode.build();
+    }
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/URIParametersParsing.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/URIParametersParsing.java
new file mode 100644 (file)
index 0000000..3c954f8
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.FileNotFoundException;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import org.junit.Before;
+import org.junit.Test;
+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.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
+import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
+import org.opendaylight.controller.sal.streams.listeners.Notificator;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+
+public class URIParametersParsing {
+
+    private RestconfImpl restconf;
+    private BrokerFacade mockedBrokerFacade;
+
+    @Before
+    public void init() throws FileNotFoundException {
+        restconf = RestconfImpl.getInstance();
+        mockedBrokerFacade = mock(BrokerFacade.class);
+        ControllerContext controllerContext = ControllerContext.getInstance();
+        controllerContext.setSchemas(TestUtils.loadSchemaContext("/datastore-and-scope-specification"));
+        restconf.setControllerContext(controllerContext);
+        restconf.setBroker(mockedBrokerFacade);
+    }
+
+    @Test
+    public void resolveURIParametersConcreteValues() {
+        resolveURIParameters("OPERATIONAL", "SUBTREE", LogicalDatastoreType.OPERATIONAL, DataChangeScope.SUBTREE);
+    }
+
+    @Test
+    public void resolveURIParametersDefaultValues() {
+        resolveURIParameters(null, null, LogicalDatastoreType.CONFIGURATION, DataChangeScope.BASE);
+    }
+
+    private void resolveURIParameters(final String datastore, final String scope,
+            final LogicalDatastoreType datastoreExpected, final DataChangeScope scopeExpected) {
+
+        InstanceIdentifierBuilder iiBuilder = YangInstanceIdentifier.builder();
+        iiBuilder.node(QName.create("dummyStreamName"));
+
+        final String datastoreValue = datastore == null ? "CONFIGURATION" : datastore;
+        final String scopeValue = scope == null ? "BASE" : scope + "";
+        Notificator.createListener(iiBuilder.build(), "dummyStreamName/datastore=" + datastoreValue + "/scope="
+                + scopeValue);
+
+        UriInfo mockedUriInfo = mock(UriInfo.class);
+        MultivaluedMap<String, String> mockedMultivaluedMap = mock(MultivaluedMap.class);
+        when(mockedMultivaluedMap.getFirst(eq("datastore"))).thenReturn(datastoreValue);
+        when(mockedMultivaluedMap.getFirst(eq("scope"))).thenReturn(scopeValue);
+
+        when(mockedUriInfo.getQueryParameters(eq(false))).thenReturn(mockedMultivaluedMap);
+
+         UriBuilder uriBuilder = UriBuilder.fromUri("www.whatever.com");
+         when(mockedUriInfo.getAbsolutePathBuilder()).thenReturn(uriBuilder);
+
+        restconf.invokeRpc("sal-remote:create-data-change-event-subscription", prepareRpcNode(datastore, scope),
+                mockedUriInfo);
+
+        ListenerAdapter listener = Notificator.getListenerFor("opendaylight-inventory:nodes/datastore="
+                + datastoreValue + "/scope=" + scopeValue);
+        assertNotNull(listener);
+
+    }
+
+    private CompositeNode prepareRpcNode(final String datastore, final String scope) {
+        CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+        inputBuilder.setQName(QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote",
+                "2014-01-14", "input"));
+        inputBuilder.addLeaf(
+                QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote", "2014-01-14", "path"),
+                YangInstanceIdentifier.builder().node(QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes")).build());
+        inputBuilder.addLeaf(QName.create("urn:sal:restconf:event:subscription", "2014-7-8", "datastore"), datastore);
+        inputBuilder.addLeaf(QName.create("urn:sal:restconf:event:subscription", "2014-7-8", "scope"), scope);
+        return inputBuilder.toInstance();
+    }
+}
index 655aba267fb5574a94e352fcedd3e4727c923a73..ed871bb52727895c5cdf69dd80e0caa2433cacef 100644 (file)
@@ -14,6 +14,7 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.Iterables;
 import java.io.FileNotFoundException;
 import java.util.Set;
@@ -21,8 +22,8 @@ import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.opendaylight.controller.sal.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
@@ -153,7 +154,7 @@ public class URITest {
     }
 
     public void initMountService(final boolean withSchema) {
-        MountService mountService = mock(MountService.class);
+        DOMMountPointService mountService = mock(DOMMountPointService.class);
         controllerContext.setMountService(mountService);
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
         RestconfImpl restconfImpl = RestconfImpl.getInstance();
@@ -162,12 +163,12 @@ public class URITest {
 
         Set<Module> modules2 = TestUtils.loadModulesFrom("/test-config-data/yang2");
         SchemaContext schemaContext2 = TestUtils.loadSchemaContext(modules2);
-        MountInstance mountInstance = mock(MountInstance.class);
+        DOMMountPoint mountInstance = mock(DOMMountPoint.class);
         if (withSchema) {
             when(mountInstance.getSchemaContext()).thenReturn(schemaContext2);
         } else {
             when(mountInstance.getSchemaContext()).thenReturn(null);
         }
-        when(mountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(mountInstance);
+        when(mountService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountInstance));
     }
 }
index f4e869f99f49ebf42e482ca0c67f88dff0a6c285..23e868c8b2d738e040081603234a86038146f593 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 
 public class XmlAndJsonToCnSnInstanceIdentifierTest extends YangAndXmlAndDataSchemaLoader {
@@ -37,32 +38,44 @@ public class XmlAndJsonToCnSnInstanceIdentifierTest extends YangAndXmlAndDataSch
 
     @Test
     public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
-        CompositeNode cnSn = TestUtils.readInputToCnSn("/instanceidentifier/xml/xmldata.xml",
+        Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/xml/xmldata.xml",
                 XmlToCompositeNodeProvider.INSTANCE);
+
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode cnSn = (CompositeNode)node;
         TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
         verifyListPredicate(cnSn);
     }
 
     @Test
     public void loadXmlLeafListToCnSn() throws WebApplicationException, IOException, URISyntaxException {
-        CompositeNode cnSn = TestUtils.readInputToCnSn("/instanceidentifier/xml/xmldata_leaf_list.xml",
+        Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/xml/xmldata_leaf_list.xml",
                 XmlToCompositeNodeProvider.INSTANCE);
+
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode cnSn = (CompositeNode)node;
         TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
         verifyLeafListPredicate(cnSn);
     }
 
     @Test
     public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
-        CompositeNode cnSn = TestUtils.readInputToCnSn("/instanceidentifier/json/jsondata.json",
+        Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/json/jsondata.json",
                 JsonToCompositeNodeProvider.INSTANCE);
+
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode cnSn = (CompositeNode)node;
         TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
         verifyListPredicate(cnSn);
     }
 
     @Test
     public void loadJsonLeafListToCnSn() throws WebApplicationException, IOException, URISyntaxException {
-        CompositeNode cnSn = TestUtils.readInputToCnSn("/instanceidentifier/json/jsondata_leaf_list.json",
+        Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/json/jsondata_leaf_list.json",
                 JsonToCompositeNodeProvider.INSTANCE);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode cnSn = (CompositeNode)node;
+
         TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
         verifyLeafListPredicate(cnSn);
     }
index 483d90da0d220fc1054929d01008afabb5871175..1c8e53e69ff5091d9a9013947d09cb6381d5723a 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.net.URISyntaxException;
@@ -29,15 +30,22 @@ public class XmlAndJsonToCnSnLeafRefTest extends YangAndXmlAndDataSchemaLoader {
 
     @Test
     public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
-        CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/xml/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE);
+        Node<?> node = TestUtils.readInputToCnSn("/leafref/xml/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE);
+
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode cnSn = (CompositeNode)node;
+
         TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
         verifyContPredicate(cnSn, "/ns:cont/ns:lf1", "/cont/lf1", "/ns:cont/ns:lf1", "../lf1");
     }
 
     @Test
     public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
-        CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/json/jsondata.json",
+        Node<?> node = TestUtils.readInputToCnSn("/leafref/json/jsondata.json",
                 JsonToCompositeNodeProvider.INSTANCE);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode cnSn = (CompositeNode)node;
+
         TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
         verifyContPredicate(cnSn, "/leafref-module:cont/leafref-module:lf1", "/leafref-module:cont/leafref-module:lf1",
                 "/referenced-module:cont/referenced-module:lf1", "/leafref-module:cont/leafref-module:lf1");
index 70f0f050dc9fdea84f186537eafbcad6779d7e53..121a3865bd01343533924435aa981f865586e53e 100644 (file)
@@ -32,6 +32,9 @@ import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
 public class RestStream extends JerseyTest {
 
@@ -68,17 +71,20 @@ public class RestStream extends JerseyTest {
     public void testCallRpcCallGet() throws UnsupportedEncodingException, InterruptedException {
         String uri = "/operations/sal-remote:create-data-change-event-subscription";
         Response responseWithStreamName = post(uri, MediaType.APPLICATION_XML, getRpcInput());
-        String xmlResponse = responseWithStreamName.readEntity(String.class);
+        Document xmlResponse = responseWithStreamName.readEntity(Document.class);
         assertNotNull(xmlResponse);
-        assertTrue(xmlResponse
-                .contains("<stream-name>ietf-interfaces:interfaces/ietf-interfaces:interface/eth0</stream-name>"));
+        Element outputElement = xmlResponse.getDocumentElement();
+        assertEquals("output",outputElement.getLocalName());
 
-        uri = "/streams/stream/ietf-interfaces:interfaces/ietf-interfaces:interface/eth0";
+        Node streamNameElement = outputElement.getFirstChild();
+        assertEquals("stream-name",streamNameElement.getLocalName());
+        assertEquals("ietf-interfaces:interfaces/ietf-interfaces:interface/eth0/datastore=CONFIGURATION/scope=BASE",streamNameElement.getTextContent());
+
+        uri = "/streams/stream/ietf-interfaces:interfaces/ietf-interfaces:interface/eth0/datastore=CONFIGURATION/scope=BASE";
         Response responseWithRedirectionUri = get(uri, MediaType.APPLICATION_XML);
         final URI websocketServerUri = responseWithRedirectionUri.getLocation();
         assertNotNull(websocketServerUri);
-        assertEquals(websocketServerUri.toString(),
-                "http://localhost:8181/ietf-interfaces:interfaces/ietf-interfaces:interface/eth0");
+        assertTrue(websocketServerUri.toString().matches(".*http://localhost:[\\d]+/ietf-interfaces:interfaces/ietf-interfaces:interface/eth0.*"));
     }
 
     private Response post(String uri, String mediaType, String data) {
index 5a5a621d930b68fc240140f76b086a0d57bc0a3c..e992e1214e9b44af05bf76bc0091afc623d11613 100644 (file)
@@ -8,12 +8,14 @@
 package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
 
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.util.Set;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
 public class XmlAugmentedElementToCnSnTest {
@@ -25,12 +27,15 @@ public class XmlAugmentedElementToCnSnTest {
     }
 
     private void loadAndNormalizeData(String xmlPath, String yangPath, String topLevelElementName, String moduleName) {
-        CompositeNode compNode = TestUtils.readInputToCnSn(xmlPath, false, XmlToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compNode);
+        Node<?> node = TestUtils.readInputToCnSn(xmlPath, false,
+                XmlToCompositeNodeProvider.INSTANCE);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode cnSn = (CompositeNode)node;
+
         Set<Module> modules = TestUtils.loadModulesFrom(yangPath);
 
         assertNotNull(modules);
-        TestUtils.normalizeCompositeNode(compNode, modules, topLevelElementName + ":" + moduleName);
+        TestUtils.normalizeCompositeNode(cnSn, modules, topLevelElementName + ":" + moduleName);
     }
 
 }
index 6c11bc1861995879818ce31b3d6d75696c2decf7..1c62b7fbdb8e9013a38cd124d1df4e1c481bf3e5 100644 (file)
@@ -33,8 +33,11 @@ public class XmlLeafrefToCnSnTest {
      */
     @Test
     public void testXmlDataContainer() {
-        CompositeNode compNode = TestUtils.readInputToCnSn("/xml-to-cnsn/data-container.xml", false,
+        Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/data-container.xml", false,
                 XmlToCompositeNodeProvider.INSTANCE);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compNode = (CompositeNode)node;
+
         assertNotNull(compNode);
         Set<Module> modules = TestUtils.loadModulesFrom("/xml-to-cnsn/data-container-yang");
 
@@ -76,9 +79,11 @@ public class XmlLeafrefToCnSnTest {
 
     @Test
     public void testXmlDataList() {
-        CompositeNode compNode = TestUtils.readInputToCnSn("/xml-to-cnsn/data-list.xml", false,
+        Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/data-list.xml", false,
                 XmlToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compNode);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compNode = (CompositeNode)node;
+
 
         Set<Module> modules = TestUtils.loadModulesFrom("/xml-to-cnsn/data-list-yang");
         assertNotNull(modules);
@@ -93,22 +98,22 @@ public class XmlLeafrefToCnSnTest {
         CompositeNode lst1_1 = null;
         CompositeNode lst1_2 = null;
         int loopCount = 0;
-        for (Node<?> node : compNode.getValue()) {
-            if (node.getNodeType().getLocalName().equals("lf1")) {
-                assertEquals(nameSpaceList, node.getNodeType().getNamespace().toString());
-                assertTrue(node instanceof SimpleNode<?>);
-                assertEquals("lf1", node.getValue());
+        for (Node<?> nd : compNode.getValue()) {
+            if (nd.getNodeType().getLocalName().equals("lf1")) {
+                assertEquals(nameSpaceList, nd.getNodeType().getNamespace().toString());
+                assertTrue(nd instanceof SimpleNode<?>);
+                assertEquals("lf1", nd.getValue());
             } else {
-                assertTrue(node instanceof CompositeNode);
+                assertTrue(nd instanceof CompositeNode);
                 switch (loopCount++) {
                 case 0:
-                    lst1_1 = (CompositeNode) node;
+                    lst1_1 = (CompositeNode) nd;
                     break;
                 case 1:
-                    lst1_2 = (CompositeNode) node;
+                    lst1_2 = (CompositeNode) nd;
                     break;
                 }
-                assertEquals(nameSpaceCont, node.getNodeType().getNamespace().toString());
+                assertEquals(nameSpaceCont, nd.getNodeType().getNamespace().toString());
             }
         }
         // lst1_1
@@ -118,15 +123,15 @@ public class XmlLeafrefToCnSnTest {
         // lst1_2
         SimpleNode<?> lflst11 = null;
         CompositeNode cont11 = null;
-        for (Node<?> node : lst1_2.getValue()) {
-            String nodeName = node.getNodeType().getLocalName();
+        for (Node<?> nd : lst1_2.getValue()) {
+            String nodeName = nd.getNodeType().getLocalName();
             if (nodeName.equals("lflst11")) {
-                assertTrue(node instanceof SimpleNode<?>);
-                lflst11 = (SimpleNode<?>) node;
+                assertTrue(nd instanceof SimpleNode<?>);
+                lflst11 = (SimpleNode<?>) nd;
 
             } else if (nodeName.equals("cont11")) {
-                assertTrue(node instanceof CompositeNode);
-                cont11 = (CompositeNode) node;
+                assertTrue(nd instanceof CompositeNode);
+                cont11 = (CompositeNode) nd;
             }
             assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString());
         }
@@ -144,32 +149,35 @@ public class XmlLeafrefToCnSnTest {
 
     @Test
     public void testXmlEmptyData() {
-        CompositeNode compNode = TestUtils.readInputToCnSn("/xml-to-cnsn/empty-data.xml", true,
+        Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/empty-data.xml", true,
                 XmlToCompositeNodeProvider.INSTANCE);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compNode = (CompositeNode)node;
+
         assertEquals("cont", compNode.getNodeType().getLocalName());
         SimpleNode<?> lf1 = null;
         SimpleNode<?> lflst1_1 = null;
         SimpleNode<?> lflst1_2 = null;
         CompositeNode lst1 = null;
         int lflst1Count = 0;
-        for (Node<?> node : compNode.getValue()) {
-            if (node.getNodeType().getLocalName().equals("lf1")) {
-                assertTrue(node instanceof SimpleNode<?>);
-                lf1 = (SimpleNode<?>) node;
-            } else if (node.getNodeType().getLocalName().equals("lflst1")) {
-                assertTrue(node instanceof SimpleNode<?>);
+        for (Node<?> nd : compNode.getValue()) {
+            if (nd.getNodeType().getLocalName().equals("lf1")) {
+                assertTrue(nd instanceof SimpleNode<?>);
+                lf1 = (SimpleNode<?>) nd;
+            } else if (nd.getNodeType().getLocalName().equals("lflst1")) {
+                assertTrue(nd instanceof SimpleNode<?>);
 
                 switch (lflst1Count++) {
                 case 0:
-                    lflst1_1 = (SimpleNode<?>) node;
+                    lflst1_1 = (SimpleNode<?>) nd;
                     break;
                 case 1:
-                    lflst1_2 = (SimpleNode<?>) node;
+                    lflst1_2 = (SimpleNode<?>) nd;
                     break;
                 }
-            } else if (node.getNodeType().getLocalName().equals("lst1")) {
-                assertTrue(node instanceof CompositeNode);
-                lst1 = (CompositeNode) node;
+            } else if (nd.getNodeType().getLocalName().equals("lst1")) {
+                assertTrue(nd instanceof CompositeNode);
+                lst1 = (CompositeNode) nd;
             }
         }
 
@@ -317,8 +325,10 @@ public class XmlLeafrefToCnSnTest {
 
     private void testIdentityrefToCnSn(final String xmlPath, final String yangPath, final String moduleName,
             final String schemaName, final int moduleCount, final String resultLocalName, final String resultNamespace) {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn(xmlPath, false, XmlToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        Node<?> node = TestUtils.readInputToCnSn(xmlPath, false, XmlToCompositeNodeProvider.INSTANCE);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
+
 
         Set<Module> modules = TestUtils.loadModulesFrom(yangPath);
         assertEquals(moduleCount, modules.size());
index e2621d635bc3dab04629beffcb15c3d111b9eb21..d0af29e913fa633381c176ff1796a2fbd3f41c29 100644 (file)
@@ -32,9 +32,12 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
 
     @Test
     public void testXmlLeafrefToCnSn() {
-        CompositeNode compositeNode = TestUtils.readInputToCnSn("/xml-to-cnsn/leafref/xml/data.xml", false,
+        Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/leafref/xml/data.xml", false,
                 XmlToCompositeNodeProvider.INSTANCE);
-        assertNotNull(compositeNode);
+        assertTrue(node instanceof CompositeNode);
+        CompositeNode compositeNode = (CompositeNode)node;
+
+
         assertNotNull(dataSchemaNode);
         TestUtils.normalizeCompositeNode(compositeNode, modules, schemaNodePath);
 
@@ -58,10 +61,10 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
     @Test
     public void testXmlBlankInput() throws Exception {
         InputStream inputStream = new ByteArrayInputStream("".getBytes());
-        CompositeNode compositeNode = XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null,
-                inputStream);
+        Node<?> node =
+                XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
 
-        assertNull(compositeNode);
+        assertNull( node );
     }
 
     @Test
@@ -72,10 +75,10 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
                 return false;
             }
         };
-        CompositeNode compositeNode = XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null,
-                inputStream);
+        Node<?> node =
+                XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
 
-        assertNull(compositeNode);
+        assertNull( node );
     }
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/opendaylight-inventory.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/opendaylight-inventory.yang
new file mode 100644 (file)
index 0000000..e4247be
--- /dev/null
@@ -0,0 +1,19 @@
+module opendaylight-inventory {
+    namespace "urn:opendaylight:inventory";
+    prefix inv;
+
+    revision "2013-08-19" {
+        description "Initial revision of Inventory model";
+    }
+    
+    
+    container nodes {
+        list node {
+            key "id";
+            leaf id {
+                type string;
+            }
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/sal-remote-augment.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/sal-remote-augment.yang
new file mode 100644 (file)
index 0000000..8393456
--- /dev/null
@@ -0,0 +1,31 @@
+module sal-remote-augment {
+
+    yang-version 1;
+    namespace "urn:sal:restconf:event:subscription";
+    prefix "salrmt-aug-ev-subscr";
+
+    import sal-remote {prefix salrmt; revision-date "2014-01-14";}
+
+    description
+        "Added input parameters to rpc create-data-change-event-subscription";
+
+    revision "2014-7-8" {
+    }
+
+    augment "/salrmt:create-data-change-event-subscription/salrmt:input" {
+        leaf datastore {
+            type enumeration {
+                enum OPERATIONAL;
+                enum CONFIGURATION;
+            }
+        }
+        leaf scope {
+            type enumeration {
+                enum BASE;
+                enum ONE;
+                enum SUBTREE;
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/sal-remote@2014-01-14.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/datastore-and-scope-specification/sal-remote@2014-01-14.yang
new file mode 100644 (file)
index 0000000..d12e252
--- /dev/null
@@ -0,0 +1,98 @@
+module sal-remote {
+
+       yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote";
+    prefix "sal-remote";
+    
+
+    organization "Cisco Systems, Inc.";
+    contact "Martin Bobak <mbobak@cisco.com>";
+
+    description
+          "This module contains the definition of methods related to
+           sal remote model.
+
+           Copyright (c)2013 Cisco Systems, Inc. All rights reserved.
+
+           This program and the accompanying materials are made available
+           under the terms of the Eclipse Public License v1.0 which
+           accompanies this distribution, and is available at
+           http://www.eclipse.org/legal/epl-v10.html";
+
+    revision "2014-01-14" {
+        description
+            "Initial revision";
+    }
+
+
+     typedef q-name {
+       type string;
+       reference
+         "http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#QName";
+     }
+
+    rpc create-data-change-event-subscription {
+        input {
+            leaf path {
+                type instance-identifier;
+                description "Subtree path. ";
+            }
+         }
+         output {
+            leaf stream-name {
+                type string;
+                description "Notification stream name.";
+            }
+         }
+    }
+
+    notification data-changed-notification {
+        description "Data change notification.";
+        list data-change-event {
+            key path;
+            leaf path {
+                type instance-identifier;
+            }
+            leaf store {
+                type enumeration {
+                    enum config;
+                    enum operation;
+                }
+            }
+            leaf operation {
+                type enumeration {
+                    enum created;
+                    enum updated;
+                    enum deleted;
+                }
+            }
+            anyxml data{
+                description "DataObject ";
+            }
+         }
+    }
+
+    rpc create-notification-stream {
+        input {
+            leaf-list notifications {
+                type q-name;
+                description "Notification QNames";
+            }
+         }
+        output {
+            leaf notification-stream-identifier {
+                type string;
+                description "Unique notification stream identifier, in which notifications will be propagated";
+            }
+        }
+    }
+
+    rpc begin-transaction{
+        output{
+            anyxml data-modification-transaction{
+                description "DataModificationTransaction xml";
+            }
+        }
+    }
+
+}
\ No newline at end of file
index 9995a8f1271ea348b835fb8b296937797f944f6d..a1d5ab0a129fa92d362b4faa7d1e416fd367b7ab 100644 (file)
@@ -3,7 +3,7 @@
     yang-version 1;
 
     namespace
-      "http://netconfcentral.org/ns/toaster";
+      "http://netconfcentral.org/ns/toaster2";
 
     prefix toast;
 
index a0c23aecb4627c4aec4ab1a828d6d97fe695fc60..af7a32924b783ebfafa1f43a2726b9a635387270 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.controller.md.sal.test.model.util;
 
-import java.util.Arrays;
-
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
@@ -25,7 +26,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
 
 public class ListsBindingUtils {
 
@@ -79,4 +80,9 @@ public class ListsBindingUtils {
         return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
     }
 
+    public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+        return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+    }
+
 }
index c601647a2eb93e63afafeb2123318e277de2a957..ae7d3234808bdd00059fce9403419eb923f8a8fd 100644 (file)
@@ -15,6 +15,7 @@
     <module>toaster</module>
     <module>toaster-consumer</module>
     <module>toaster-provider</module>
+    <module>toaster-config</module>
     <module>l2switch</module>
   </modules>
   <scm>
diff --git a/opendaylight/md-sal/samples/toaster-config/pom.xml b/opendaylight/md-sal/samples/toaster-config/pom.xml
new file mode 100644 (file)
index 0000000..b30c4ba
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller.samples</groupId>
+    <artifactId>sal-samples</artifactId>
+    <version>1.1-SNAPSHOT</version>
+  </parent>
+  <artifactId>toaster-config</artifactId>
+  <description>Configuration files for toaster</description>
+  <packaging>jar</packaging>
+  <build>
+    <plugins>
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/initial/03-toaster-sample.xml</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
similarity index 99%
rename from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/03-toaster-sample.xml
rename to opendaylight/md-sal/samples/toaster-config/src/main/resources/initial/03-toaster-sample.xml
index 3958e185605e155f8b4b092e927ff5e8a679cbd1..2e8c7d5ce6ee3f2093f6bc0340bda56e634d2d63 100644 (file)
@@ -26,7 +26,7 @@
                         <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
@@ -54,7 +54,7 @@
                     </notification-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">
index 2c8571ca64369c80748ee5d1b157a39017c1db86..e01a0d5dcba4956f790d2274462455911970742c 100644 (file)
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-base</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
index eddad8b4c7c1df593c45a5f829c3c56828339e18..fff8d611b7975b34dce89ce603f164603ea2b582 100644 (file)
@@ -65,9 +65,11 @@ public class ConfigPusher {
         LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> result = new LinkedHashMap<>();
         // start pushing snapshots:
         for (ConfigSnapshotHolder configSnapshotHolder : configs) {
-            EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
-            logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
-            result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+            if(configSnapshotHolder != null) {
+                EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
+                logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
+                result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+            }
         }
         logger.debug("All configuration snapshots have been pushed successfully.");
         return result;
index cd7a1aacf2dbfbf47dc0e6a00003abde2f09b3d7..55a87150008ab51f0a96cc163ed218e629e31201 100644 (file)
     <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>
+      <artifactId>yang-data-composite-node</artifactId>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
index c101db9ef8406342c502fe2e276e203791970662..ef29a76fff342c5c5e0fc87d89b1a56639aa04f6 100644 (file)
@@ -18,7 +18,7 @@ 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.data.composite.node.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;
diff --git a/opendaylight/netconf/netconf-config/pom.xml b/opendaylight/netconf/netconf-config/pom.xml
new file mode 100644 (file)
index 0000000..db5d14d
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>netconf-subsystem</artifactId>
+    <version>0.2.5-SNAPSHOT</version>
+  </parent>
+  <artifactId>netconf-config</artifactId>
+  <description>Configuration files for netconf</description>
+  <packaging>jar</packaging>
+  <build>
+    <plugins>
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/initial/01-netconf.xml</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/opendaylight/netconf/netconf-connector-config/pom.xml b/opendaylight/netconf/netconf-connector-config/pom.xml
new file mode 100644 (file)
index 0000000..d9cc5ea
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>netconf-subsystem</artifactId>
+    <version>0.2.5-SNAPSHOT</version>
+  </parent>
+  <artifactId>netconf-connector-config</artifactId>
+  <description>Configuration files for netconf-connector</description>
+  <packaging>jar</packaging>
+  <build>
+    <plugins>
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/initial/99-netconf-connector.xml</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
index 0e9589d2d21b0bde118440a1a0c683e1bedf3fd5..272b686fc034ff33fbbe247b706ec536040660cb 100644 (file)
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <forkCount>1</forkCount>
-          <reuseForks>false</reuseForks>
-          <perCoreThreadCount>false</perCoreThreadCount>
-        </configuration>
-        <executions>
-          <execution>
-            <id>default-test</id>
-            <configuration>
-              <skip>true</skip>
-            </configuration>
-          </execution>
-          <execution>
-            <id>integration-tests</id>
-            <goals>
-              <goal>test</goal>
-            </goals>
-            <phase>integration-test</phase>
-            <configuration>
-              <skip>false</skip>
-              <argLine>-Dlogback.configurationFile=${maven.test.dest}/logback.xml</argLine>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
index 937949a17e5827bbe74d22eb5071904b3a71906d..c72705d50ebd8f505feaac092331fcbafc1ee41b 100644 (file)
@@ -20,6 +20,7 @@
   <modules>
     <module>netconf-api</module>
     <module>netconf-cli</module>
+    <module>netconf-config</module>
     <module>netconf-impl</module>
     <module>config-netconf-connector</module>
     <module>netconf-util</module>
@@ -32,6 +33,7 @@
     <module>netconf-monitoring</module>
     <module>ietf-netconf-monitoring</module>
     <module>ietf-netconf-monitoring-extension</module>
+    <module>netconf-connector-config</module>
   </modules>
 
   <dependencies>
index 1e2cd47c9c2d923ac09f3cbc50fc60b9c2a519f0..45070ca8b01e64331381f67f28b367e2f80bc483 100644 (file)
@@ -8,23 +8,26 @@
 
 package org.opendaylight.controller.networkconfig.neutron.implementation;
 
-import java.util.Hashtable;
-import java.util.Dictionary;
-
 import org.apache.felix.dm.Component;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
 import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallPolicyCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallRuleCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
 import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
 
 public class Activator extends ComponentActivatorAbstractBase {
     protected static final Logger logger = LoggerFactory
@@ -68,7 +71,10 @@ public class Activator extends ComponentActivatorAbstractBase {
                 NeutronSubnetInterface.class,
                 NeutronNetworkInterface.class,
                 NeutronSecurityGroupInterface.class,
-                NeutronSecurityRuleInterface.class};
+                NeutronSecurityRuleInterface.class,
+                NeutronFirewallInterface.class,
+                NeutronFirewallPolicyInterface.class,
+                NeutronFirewallRuleInterface.class};
         return res;
     }
 
@@ -199,5 +205,53 @@ public class Activator extends ComponentActivatorAbstractBase {
                 "setConfigurationContainerService",
                 "unsetConfigurationContainerService").setRequired(true));
         }
+        if (imp.equals(NeutronFirewallInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronFirewallCRUD.class.getName(),
+                            IConfigurationContainerAware.class.getName()}, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                            "unsetClusterContainerService").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IConfigurationContainerService.class).setCallbacks(
+                    "setConfigurationContainerService",
+                    "unsetConfigurationContainerService").setRequired(true));
+        }
+        if (imp.equals(NeutronFirewallPolicyInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronFirewallPolicyCRUD.class.getName(),
+                            IConfigurationContainerAware.class.getName()}, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                            "unsetClusterContainerService").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IConfigurationContainerService.class).setCallbacks(
+                    "setConfigurationContainerService",
+                    "unsetConfigurationContainerService").setRequired(true));
+        }
+        if (imp.equals(NeutronFirewallRuleInterface.class)) {
+            // export the service
+            c.setInterface(
+                    new String[] { INeutronFirewallRuleCRUD.class.getName(),
+                            IConfigurationContainerAware.class.getName()}, null);
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "neutron");
+            c.add(createContainerServiceDependency(containerName)
+                    .setService(IClusterContainerServices.class)
+                    .setCallbacks("setClusterContainerService",
+                            "unsetClusterContainerService").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IConfigurationContainerService.class).setCallbacks(
+                    "setConfigurationContainerService",
+                    "unsetConfigurationContainerService").setRequired(true));
+        }
     }
 }
diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallInterface.java
new file mode 100644 (file)
index 0000000..60476a1
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.implementation;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewall;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronFirewallInterface implements INeutronFirewallCRUD, IConfigurationContainerAware, IObjectReader {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronFirewallInterface.class);
+    private static final String FILE_NAME = "neutron.firewall.conf";
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private IConfigurationContainerService configurationService;
+    private ConcurrentMap<String, NeutronFirewall> firewallDB;
+
+    // methods needed for creating caches
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            clusterContainerService = null;
+        }
+    }
+
+    public void setConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service set: {}", service);
+        configurationService = service;
+    }
+
+    public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service removed: {}", service);
+        configurationService = null;
+    }
+
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Firewall");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronFirewalls",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Firewall -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Firewall already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Firewall");
+    }
+
+    @SuppressWarnings ({"unchecked"})
+    private void retrieveCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Firewall");
+        firewallDB = (ConcurrentMap<String, NeutronFirewall>) clusterContainerService
+                .getCache("neutronFirewalls");
+        if (firewallDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Firewall");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Firewall");
+    }
+
+    private void destroyCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for HostTracker");
+        clusterContainerService.destroyCache("neutronFirewalls");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+        loadConfiguration();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for (Method toMethod : methods) {
+            if (toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")) {
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[]) null);
+                    if (value != null) {
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean neutronFirewallExists(String uuid) {
+        return firewallDB.containsKey(uuid);
+    }
+
+    @Override
+    public NeutronFirewall getNeutronFirewall(String uuid) {
+        if (!neutronFirewallExists(uuid)) {
+            logger.debug("No Firewall Have Been Defined");
+            return null;
+        }
+        return firewallDB.get(uuid);
+    }
+
+    @Override
+    public List<NeutronFirewall> getAllNeutronFirewalls() {
+        Set<NeutronFirewall> allFirewalls = new HashSet<NeutronFirewall>();
+        for (Entry<String, NeutronFirewall> entry : firewallDB.entrySet()) {
+            NeutronFirewall firewall = entry.getValue();
+            allFirewalls.add(firewall);
+        }
+        logger.debug("Exiting getFirewalls, Found {} OpenStackFirewall", allFirewalls.size());
+        List<NeutronFirewall> ans = new ArrayList<NeutronFirewall>();
+        ans.addAll(allFirewalls);
+        return ans;
+    }
+
+    @Override
+    public boolean addNeutronFirewall(NeutronFirewall input) {
+        if (neutronFirewallExists(input.getFirewallUUID())) {
+            return false;
+        }
+        firewallDB.putIfAbsent(input.getFirewallUUID(), input);
+        return true;
+    }
+
+    @Override
+    public boolean removeNeutronFirewall(String uuid) {
+        if (!neutronFirewallExists(uuid)) {
+            return false;
+        }
+        firewallDB.remove(uuid);
+        return true;
+    }
+
+    @Override
+    public boolean updateNeutronFirewall(String uuid, NeutronFirewall delta) {
+        if (!neutronFirewallExists(uuid)) {
+            return false;
+        }
+        NeutronFirewall target = firewallDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    @Override
+    public boolean neutronFirewallInUse(String firewallUUID) {
+        return !neutronFirewallExists(firewallUUID);
+    }
+
+    private void loadConfiguration() {
+        for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+            NeutronFirewall nn = (NeutronFirewall) conf;
+            firewallDB.put(nn.getFirewallUUID(), nn);
+        }
+    }
+
+    @Override
+    public Status saveConfiguration() {
+        return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(firewallDB.values()),
+                FILE_NAME);
+    }
+
+    @Override
+    public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+        return ois.readObject();
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallPolicyInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallPolicyInterface.java
new file mode 100644 (file)
index 0000000..8459262
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.implementation;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallPolicyCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewallPolicy;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronFirewallPolicyInterface implements INeutronFirewallPolicyCRUD, IConfigurationContainerAware, IObjectReader {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronFirewallPolicyInterface.class);
+    private static final String FILE_NAME ="neutron.firewallpolicy.conf";
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private IConfigurationContainerService configurationService;
+    private ConcurrentMap<String, NeutronFirewallPolicy> firewallPolicyDB;
+
+    // methods needed for creating caches
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            clusterContainerService = null;
+        }
+    }
+
+    public void setConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service set: {}", service);
+        configurationService = service;
+    }
+
+    public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service removed: {}", service);
+        configurationService = null;
+    }
+
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Firewall Rule");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronFirewallPolicies",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Firewall Rule -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Firewall Rule already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Firewall Rule");
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    private void retrieveCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Firewall Rule");
+        firewallPolicyDB = (ConcurrentMap<String, NeutronFirewallPolicy>) clusterContainerService
+                .getCache("neutronFirewallPolicies");
+        if (firewallPolicyDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Firewall Rule");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Firewall Rule");
+    }
+
+    private void destroyCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for HostTracker");
+        clusterContainerService.destroyCache("neutronFirewallPolicies");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+        loadConfiguration();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean neutronFirewallPolicyExists(String uuid) {
+        return firewallPolicyDB.containsKey(uuid);
+    }
+
+    @Override
+    public NeutronFirewallPolicy getNeutronFirewallPolicy(String uuid) {
+        if (!neutronFirewallPolicyExists(uuid)) {
+            logger.debug("No Firewall Rule Have Been Defined");
+            return null;
+        }
+        return firewallPolicyDB.get(uuid);
+    }
+
+    @Override
+    public List<NeutronFirewallPolicy> getAllNeutronFirewallPolicies() {
+        Set<NeutronFirewallPolicy> allFirewallPolicies = new HashSet<NeutronFirewallPolicy>();
+        for (Entry<String, NeutronFirewallPolicy> entry : firewallPolicyDB.entrySet()) {
+            NeutronFirewallPolicy firewallPolicy = entry.getValue();
+            allFirewallPolicies.add(firewallPolicy);
+        }
+        logger.debug("Exiting getFirewallPolicies, Found {} OpenStackFirewallPolicy", allFirewallPolicies.size());
+        List<NeutronFirewallPolicy> ans = new ArrayList<NeutronFirewallPolicy>();
+        ans.addAll(allFirewallPolicies);
+        return ans;
+    }
+
+    @Override
+    public boolean addNeutronFirewallPolicy(NeutronFirewallPolicy input) {
+        if (neutronFirewallPolicyExists(input.getFirewallPolicyUUID())) {
+            return false;
+        }
+        firewallPolicyDB.putIfAbsent(input.getFirewallPolicyUUID(), input);
+        return true;
+    }
+
+    @Override
+    public boolean removeNeutronFirewallPolicy(String uuid) {
+        if (!neutronFirewallPolicyExists(uuid)) {
+            return false;
+        }
+        firewallPolicyDB.remove(uuid);
+        return true;
+    }
+
+    @Override
+    public boolean updateNeutronFirewallPolicy(String uuid, NeutronFirewallPolicy delta) {
+        if (!neutronFirewallPolicyExists(uuid)) {
+            return false;
+        }
+        NeutronFirewallPolicy target = firewallPolicyDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    @Override
+    public boolean neutronFirewallPolicyInUse(String firewallPolicyUUID) {
+        return !neutronFirewallPolicyExists(firewallPolicyUUID);
+    }
+
+    private void loadConfiguration() {
+        for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+            NeutronFirewallPolicy nn = (NeutronFirewallPolicy) conf;
+            firewallPolicyDB.put(nn.getFirewallPolicyUUID(), nn);
+        }
+    }
+
+    @Override
+    public Status saveConfiguration() {
+        return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(firewallPolicyDB.values()),
+                FILE_NAME);
+    }
+
+    @Override
+    public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+        return ois.readObject();
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallRuleInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFirewallRuleInterface.java
new file mode 100644 (file)
index 0000000..ba84500
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.implementation;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewallRule;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronFirewallRuleInterface implements INeutronFirewallRuleCRUD, IConfigurationContainerAware, IObjectReader {
+    private static final Logger logger = LoggerFactory.getLogger(NeutronFirewallRuleInterface.class);
+    private static final String FILE_NAME ="neutron.firewallrules.conf";
+    private String containerName = null;
+
+    private IClusterContainerServices clusterContainerService = null;
+    private IConfigurationContainerService configurationService;
+    private ConcurrentMap<String, NeutronFirewallRule> firewallRuleDB;
+
+    // methods needed for creating caches
+    void setClusterContainerService(IClusterContainerServices s) {
+        logger.debug("Cluster Service set");
+        clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (clusterContainerService == s) {
+            logger.debug("Cluster Service removed!");
+            clusterContainerService = null;
+        }
+    }
+
+    public void setConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service set: {}", service);
+        configurationService = service;
+    }
+
+    public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+        logger.trace("Configuration service removed: {}", service);
+        configurationService = null;
+    }
+
+    private void allocateCache() {
+        if (this.clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+        logger.debug("Creating Cache for Neutron Firewall Rule");
+        try {
+            // neutron caches
+            this.clusterContainerService.createCache("neutronFirewallRules",
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("Cache couldn't be created for Neutron Firewall Rule -  check cache mode");
+        } catch (CacheExistException cce) {
+            logger.error("Cache for Neutron Firewall Rule already exists, destroy and recreate");
+        }
+        logger.debug("Cache successfully created for Neutron Firewall Rule");
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    private void retrieveCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        logger.debug("Retrieving cache for Neutron Firewall Rule");
+        firewallRuleDB = (ConcurrentMap<String, NeutronFirewallRule>) clusterContainerService
+                .getCache("neutronFirewallRules");
+        if (firewallRuleDB == null) {
+            logger.error("Cache couldn't be retrieved for Neutron Firewall Rule");
+        }
+        logger.debug("Cache was successfully retrieved for Neutron Firewall Rule");
+    }
+
+    private void destroyCache() {
+        if (clusterContainerService == null) {
+            logger.error("un-initialized clusterMger, can't destroy cache");
+            return;
+        }
+        logger.debug("Destroying Cache for HostTracker");
+        clusterContainerService.destroyCache("neutronFirewallRules");
+    }
+
+    private void startUp() {
+        allocateCache();
+        retrieveCache();
+        loadConfiguration();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+            logger.debug("Running containerName: {}", this.containerName);
+        } else {
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        startUp();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        destroyCache();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    void stop() {
+    }
+
+    // this method uses reflection to update an object from it's delta.
+
+    private boolean overwrite(Object target, Object delta) {
+        Method[] methods = target.getClass().getMethods();
+
+        for(Method toMethod: methods){
+            if(toMethod.getDeclaringClass().equals(target.getClass())
+                    && toMethod.getName().startsWith("set")){
+
+                String toName = toMethod.getName();
+                String fromName = toName.replace("set", "get");
+
+                try {
+                    Method fromMethod = delta.getClass().getMethod(fromName);
+                    Object value = fromMethod.invoke(delta, (Object[])null);
+                    if(value != null){
+                        toMethod.invoke(target, value);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean neutronFirewallRuleExists(String uuid) {
+        return firewallRuleDB.containsKey(uuid);
+    }
+
+    @Override
+    public NeutronFirewallRule getNeutronFirewallRule(String uuid) {
+        if (!neutronFirewallRuleExists(uuid)) {
+            logger.debug("No Firewall Rule Have Been Defined");
+            return null;
+        }
+        return firewallRuleDB.get(uuid);
+    }
+
+    @Override
+    public List<NeutronFirewallRule> getAllNeutronFirewallRules() {
+        Set<NeutronFirewallRule> allFirewallRules = new HashSet<NeutronFirewallRule>();
+        for (Entry<String, NeutronFirewallRule> entry : firewallRuleDB.entrySet()) {
+            NeutronFirewallRule firewallRule = entry.getValue();
+            allFirewallRules.add(firewallRule);
+        }
+        logger.debug("Exiting getFirewallRules, Found {} OpenStackFirewallRule", allFirewallRules.size());
+        List<NeutronFirewallRule> ans = new ArrayList<NeutronFirewallRule>();
+        ans.addAll(allFirewallRules);
+        return ans;
+    }
+
+    @Override
+    public boolean addNeutronFirewallRule(NeutronFirewallRule input) {
+        if (neutronFirewallRuleExists(input.getFirewallRuleUUID())) {
+            return false;
+        }
+        firewallRuleDB.putIfAbsent(input.getFirewallRuleUUID(), input);
+        return true;
+    }
+
+    @Override
+    public boolean removeNeutronFirewallRule(String uuid) {
+        if (!neutronFirewallRuleExists(uuid)) {
+            return false;
+        }
+        firewallRuleDB.remove(uuid);
+        return true;
+    }
+
+    @Override
+    public boolean updateNeutronFirewallRule(String uuid, NeutronFirewallRule delta) {
+        if (!neutronFirewallRuleExists(uuid)) {
+            return false;
+        }
+        NeutronFirewallRule target = firewallRuleDB.get(uuid);
+        return overwrite(target, delta);
+    }
+
+    @Override
+    public boolean neutronFirewallRuleInUse(String firewallRuleUUID) {
+        return !neutronFirewallRuleExists(firewallRuleUUID);
+    }
+
+    private void loadConfiguration() {
+        for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+            NeutronFirewallRule nn = (NeutronFirewallRule) conf;
+            firewallRuleDB.put(nn.getFirewallRuleUUID(), nn);
+        }
+    }
+
+    @Override
+    public Status saveConfiguration() {
+        return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(firewallRuleDB.values()),
+                FILE_NAME);
+    }
+
+    @Override
+    public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+        return ois.readObject();
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallAware.java
new file mode 100644 (file)
index 0000000..9b4f579
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Firewall Rules needs to implement
+ *
+ */
+
+public interface INeutronFirewallAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified firewall can be created
+     *
+     * @param firewall
+     *            instance of proposed new Firewall object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreateNeutronFirewall(NeutronFirewall firewall);
+
+    /**
+     * Services provide this interface method for taking action after a firewall has been created
+     *
+     * @param firewall
+     *            instance of new Firewall object
+     * @return void
+     */
+    public void neutronFirewallCreated(NeutronFirewall firewall);
+
+    /**
+     * Services provide this interface method to indicate if the specified firewall can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the firewall object using patch semantics
+     * @param original
+     *            instance of the Firewall object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdateNeutronFirewall(NeutronFirewall delta, NeutronFirewall original);
+
+    /**
+     * Services provide this interface method for taking action after a firewall has been updated
+     *
+     * @param firewall
+     *            instance of modified Firewall object
+     * @return void
+     */
+    public void neutronFirewallUpdated(NeutronFirewall firewall);
+
+    /**
+     * Services provide this interface method to indicate if the specified firewall can be deleted
+     *
+     * @param firewall
+     *            instance of the Firewall object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeleteNeutronFirewall(NeutronFirewall firewall);
+
+    /**
+     * Services provide this interface method for taking action after a firewall has been deleted
+     *
+     * @param firewall
+     *            instance of deleted Firewall object
+     * @return void
+     */
+    public void neutronFirewallDeleted(NeutronFirewall firewall);
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallCRUD.java
new file mode 100644 (file)
index 0000000..c986bff
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB OpenStack Firewall objects
+ *
+ */
+
+public interface INeutronFirewallCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     *Firewall object exists
+     *
+     * @param uuid
+     *            UUID of the Firewall object
+     * @return boolean
+     */
+
+    public boolean neutronFirewallExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * Firewall object exists
+     *
+     * @param uuid
+     *            UUID of the Firewall object
+     * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronFirewall}
+     *          OpenStackFirewall class
+     */
+
+    public NeutronFirewall getNeutronFirewall(String uuid);
+
+    /**
+     * Applications call this interface method to return all Firewall objects
+     *
+     * @return List of OpenStackNetworks objects
+     */
+
+    public List<NeutronFirewall> getAllNeutronFirewalls();
+
+    /**
+     * Applications call this interface method to add a Firewall object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackNetwork object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addNeutronFirewall(NeutronFirewall input);
+
+    /**
+     * Applications call this interface method to remove a Neutron Firewall object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the Firewall object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeNeutronFirewall(String uuid);
+
+    /**
+     * Applications call this interface method to edit a Firewall object
+     *
+     * @param uuid
+     *            identifier of the Firewall object
+     * @param delta
+     *            OpenStackFirewall object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateNeutronFirewall(String uuid, NeutronFirewall delta);
+
+    /**
+     * Applications call this interface method to see if a MAC address is in use
+     *
+     * @param uuid
+     *            identifier of the Firewall object
+     * @return boolean on whether the macAddress is already associated with a
+     * port or not
+     */
+
+    public boolean neutronFirewallInUse(String uuid);
+
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallPolicyAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallPolicyAware.java
new file mode 100644 (file)
index 0000000..203d513
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Firewall Policys needs to implement
+ *
+ */
+
+public interface INeutronFirewallPolicyAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified firewallPolicy can be created
+     *
+     * @param firewallPolicy
+     *            instance of proposed new Firewall Policy object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreateNeutronFirewallPolicy(NeutronFirewallPolicy firewallPolicy);
+
+    /**
+     * Services provide this interface method for taking action after a firewallPolicy has been created
+     *
+     * @param firewallPolicy
+     *            instance of new Firewall Policy object
+     * @return void
+     */
+    public void neutronFirewallPolicyCreated(NeutronFirewallPolicy firewallPolicy);
+
+    /**
+     * Services provide this interface method to indicate if the specified firewallPolicy can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the firewallPolicy object using patch semantics
+     * @param original
+     *            instance of the Firewall Policy object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdateNeutronFirewallPolicy(NeutronFirewallPolicy delta, NeutronFirewallPolicy original);
+
+    /**
+     * Services provide this interface method for taking action after a firewallPolicy has been updated
+     *
+     * @param firewallPolicy
+     *            instance of modified Firewall Policy object
+     * @return void
+     */
+    public void neutronFirewallPolicyUpdated(NeutronFirewallPolicy firewallPolicy);
+
+    /**
+     * Services provide this interface method to indicate if the specified firewallPolicy can be deleted
+     *
+     * @param firewallPolicy
+     *            instance of the Firewall Policy object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeleteNeutronFirewallPolicy(NeutronFirewallPolicy firewallPolicy);
+
+    /**
+     * Services provide this interface method for taking action after a firewallPolicy has been deleted
+     *
+     * @param firewallPolicy
+     *            instance of deleted Firewall Policy object
+     * @return void
+     */
+    public void neutronFirewallPolicyDeleted(NeutronFirewallPolicy firewallPolicy);
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallPolicyCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallPolicyCRUD.java
new file mode 100644 (file)
index 0000000..6049656
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB OpenStack Firewall Policy objects
+ *
+ */
+
+public interface INeutronFirewallPolicyCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     *FirewallPolicy object exists
+     *
+     * @param uuid
+     *            UUID of the Firewall Policy object
+     * @return boolean
+     */
+
+    public boolean neutronFirewallPolicyExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * FirewallPolicy object exists
+     *
+     * @param uuid
+     *            UUID of the Firewall Policy object
+     * @return {@link NeutronFirewallPolicy}
+     *          OpenStackFirewallPolicy class
+     */
+
+    public NeutronFirewallPolicy getNeutronFirewallPolicy(String uuid);
+
+    /**
+     * Applications call this interface method to return all Firewall Policy objects
+     *
+     * @return List of OpenStack Firewall Policy objects
+     */
+
+    public List<NeutronFirewallPolicy> getAllNeutronFirewallPolicies();
+
+    /**
+     * Applications call this interface method to add a Firewall Policy object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackNetwork object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addNeutronFirewallPolicy(NeutronFirewallPolicy input);
+
+    /**
+     * Applications call this interface method to remove a Neutron FirewallPolicy object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the Firewall Policy object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeNeutronFirewallPolicy(String uuid);
+
+    /**
+     * Applications call this interface method to edit a FirewallPolicy object
+     *
+     * @param uuid
+     *            identifier of the Firewall Policy object
+     * @param delta
+     *            OpenStackFirewallPolicy object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateNeutronFirewallPolicy(String uuid, NeutronFirewallPolicy delta);
+
+    /**
+     * Applications call this interface method to see if a MAC address is in use
+     *
+     * @param uuid
+     *            identifier of the Firewall Policy object
+     * @return boolean on whether the macAddress is already associated with a
+     * port or not
+     */
+
+    public boolean neutronFirewallPolicyInUse(String uuid);
+
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallRuleAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallRuleAware.java
new file mode 100644 (file)
index 0000000..a663058
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Firewall Rules needs to implement
+ *
+ */
+
+public interface INeutronFirewallRuleAware {
+
+    /**
+     * Services provide this interface method to indicate if the specified firewallRule can be created
+     *
+     * @param firewallRule
+     *            instance of proposed new Firewall Rule object
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the create operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canCreateNeutronFirewallRule(NeutronFirewallRule firewallRule);
+
+    /**
+     * Services provide this interface method for taking action after a firewallRule has been created
+     *
+     * @param firewallRule
+     *            instance of new Firewall Rule object
+     * @return void
+     */
+    public void neutronFirewallRuleCreated(NeutronFirewallRule firewallRule);
+
+    /**
+     * Services provide this interface method to indicate if the specified firewallRule can be changed using the specified
+     * delta
+     *
+     * @param delta
+     *            updates to the firewallRule object using patch semantics
+     * @param original
+     *            instance of the Firewall Rule object to be updated
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the update operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canUpdateNeutronFirewallRule(NeutronFirewallRule delta, NeutronFirewallRule original);
+
+    /**
+     * Services provide this interface method for taking action after a firewallRule has been updated
+     *
+     * @param firewallRule
+     *            instance of modified Firewall Rule object
+     * @return void
+     */
+    public void neutronFirewallRuleUpdated(NeutronFirewallRule firewallRule);
+
+    /**
+     * Services provide this interface method to indicate if the specified firewallRule can be deleted
+     *
+     * @param firewallRule
+     *            instance of the Firewall Rule object to be deleted
+     * @return integer
+     *            the return value is understood to be a HTTP status code.  A return value outside of 200 through 299
+     *            results in the delete operation being interrupted and the returned status value reflected in the
+     *            HTTP response.
+     */
+    public int canDeleteNeutronFirewallRule(NeutronFirewallRule firewallRule);
+
+    /**
+     * Services provide this interface method for taking action after a firewallRule has been deleted
+     *
+     * @param firewallRule
+     *            instance of deleted Firewall Rule object
+     * @return void
+     */
+    public void neutronFirewallRuleDeleted(NeutronFirewallRule firewallRule);
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallRuleCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFirewallRuleCRUD.java
new file mode 100644 (file)
index 0000000..990896b
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB OpenStack Firewall Rule objects
+ *
+ */
+
+public interface INeutronFirewallRuleCRUD {
+    /**
+     * Applications call this interface method to determine if a particular
+     *FirewallRule object exists
+     *
+     * @param uuid
+     *            UUID of the Firewall Rule object
+     * @return boolean
+     */
+
+    public boolean neutronFirewallRuleExists(String uuid);
+
+    /**
+     * Applications call this interface method to return if a particular
+     * FirewallRule object exists
+     *
+     * @param uuid
+     *            UUID of the Firewall Rule object
+     * @return {@link NeutronFirewallRule}
+     *          OpenStackFirewall Rule class
+     */
+
+    public NeutronFirewallRule getNeutronFirewallRule(String uuid);
+
+    /**
+     * Applications call this interface method to return all Firewall Rule objects
+     *
+     * @return List of OpenStackNetworks objects
+     */
+
+    public List<NeutronFirewallRule> getAllNeutronFirewallRules();
+
+    /**
+     * Applications call this interface method to add a Firewall Rule object to the
+     * concurrent map
+     *
+     * @param input
+     *            OpenStackNetwork object
+     * @return boolean on whether the object was added or not
+     */
+
+    public boolean addNeutronFirewallRule(NeutronFirewallRule input);
+
+    /**
+     * Applications call this interface method to remove a Neutron FirewallRule object to the
+     * concurrent map
+     *
+     * @param uuid
+     *            identifier for the Firewall Rule object
+     * @return boolean on whether the object was removed or not
+     */
+
+    public boolean removeNeutronFirewallRule(String uuid);
+
+    /**
+     * Applications call this interface method to edit a FirewallRule object
+     *
+     * @param uuid
+     *            identifier of the Firewall Rule object
+     * @param delta
+     *            OpenStackFirewallRule object containing changes to apply
+     * @return boolean on whether the object was updated or not
+     */
+
+    public boolean updateNeutronFirewallRule(String uuid, NeutronFirewallRule delta);
+
+    /**
+     * Applications call this interface method to see if a MAC address is in use
+     *
+     * @param uuid
+     *            identifier of the Firewall Rule object
+     * @return boolean on whether the macAddress is already associated with a
+     * port or not
+     */
+
+    public boolean neutronFirewallRuleInUse(String uuid);
+
+}
index 21cfdb1305060d1bfa24ff32866f1ce0aa8509b5..6ce5499cdf9a2cc99ffda04d75d13a11d4c11bbb 100644 (file)
@@ -46,4 +46,19 @@ public class NeutronCRUDInterfaces {
         INeutronSecurityRuleCRUD answer = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, o);
         return answer;
     }
+
+    public static INeutronFirewallCRUD getINeutronFirewallCRUD(Object o) {
+        INeutronFirewallCRUD answer = (INeutronFirewallCRUD) ServiceHelper.getGlobalInstance(INeutronFirewallCRUD.class, o);
+        return answer;
+    }
+
+    public static INeutronFirewallPolicyCRUD getINeutronFirewallPolicyCRUD(Object o) {
+        INeutronFirewallPolicyCRUD answer = (INeutronFirewallPolicyCRUD) ServiceHelper.getGlobalInstance(INeutronFirewallPolicyCRUD.class, o);
+        return answer;
+    }
+
+    public static INeutronFirewallRuleCRUD getINeutronFirewallRuleCRUD(Object o) {
+        INeutronFirewallRuleCRUD answer = (INeutronFirewallRuleCRUD) ServiceHelper.getGlobalInstance(INeutronFirewallRuleCRUD.class, o);
+        return answer;
+    }
 }
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewall.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewall.java
new file mode 100644 (file)
index 0000000..39f04c9
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Firewall as a service
+ * (FWaaS) bindings. See OpenStack Network API
+ * v2.0 Reference for description of  the fields:
+ * Implemented fields are as follows:
+ *
+ * id                 uuid-str
+ * tenant_id          uuid-str
+ * name               String
+ * description        String
+ * admin_state_up     Bool
+ * status             String
+ * shared             Bool
+ * firewall_policy_id uuid-str
+ * http://docs.openstack.org/api/openstack-network/2.0/openstack-network.pdf
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronFirewall extends ConfigurationObject implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(name="id")
+    String firewallUUID;
+
+    @XmlElement (name="tenant_id")
+    String firewallTenantID;
+
+    @XmlElement (name="name")
+    String firewallName;
+
+    @XmlElement (name="description")
+    String firewallDescription;
+
+    @XmlElement (defaultValue="true", name="admin_state_up")
+    Boolean firewallAdminStateIsUp;
+
+    @XmlElement (name="status")
+    String firewallStatus;
+
+    @XmlElement (defaultValue="false", name="shared")
+    Boolean firewallIsShared;
+
+    @XmlElement (name="firewall_policy_id")
+    String neutronFirewallPolicyID;
+
+    public String getFirewallUUID() {
+        return firewallUUID;
+    }
+
+    public void setFirewallUUID(String firewallUUID) {
+        this.firewallUUID = firewallUUID;
+    }
+
+    public String getFirewallTenantID() {
+        return firewallTenantID;
+    }
+
+    public void setFirewallTenantID(String firewallTenantID) {
+        this.firewallTenantID = firewallTenantID;
+    }
+
+    public String getFirewallName() {
+        return firewallName;
+    }
+
+    public void setFirewallName(String firewallName) {
+        this.firewallName = firewallName;
+    }
+
+    public String getFirewallDescription() {
+        return firewallDescription;
+    }
+
+    public void setFirewallDescription(String firewallDescription) {
+        this.firewallDescription = firewallDescription;
+    }
+
+    public Boolean getFirewallAdminStateIsUp() {
+        return firewallAdminStateIsUp;
+    }
+
+    public void setFirewallAdminStateIsUp(Boolean firewallAdminStateIsUp) {
+        this.firewallAdminStateIsUp = firewallAdminStateIsUp;
+    }
+
+    public String getFirewallStatus() {
+        return firewallStatus;
+    }
+
+    public void setFirewallStatus(String firewallStatus) {
+        this.firewallStatus = firewallStatus;
+    }
+
+    public Boolean getFirewallIsShared() {
+        return firewallIsShared;
+    }
+
+    public void setFirewallIsShared(Boolean firewallIsShared) {
+        this.firewallIsShared = firewallIsShared;
+    }
+
+    public String getFirewallPolicyID() {
+        return neutronFirewallPolicyID;
+    }
+
+    public void setNeutronFirewallPolicyID(String firewallPolicy) {
+        this.neutronFirewallPolicyID = firewallPolicy;
+    }
+
+    public NeutronFirewall extractFields(List<String> fields) {
+        NeutronFirewall ans = new NeutronFirewall();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setFirewallUUID(this.getFirewallUUID());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setFirewallTenantID(this.getFirewallTenantID());
+            }
+            if (s.equals("name")) {
+                ans.setFirewallName(this.getFirewallName());
+            }
+            if(s.equals("description")) {
+                ans.setFirewallDescription(this.getFirewallDescription());
+            }
+            if (s.equals("admin_state_up")) {
+                ans.setFirewallAdminStateIsUp(firewallAdminStateIsUp);
+            }
+            if (s.equals("status")) {
+                ans.setFirewallStatus(this.getFirewallStatus());
+            }
+            if (s.equals("shared")) {
+                ans.setFirewallIsShared(firewallIsShared);
+            }
+            if (s.equals("firewall_policy_id")) {
+                ans.setNeutronFirewallPolicyID(this.getFirewallPolicyID());
+            }
+        }
+        return ans;
+    }
+
+    @Override
+    public String toString() {
+        return "NeutronFirewall{" +
+            "firewallUUID='" + firewallUUID + '\'' +
+            ", firewallTenantID='" + firewallTenantID + '\'' +
+            ", firewallName='" + firewallName + '\'' +
+            ", firewallDescription='" + firewallDescription + '\'' +
+            ", firewallAdminStateIsUp=" + firewallAdminStateIsUp +
+            ", firewallStatus='" + firewallStatus + '\'' +
+            ", firewallIsShared=" + firewallIsShared +
+            ", firewallRulePolicyID=" + neutronFirewallPolicyID +
+            '}';
+    }
+}
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewallPolicy.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewallPolicy.java
new file mode 100644 (file)
index 0000000..46436b5
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Firewall as a service
+ * (FWaaS) bindings. See OpenStack Network API
+ * v2.0 Reference for description of  the fields.
+ * The implemented fields are as follows:
+ *
+ * id             uuid-str
+ * tenant_id      uuid-str
+ * name           String
+ * description    String
+ * shared         Boolean
+ * firewall_rules List
+ * audited        Boolean
+ * http://docs.openstack.org/api/openstack-network/2.0/openstack-network.pdf
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronFirewallPolicy extends ConfigurationObject implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(name="id")
+    String firewallPolicyUUID;
+
+    @XmlElement (name="tenant_id")
+    String firewallPolicyTenantID;
+
+    @XmlElement (name="name")
+    String firewallPolicyName;
+
+    @XmlElement (name="description")
+    String firewallPolicyDescription;
+
+    @XmlElement (defaultValue="false", name="shared")
+    Boolean firewallPolicyIsShared;
+
+    @XmlElement (name="firewall_rules")
+    List<String> firewallPolicyRules;
+
+    @XmlElement (defaultValue="false", name="audited")
+    String firewallPolicyIsAudited;
+
+    public String getFirewallPolicyIsAudited() {
+        return firewallPolicyIsAudited;
+    }
+
+    public void setFirewallPolicyIsAudited(String firewallPolicyIsAudited) {
+        this.firewallPolicyIsAudited = firewallPolicyIsAudited;
+    }
+
+    public void setFirewallPolicyRules(List<String> firewallPolicyRules) {
+        this.firewallPolicyRules = firewallPolicyRules;
+    }
+
+    public List<String> getFirewallPolicyRules() {
+        return firewallPolicyRules;
+    }
+
+    public Boolean getFirewallPolicyIsShared() {
+        return firewallPolicyIsShared;
+    }
+
+    public void setFirewallPolicyIsShared(Boolean firewallPolicyIsShared) {
+        this.firewallPolicyIsShared = firewallPolicyIsShared;
+    }
+
+    public String getFirewallPolicyDescription() {
+        return firewallPolicyDescription;
+    }
+
+    public void setFirewallPolicyDescription(String firewallPolicyDescription) {
+        this.firewallPolicyDescription = firewallPolicyDescription;
+    }
+
+    public String getFirewallPolicyName() {
+        return firewallPolicyName;
+    }
+
+    public void setFirewallPolicyName(String firewallPolicyName) {
+        this.firewallPolicyName = firewallPolicyName;
+    }
+
+    public String getFirewallPolicyTenantID() {
+        return firewallPolicyTenantID;
+    }
+
+    public void setFirewallPolicyTenantID(String firewallPolicyTenantID) {
+        this.firewallPolicyTenantID = firewallPolicyTenantID;
+    }
+
+    public String getFirewallPolicyUUID() {
+        return firewallPolicyUUID;
+    }
+
+    public void setFirewallPolicyUUID(String firewallPolicyUUID) {
+        this.firewallPolicyUUID = firewallPolicyUUID;
+    }
+
+    public NeutronFirewallPolicy extractFields(List<String> fields) {
+        NeutronFirewallPolicy ans = new NeutronFirewallPolicy();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setFirewallPolicyUUID(this.getFirewallPolicyUUID());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setFirewallPolicyTenantID(this.getFirewallPolicyTenantID());
+            }
+            if (s.equals("name")) {
+                ans.setFirewallPolicyName(this.getFirewallPolicyName());
+            }
+            if(s.equals("description")) {
+                ans.setFirewallPolicyDescription(this.getFirewallPolicyDescription());
+            }
+            if (s.equals("shared")) {
+                ans.setFirewallPolicyIsShared(firewallPolicyIsShared);
+            }
+            if (s.equals("firewall_rules")) {
+                List<String> firewallRuleList = new ArrayList<String>();
+                firewallRuleList.addAll(this.getFirewallPolicyRules());
+                ans.setFirewallPolicyRules(firewallRuleList);
+            }
+            if (s.equals("audited")) {
+                ans.setFirewallPolicyIsAudited(firewallPolicyIsAudited);
+            }
+        }
+        return ans;
+    }
+
+    @Override
+    public String toString() {
+        return "NeutronFirewallPolicy{" +
+            "firewallPolicyUUID='" + firewallPolicyUUID + '\'' +
+            ", firewallPolicyTenantID='" + firewallPolicyTenantID + '\'' +
+            ", firewallPolicyName='" + firewallPolicyName + '\'' +
+            ", firewallPolicyDescription='" + firewallPolicyDescription + '\'' +
+            ", firewallPolicyIsShared=" + firewallPolicyIsShared +
+            ", firewallPolicyRules=" + firewallPolicyRules +
+            ", firewallPolicyIsAudited='" + firewallPolicyIsAudited + '\'' +
+            '}';
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewallRule.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFirewallRule.java
new file mode 100644 (file)
index 0000000..63a65a2
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron;
+
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Firewall as a service
+ * (FWaaS) bindings. See OpenStack Network API
+ * v2.0 Reference for description of  the fields.
+ * The implemented fields are as follows:
+ *
+ * tenant_id               uuid-str
+ * name                    String
+ * description             String
+ * admin_state_up          Bool
+ * status                  String
+ * shared                  Bool
+ * firewall_policy_id      uuid-str
+ * protocol                String
+ * ip_version              Integer
+ * source_ip_address       String (IP addr or CIDR)
+ * destination_ip_address  String (IP addr or CIDR)
+ * source_port             Integer
+ * destination_port        Integer
+ * position                Integer
+ * action                  String
+ * enabled                 Bool
+ * id                      uuid-str
+ * http://docs.openstack.org/api/openstack-network/2.0/openstack-network.pdf
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronFirewallRule extends ConfigurationObject implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(name = "id")
+    String firewallRuleUUID;
+
+    @XmlElement(name = "tenant_id")
+    String firewallRuleTenantID;
+
+    @XmlElement(name = "name")
+    String firewallRuleName;
+
+    @XmlElement(name = "description")
+    String firewallRuleDescription;
+
+    @XmlElement(defaultValue = "true", name = "admin_state_up")
+    Boolean firewallRuleAdminStateIsUp;
+
+    @XmlElement(name = "status")
+    String firewallRuleStatus;
+
+    @XmlElement(defaultValue = "false", name = "shared")
+    Boolean firewallRuleIsShared;
+
+    @XmlElement(name = "firewall_policy_id")
+    String firewallRulePolicyID;
+
+    @XmlElement(name = "protocol")
+    String firewallRuleProtocol;
+
+    @XmlElement(name = "ip_version")
+    Integer firewallRuleIpVer;
+
+    @XmlElement(name = "source_ip_address")
+    String firewallRuleSrcIpAddr;
+
+    @XmlElement(name = "destination_ip_address")
+    String firewallRuleDstIpAddr;
+
+    @XmlElement(name = "source_port")
+    Integer firewallRuleSrcPort;
+
+    @XmlElement(name = "destination_port")
+    Integer firewallRuleDstPort;
+
+    @XmlElement(name = "position")
+    Integer firewallRulePosition;
+
+    @XmlElement(name = "action")
+    String firewallRuleAction;
+
+    @XmlElement(name = "enabled")
+    Boolean firewallRuleIsEnabled;
+
+    public Boolean getFirewallRuleIsEnabled() {
+        return firewallRuleIsEnabled;
+    }
+
+    public void setFirewallRuleIsEnabled(Boolean firewallRuleIsEnabled) {
+        this.firewallRuleIsEnabled = firewallRuleIsEnabled;
+    }
+
+    public String getFirewallRuleAction() {
+        return firewallRuleAction;
+    }
+
+    public void setFirewallRuleAction(String firewallRuleAction) {
+        this.firewallRuleAction = firewallRuleAction;
+    }
+
+    public Integer getFirewallRulePosition() {
+        return firewallRulePosition;
+    }
+
+    public void setFirewallRulePosition(Integer firewallRulePosition) {
+        this.firewallRulePosition = firewallRulePosition;
+    }
+
+    public Integer getFirewallRuleDstPort() {
+        return firewallRuleDstPort;
+    }
+
+    public void setFirewallRuleDstPort(Integer firewallRuleDstPort) {
+        this.firewallRuleDstPort = firewallRuleDstPort;
+    }
+
+    public Integer getFirewallRuleSrcPort() {
+        return firewallRuleSrcPort;
+    }
+
+    public void setFirewallRuleSrcPort(Integer firewallRuleSrcPort) {
+        this.firewallRuleSrcPort = firewallRuleSrcPort;
+    }
+
+    public String getFirewallRuleDstIpAddr() {
+        return firewallRuleDstIpAddr;
+    }
+
+    public void setFirewallRuleDstIpAddr(String firewallRuleDstIpAddr) {
+        this.firewallRuleDstIpAddr = firewallRuleDstIpAddr;
+    }
+
+    public String getFirewallRuleSrcIpAddr() {
+        return firewallRuleSrcIpAddr;
+    }
+
+    public void setFirewallRuleSrcIpAddr(String firewallRuleSrcIpAddr) {
+        this.firewallRuleSrcIpAddr = firewallRuleSrcIpAddr;
+    }
+
+    public Integer getFirewallRuleIpVer() {
+        return firewallRuleIpVer;
+    }
+
+    public void setFirewallRuleIpVer(Integer firewallRuleIpVer) {
+        this.firewallRuleIpVer = firewallRuleIpVer;
+    }
+
+    public String getFirewallRuleProtocol() {
+        return firewallRuleProtocol;
+    }
+
+    public void setFirewallRuleProtocol(String firewallRuleProtocol) {
+        this.firewallRuleProtocol = firewallRuleProtocol;
+    }
+
+    public String getFirewallRulePolicyID() {
+        return firewallRulePolicyID;
+    }
+
+    public void setFirewallRulesPolicyID(String firewallRulePolicyID) {
+        this.firewallRulePolicyID = firewallRulePolicyID;
+    }
+
+    public Boolean getFirewallRuleIsShared() {
+        return firewallRuleIsShared;
+    }
+
+    public void setFirewallRuleIsShared(Boolean firewallRuleIsShared) {
+        this.firewallRuleIsShared = firewallRuleIsShared;
+    }
+
+    public String getFirewallRuleStatus() {
+        return firewallRuleStatus;
+    }
+
+    public void setFirewallRuleStatus(String firewallRuleStatus) {
+        this.firewallRuleStatus = firewallRuleStatus;
+    }
+
+    public Boolean getFirewallRuleAdminStateIsUp() {
+        return firewallRuleAdminStateIsUp;
+    }
+
+    public void setFirewallRuleAdminStateIsUp(Boolean firewallRuleAdminStateIsUp) {
+        this.firewallRuleAdminStateIsUp = firewallRuleAdminStateIsUp;
+    }
+
+    public String getFirewallRuleDescription() {
+        return firewallRuleDescription;
+    }
+
+    public void setFirewallRuleDescription(String firewallRuleDescription) {
+        this.firewallRuleDescription = firewallRuleDescription;
+    }
+
+    public String getFirewallRuleName() {
+        return firewallRuleName;
+    }
+
+    public void setFirewallRuleName(String firewallRuleName) {
+        this.firewallRuleName = firewallRuleName;
+    }
+
+    public String getFirewallRuleTenantID() {
+        return firewallRuleTenantID;
+    }
+
+    public void setFirewallRuleTenantID(String firewallRuleTenantID) {
+        this.firewallRuleTenantID = firewallRuleTenantID;
+    }
+
+    public String getFirewallRuleUUID() {
+        return firewallRuleUUID;
+    }
+
+    public void setFirewallRuleUUID(String firewallRuleUUID) {
+        this.firewallRuleUUID = firewallRuleUUID;
+    }
+
+    public NeutronFirewallRule extractFields(List<String> fields) {
+        NeutronFirewallRule ans = new NeutronFirewallRule();
+        Iterator<String> i = fields.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (s.equals("id")) {
+                ans.setFirewallRuleUUID(this.getFirewallRuleUUID());
+            }
+            if (s.equals("tenant_id")) {
+                ans.setFirewallRuleTenantID(this.getFirewallRuleTenantID());
+            }
+            if (s.equals("name")) {
+                ans.setFirewallRuleName(this.getFirewallRuleName());
+            }
+            if (s.equals("description")) {
+                ans.setFirewallRuleDescription(this.getFirewallRuleDescription());
+            }
+            if (s.equals("admin_state_up")) {
+                ans.setFirewallRuleAdminStateIsUp(firewallRuleAdminStateIsUp);
+            }
+            if (s.equals("status")) {
+                ans.setFirewallRuleStatus(this.getFirewallRuleStatus());
+            }
+            if (s.equals("shared")) {
+                ans.setFirewallRuleIsShared(firewallRuleIsShared);
+            }
+            if (s.equals("firewall_policy_id")) {
+                ans.setFirewallRulesPolicyID(this.getFirewallRulePolicyID());
+            }
+            if (s.equals("protocol")) {
+                ans.setFirewallRuleProtocol(this.getFirewallRuleProtocol());
+            }
+            if (s.equals("source_ip_address")) {
+                ans.setFirewallRuleSrcIpAddr(this.getFirewallRuleSrcIpAddr());
+            }
+            if (s.equals("destination_ip_address")) {
+                ans.setFirewallRuleDstIpAddr(this.getFirewallRuleDstIpAddr());
+            }
+            if (s.equals("source_port")) {
+                ans.setFirewallRuleSrcPort(this.getFirewallRuleSrcPort());
+            }
+            if (s.equals("destination_port")) {
+                ans.setFirewallRuleDstPort(this.getFirewallRuleDstPort());
+            }
+            if (s.equals("position")) {
+                ans.setFirewallRulePosition(this.getFirewallRulePosition());
+            }
+            if (s.equals("action")) {
+                ans.setFirewallRuleAction(this.getFirewallRuleAction());
+            }
+            if (s.equals("enabled")) {
+                ans.setFirewallRuleIsEnabled(firewallRuleIsEnabled);
+            }
+
+        }
+        return ans;
+    }
+
+    @Override
+    public String toString() {
+        return "firewallPolicyRules{" +
+            "firewallRuleUUID='" + firewallRuleUUID + '\'' +
+            ", firewallRuleTenantID='" + firewallRuleTenantID + '\'' +
+            ", firewallRuleName='" + firewallRuleName + '\'' +
+            ", firewallRuleDescription='" + firewallRuleDescription + '\'' +
+            ", firewallRuleAdminStateIsUp=" + firewallRuleAdminStateIsUp +
+            ", firewallRuleStatus='" + firewallRuleStatus + '\'' +
+            ", firewallRuleIsShared=" + firewallRuleIsShared +
+            ", firewallRulePolicyID=" + firewallRulePolicyID +
+            ", firewallRuleProtocol='" + firewallRuleProtocol + '\'' +
+            ", firewallRuleIpVer=" + firewallRuleIpVer +
+            ", firewallRuleSrcIpAddr='" + firewallRuleSrcIpAddr + '\'' +
+            ", firewallRuleDstIpAddr='" + firewallRuleDstIpAddr + '\'' +
+            ", firewallRuleSrcPort=" + firewallRuleSrcPort +
+            ", firewallRuleDstPort=" + firewallRuleDstPort +
+            ", firewallRulePosition=" + firewallRulePosition +
+            ", firewallRuleAction='" + firewallRuleAction + '\'' +
+            ", firewallRuleIsEnabled=" + firewallRuleIsEnabled +
+            '}';
+    }
+
+    public void initDefaults() {
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallNorthbound.java
new file mode 100644 (file)
index 0000000..204c9f5
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewall;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Neutron Northbound REST APIs for Firewall.<br>
+ * This class provides REST APIs for managing neutron Firewall
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+@Path("/fw/firewalls")
+public class NeutronFirewallNorthbound {
+
+    private NeutronFirewall extractFields(NeutronFirewall o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Firewalls */
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+
+    public Response listGroups(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // OpenStack firewall attributes
+            @QueryParam("id") String queryFirewallUUID,
+            @QueryParam("tenant_id") String queryFirewallTenantID,
+            @QueryParam("name") String queryFirewallName,
+            @QueryParam("description") String queryFirewallDescription,
+            @QueryParam("shared") Boolean queryFirewallAdminStateIsUp,
+            @QueryParam("status") String queryFirewallStatus,
+            @QueryParam("shared") Boolean queryFirewallIsShared,
+            @QueryParam("firewall_policy_id") String queryFirewallPolicyID,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+    ) {
+        INeutronFirewallCRUD firewallInterface = NeutronCRUDInterfaces.getINeutronFirewallCRUD(this);
+        INeutronFirewallRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronFirewallRuleCRUD(this);
+
+        if (firewallInterface == null) {
+            throw new ServiceUnavailableException("Firewall CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronFirewall> allFirewalls = firewallInterface.getAllNeutronFirewalls();
+        List<NeutronFirewall> ans = new ArrayList<NeutronFirewall>();
+        Iterator<NeutronFirewall> i = allFirewalls.iterator();
+        while (i.hasNext()) {
+            NeutronFirewall nsg = i.next();
+            if ((queryFirewallUUID == null ||
+                queryFirewallUUID.equals(nsg.getFirewallUUID())) &&
+                (queryFirewallTenantID == null ||
+                    queryFirewallTenantID.equals(nsg.getFirewallTenantID())) &&
+                (queryFirewallName == null ||
+                    queryFirewallName.equals(nsg.getFirewallName())) &&
+                (queryFirewallDescription == null ||
+                    queryFirewallDescription.equals(nsg.getFirewallDescription())) &&
+                (queryFirewallAdminStateIsUp == null ||
+                    queryFirewallAdminStateIsUp.equals(nsg.getFirewallAdminStateIsUp())) &&
+                (queryFirewallStatus == null ||
+                    queryFirewallStatus.equals(nsg.getFirewallStatus())) &&
+                (queryFirewallIsShared == null ||
+                    queryFirewallIsShared.equals(nsg.getFirewallIsShared())) &&
+                (queryFirewallPolicyID == null ||
+                    queryFirewallPolicyID.equals(nsg.getFirewallPolicyID()))) {
+                if (fields.size() > 0) {
+                    ans.add(extractFields(nsg,fields));
+                } else {
+                    ans.add(nsg);
+                }
+            }
+        }
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronFirewallRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Firewall */
+
+    @Path("{firewallUUID}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response showFirewall(@PathParam("firewallUUID") String firewallUUID,
+                                      // return fields
+                                      @QueryParam("fields") List<String> fields) {
+        INeutronFirewallCRUD firewallInterface = NeutronCRUDInterfaces.getINeutronFirewallCRUD(this);
+        if (firewallInterface == null) {
+            throw new ServiceUnavailableException("Firewall CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!firewallInterface.neutronFirewallExists(firewallUUID)) {
+            throw new ResourceNotFoundException("Firewall UUID does not exist.");
+        }
+        if (fields.size() > 0) {
+            NeutronFirewall ans = firewallInterface.getNeutronFirewall(firewallUUID);
+            return Response.status(200).entity(
+                    new NeutronFirewallRequest(extractFields(ans, fields))).build();
+        } else {
+            return Response.status(200).entity(new NeutronFirewallRequest(firewallInterface.getNeutronFirewall(firewallUUID))).build();
+        }
+    }
+
+    /**
+     * Creates new Firewall */
+
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 201, condition = "Created"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response createFirewalls(final NeutronFirewallRequest input) {
+        INeutronFirewallCRUD firewallInterface = NeutronCRUDInterfaces.getINeutronFirewallCRUD(this);
+        if (firewallInterface == null) {
+            throw new ServiceUnavailableException("Firewall CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (input.isSingleton()) {
+            NeutronFirewall singleton = input.getSingleton();
+
+            /*
+             *  Verify that the Firewall doesn't already exist.
+             */
+            if (firewallInterface.neutronFirewallExists(singleton.getFirewallUUID())) {
+                throw new BadRequestException("Firewall UUID already exists");
+            }
+            firewallInterface.addNeutronFirewall(singleton);
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                    int status = service.canCreateNeutronFirewall(singleton);
+                    if (status < 200 || status > 299) {
+                        return Response.status(status).build();
+                    }
+                }
+            }
+            firewallInterface.addNeutronFirewall(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                    service.neutronFirewallCreated(singleton);
+                }
+            }
+        } else {
+            List<NeutronFirewall> bulk = input.getBulk();
+            Iterator<NeutronFirewall> i = bulk.iterator();
+            HashMap<String, NeutronFirewall> testMap = new HashMap<String, NeutronFirewall>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronFirewall test = i.next();
+
+                /*
+                 *  Verify that the secruity group doesn't already exist
+                 */
+                if (firewallInterface.neutronFirewallExists(test.getFirewallUUID())) {
+                    throw new BadRequestException("Firewall UUID already is already created");
+                }
+                if (testMap.containsKey(test.getFirewallUUID())) {
+                    throw new BadRequestException("Firewall UUID already exists");
+                }
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                        int status = service.canCreateNeutronFirewall(test);
+                        if (status < 200 || status > 299) {
+                            return Response.status(status).build();
+                        }
+                    }
+                }
+            }
+
+            /*
+             * now, each element of the bulk request can be added to the cache
+             */
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronFirewall test = i.next();
+                firewallInterface.addNeutronFirewall(test);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                        service.neutronFirewallCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Firewall */
+
+    @Path("{firewallUUID}")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response updateFirewall(
+            @PathParam("firewallUUID") String firewallUUID, final NeutronFirewallRequest input) {
+        INeutronFirewallCRUD firewallInterface = NeutronCRUDInterfaces.getINeutronFirewallCRUD(this);
+        if (firewallInterface == null) {
+            throw new ServiceUnavailableException("Firewall CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Firewall exists and there is only one delta provided
+         */
+        if (!firewallInterface.neutronFirewallExists(firewallUUID)) {
+            throw new ResourceNotFoundException("Firewall UUID does not exist.");
+        }
+        if (!input.isSingleton()) {
+            throw new BadRequestException("Only singleton edit supported");
+        }
+        NeutronFirewall delta = input.getSingleton();
+        NeutronFirewall original = firewallInterface.getNeutronFirewall(firewallUUID);
+
+        /*
+         * updates restricted by Neutron
+         */
+        if (delta.getFirewallUUID() != null ||
+                delta.getFirewallTenantID() != null ||
+                delta.getFirewallName() != null ||
+                delta.getFirewallDescription() != null ||
+                delta.getFirewallAdminStateIsUp() != null ||
+                delta.getFirewallStatus() != null ||
+                delta.getFirewallIsShared() != null ||
+                delta.getFirewallPolicyID() != null) {
+            throw new BadRequestException("Attribute edit blocked by Neutron");
+        }
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                int status = service.canUpdateNeutronFirewall(delta, original);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * update the object and return it
+         */
+        firewallInterface.updateNeutronFirewall(firewallUUID, delta);
+        NeutronFirewall updatedFirewall = firewallInterface.getNeutronFirewall(firewallUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                service.neutronFirewallUpdated(updatedFirewall);
+            }
+        }
+        return Response.status(200).entity(new NeutronFirewallRequest(firewallInterface.getNeutronFirewall(firewallUUID))).build();
+    }
+
+    /**
+     * Deletes a Firewall */
+
+    @Path("{firewallUUID}")
+    @DELETE
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response deleteFirewall(
+            @PathParam("firewallUUID") String firewallUUID) {
+        INeutronFirewallCRUD firewallInterface = NeutronCRUDInterfaces.getINeutronFirewallCRUD(this);
+        if (firewallInterface == null) {
+            throw new ServiceUnavailableException("Firewall CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Firewall exists and it isn't currently in use
+         */
+        if (!firewallInterface.neutronFirewallExists(firewallUUID)) {
+            throw new ResourceNotFoundException("Firewall UUID does not exist.");
+        }
+        if (firewallInterface.neutronFirewallInUse(firewallUUID)) {
+            return Response.status(409).build();
+        }
+        NeutronFirewall singleton = firewallInterface.getNeutronFirewall(firewallUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                int status = service.canDeleteNeutronFirewall(singleton);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * remove it and return 204 status
+         */
+        firewallInterface.removeNeutronFirewall(firewallUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallAware service = (INeutronFirewallAware) instance;
+                service.neutronFirewallDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyNorthbound.java
new file mode 100644 (file)
index 0000000..bfe2c92
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallPolicyAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallPolicyCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewallPolicy;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Neutron Northbound REST APIs for Firewall Policies.<br>
+ * This class provides REST APIs for managing neutron Firewall Policies
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+@Path("/fw/firewalls_policies")
+public class NeutronFirewallPolicyNorthbound {
+
+    private NeutronFirewallPolicy extractFields(NeutronFirewallPolicy o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Firewall Policies */
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+
+    public Response listGroups(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // OpenStack Firewall Policy attributes
+            @QueryParam("id") String queryFirewallPolicyUUID,
+            @QueryParam("tenant_id") String queryFirewallPolicyTenantID,
+            @QueryParam("name") String queryFirewallPolicyName,
+            @QueryParam("description") String querySecurityPolicyDescription,
+            @QueryParam("shared") String querySecurityPolicyIsShared,
+            @QueryParam("firewall_rules") List querySecurityPolicyFirewallRules,
+            @QueryParam("audited") Boolean querySecurityPolicyIsAudited,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+    ) {
+        INeutronFirewallPolicyCRUD firewallPolicyInterface = NeutronCRUDInterfaces.getINeutronFirewallPolicyCRUD(this);
+
+        if (firewallPolicyInterface == null) {
+            throw new ServiceUnavailableException("Firewall Policy CRUD Interface "
+                + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronFirewallPolicy> allFirewallPolicies = firewallPolicyInterface.getAllNeutronFirewallPolicies();
+        List<NeutronFirewallPolicy> ans = new ArrayList<NeutronFirewallPolicy>();
+        Iterator<NeutronFirewallPolicy> i = allFirewallPolicies.iterator();
+        while (i.hasNext()) {
+            NeutronFirewallPolicy nsg = i.next();
+            if ((queryFirewallPolicyUUID == null ||
+                queryFirewallPolicyUUID.equals(nsg.getFirewallPolicyUUID())) &&
+                (queryFirewallPolicyTenantID == null ||
+                    queryFirewallPolicyTenantID.equals(nsg.getFirewallPolicyTenantID())) &&
+                (queryFirewallPolicyName == null ||
+                    queryFirewallPolicyName.equals(nsg.getFirewallPolicyName())) &&
+                (querySecurityPolicyDescription == null ||
+                    querySecurityPolicyDescription.equals(nsg.getFirewallPolicyDescription())) &&
+                (querySecurityPolicyIsShared == null ||
+                    querySecurityPolicyIsShared.equals(nsg.getFirewallPolicyIsShared())) &&
+                (querySecurityPolicyFirewallRules.size() == 0 ||
+                    querySecurityPolicyFirewallRules.equals(nsg.getFirewallPolicyRules())) &&
+                (querySecurityPolicyIsAudited == null ||
+                    querySecurityPolicyIsAudited.equals(nsg.getFirewallPolicyIsAudited()))) {
+                if (fields.size() > 0) {
+                    ans.add(extractFields(nsg,fields));
+                } else {
+                    ans.add(nsg);
+                }
+            }
+        } // ans.add((NeutronFirewallPolicy) rules);
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronFirewallPolicyRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Firewall Policy */
+
+    @Path("{firewallPolicyUUID}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response showFirewallPolicy(@PathParam("firewallPolicyUUID") String firewallPolicyUUID,
+                                      // return fields
+                                      @QueryParam("fields") List<String> fields) {
+        INeutronFirewallPolicyCRUD firewallPolicyInterface = NeutronCRUDInterfaces.getINeutronFirewallPolicyCRUD(this);
+        if (firewallPolicyInterface == null) {
+            throw new ServiceUnavailableException("Firewall Policy CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!firewallPolicyInterface.neutronFirewallPolicyExists(firewallPolicyUUID)) {
+            throw new ResourceNotFoundException("Firewall Policy UUID does not exist.");
+        }
+        if (fields.size() > 0) {
+            NeutronFirewallPolicy ans = firewallPolicyInterface.getNeutronFirewallPolicy(firewallPolicyUUID);
+            return Response.status(200).entity(
+                    new NeutronFirewallPolicyRequest(extractFields(ans, fields))).build();
+        } else {
+            return Response.status(200).entity(new NeutronFirewallPolicyRequest(firewallPolicyInterface.getNeutronFirewallPolicy(firewallPolicyUUID))).build();
+        }
+    }
+
+    /**
+     * Creates new Firewall Policy
+     * */
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @StatusCodes({
+            @ResponseCode(code = 201, condition = "Created"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response createFirewallPolicies(final NeutronFirewallPolicyRequest input) {
+        INeutronFirewallPolicyCRUD firewallPolicyInterface = NeutronCRUDInterfaces.getINeutronFirewallPolicyCRUD(this);
+        if (firewallPolicyInterface == null) {
+            throw new ServiceUnavailableException("Firewall Policy CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (input.isSingleton()) {
+            NeutronFirewallPolicy singleton = input.getSingleton();
+
+            /*
+             *  Verify that the Firewall Policy doesn't already exist.
+             */
+            if (firewallPolicyInterface.neutronFirewallPolicyExists(singleton.getFirewallPolicyUUID())) {
+                throw new BadRequestException("Firewall Policy UUID already exists");
+            }
+            firewallPolicyInterface.addNeutronFirewallPolicy(singleton);
+
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallPolicyAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                    int status = service.canCreateNeutronFirewallPolicy(singleton);
+                    if (status < 200 || status > 299) {
+                        return Response.status(status).build();
+                    }
+                }
+            }
+            firewallPolicyInterface.addNeutronFirewallPolicy(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                    service.neutronFirewallPolicyCreated(singleton);
+                }
+            }
+        } else {
+            List<NeutronFirewallPolicy> bulk = input.getBulk();
+            Iterator<NeutronFirewallPolicy> i = bulk.iterator();
+            HashMap<String, NeutronFirewallPolicy> testMap = new HashMap<String, NeutronFirewallPolicy>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallPolicyAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronFirewallPolicy test = i.next();
+
+                /*
+                 *  Verify that the firewall policy doesn't already exist
+                 */
+
+                if (firewallPolicyInterface.neutronFirewallPolicyExists(test.getFirewallPolicyUUID())) {
+                    throw new BadRequestException("Firewall Policy UUID already is already created");
+                }
+                if (testMap.containsKey(test.getFirewallPolicyUUID())) {
+                    throw new BadRequestException("Firewall Policy UUID already exists");
+                }
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                        int status = service.canCreateNeutronFirewallPolicy(test);
+                        if (status < 200 || status > 299) {
+                            return Response.status(status).build();
+                        }
+                    }
+                }
+            }
+            /*
+             * now, each element of the bulk request can be added to the cache
+             */
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronFirewallPolicy test = i.next();
+                firewallPolicyInterface.addNeutronFirewallPolicy(test);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                        service.neutronFirewallPolicyCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Firewall Policy
+     */
+    @Path("{firewallPolicyUUID}")
+    @PUT
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    //@TypeHint(OpenStackSubnets.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response updateFirewallPolicy(
+            @PathParam("firewallPolicyUUID") String firewallPolicyUUID, final NeutronFirewallPolicyRequest input) {
+        INeutronFirewallPolicyCRUD firewallPolicyInterface = NeutronCRUDInterfaces.getINeutronFirewallPolicyCRUD(this);
+        if (firewallPolicyInterface == null) {
+            throw new ServiceUnavailableException("Firewall Policy CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Firewall Policy exists and there is only one delta provided
+         */
+        if (!firewallPolicyInterface.neutronFirewallPolicyExists(firewallPolicyUUID)) {
+            throw new ResourceNotFoundException("Firewall Policy UUID does not exist.");
+        }
+        if (!input.isSingleton()) {
+            throw new BadRequestException("Only singleton edit supported");
+        }
+        NeutronFirewallPolicy delta = input.getSingleton();
+        NeutronFirewallPolicy original = firewallPolicyInterface.getNeutronFirewallPolicy(firewallPolicyUUID);
+
+        /*
+         * updates restricted by Neutron
+         */
+        if (delta.getFirewallPolicyUUID() != null ||
+                delta.getFirewallPolicyTenantID() != null ||
+                delta.getFirewallPolicyName() != null ||
+                delta.getFirewallPolicyDescription() != null ||
+                delta.getFirewallPolicyIsShared() != null ||
+                delta.getFirewallPolicyRules().size() > 0 ||
+                delta.getFirewallPolicyIsAudited() != null) {
+            throw new BadRequestException("Attribute edit blocked by Neutron");
+        }
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallPolicyAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                int status = service.canUpdateNeutronFirewallPolicy(delta, original);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * update the object and return it
+         */
+        firewallPolicyInterface.updateNeutronFirewallPolicy(firewallPolicyUUID, delta);
+        NeutronFirewallPolicy updatedFirewallPolicy = firewallPolicyInterface.getNeutronFirewallPolicy(firewallPolicyUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                service.neutronFirewallPolicyUpdated(updatedFirewallPolicy);
+            }
+        }
+        return Response.status(200).entity(new NeutronFirewallPolicyRequest(firewallPolicyInterface.getNeutronFirewallPolicy(firewallPolicyUUID))).build();
+    }
+
+    /**
+     * Deletes a Firewall Policy */
+
+    @Path("{firewallPolicyUUID}")
+    @DELETE
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented") })
+    public Response deleteFirewallPolicy(
+            @PathParam("firewallPolicyUUID") String firewallPolicyUUID) {
+        INeutronFirewallPolicyCRUD firewallPolicyInterface = NeutronCRUDInterfaces.getINeutronFirewallPolicyCRUD(this);
+        if (firewallPolicyInterface == null) {
+            throw new ServiceUnavailableException("Firewall Policy CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Firewall Policy exists and it isn't currently in use
+         */
+        if (!firewallPolicyInterface.neutronFirewallPolicyExists(firewallPolicyUUID)) {
+            throw new ResourceNotFoundException("Firewall Policy UUID does not exist.");
+        }
+        if (firewallPolicyInterface.neutronFirewallPolicyInUse(firewallPolicyUUID)) {
+            return Response.status(409).build();
+        }
+        NeutronFirewallPolicy singleton = firewallPolicyInterface.getNeutronFirewallPolicy(firewallPolicyUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallPolicyAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                int status = service.canDeleteNeutronFirewallPolicy(singleton);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        firewallPolicyInterface.removeNeutronFirewallPolicy(firewallPolicyUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance;
+                service.neutronFirewallPolicyDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyRequest.java
new file mode 100644 (file)
index 0000000..473846a
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewallPolicy;
+
+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 NeutronFirewallPolicyRequest {
+    /**
+     * See OpenStack Network API v2.0 Reference for description of
+     * http://docs.openstack.org/api/openstack-network/2.0/content/
+     */
+
+    @XmlElement(name="firewall_policy")
+    NeutronFirewallPolicy singletonFirewallPolicy;
+
+    @XmlElement(name="firewall_policies")
+    List<NeutronFirewallPolicy> bulkRequest;
+
+    NeutronFirewallPolicyRequest() {
+    }
+
+    NeutronFirewallPolicyRequest(List<NeutronFirewallPolicy> bulk) {
+        bulkRequest = bulk;
+        singletonFirewallPolicy = null;
+    }
+
+    NeutronFirewallPolicyRequest(NeutronFirewallPolicy group) {
+        singletonFirewallPolicy = group;
+    }
+
+    public List<NeutronFirewallPolicy> getBulk() {
+        return bulkRequest;
+    }
+
+    public NeutronFirewallPolicy getSingleton() {
+        return singletonFirewallPolicy;
+    }
+
+    public boolean isSingleton() {
+        return (singletonFirewallPolicy != null);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRequest.java
new file mode 100644 (file)
index 0000000..11a7836
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewall;
+
+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 NeutronFirewallRequest {
+    /**
+     * See OpenStack Network API v2.0 Reference for description of
+     * http://docs.openstack.org/api/openstack-network/2.0/content/
+     */
+
+    @XmlElement(name="firewall")
+    NeutronFirewall singletonFirewall;
+
+    @XmlElement(name="firewalls")
+    List<NeutronFirewall> bulkRequest;
+
+    NeutronFirewallRequest() {
+    }
+
+    NeutronFirewallRequest(List<NeutronFirewall> bulk) {
+        bulkRequest = bulk;
+        singletonFirewall = null;
+    }
+
+    NeutronFirewallRequest(NeutronFirewall group) {
+        singletonFirewall = group;
+    }
+
+    public List<NeutronFirewall> getBulk() {
+        return bulkRequest;
+    }
+
+    public NeutronFirewall getSingleton() {
+        return singletonFirewall;
+    }
+
+    public boolean isSingleton() {
+        return (singletonFirewall != null);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRuleRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRuleRequest.java
new file mode 100644 (file)
index 0000000..19e67dd
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewallRule;
+
+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 NeutronFirewallRuleRequest {
+    /**
+     * See OpenStack Network API v2.0 Reference for description of
+     * http://docs.openstack.org/api/openstack-network/2.0/content/
+     */
+
+    @XmlElement(name="firewall_rule")
+    NeutronFirewallRule singletonFirewallRule;
+
+    @XmlElement(name="firewall_rules")
+    List<NeutronFirewallRule> bulkRequest;
+
+    NeutronFirewallRuleRequest() {
+    }
+
+    NeutronFirewallRuleRequest(List<NeutronFirewallRule> bulk) {
+        bulkRequest = bulk;
+        singletonFirewallRule = null;
+    }
+
+    NeutronFirewallRuleRequest(NeutronFirewallRule group) {
+        singletonFirewallRule = group;
+    }
+
+    public List<NeutronFirewallRule> getBulk() {
+        return bulkRequest;
+    }
+
+    public NeutronFirewallRule getSingleton() {
+        return singletonFirewallRule;
+    }
+
+    public boolean isSingleton() {
+        return (singletonFirewallRule != null);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRulesNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRulesNorthbound.java
new file mode 100644 (file)
index 0000000..9911b4d
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallPolicyCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallRuleAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFirewallRule;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Neutron Northbound REST APIs for Firewall Rule.<br>
+ * This class provides REST APIs for managing neutron Firewall Rule
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ */
+
+@Path("fw/firewalls_rules")
+public class NeutronFirewallRulesNorthbound {
+
+    private NeutronFirewallRule extractFields(NeutronFirewallRule o, List<String> fields) {
+        return o.extractFields(fields);
+    }
+
+    /**
+     * Returns a list of all Firewall Rules
+     */
+    @GET
+    @Produces({MediaType.APPLICATION_JSON})
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 501, condition = "Not Implemented")})
+    public Response listRules(
+            // return fields
+            @QueryParam("fields") List<String> fields,
+            // OpenStack firewall rule attributes
+            @QueryParam("id") String queryFirewallRuleUUID,
+            @QueryParam("tenant_id") String queryFirewallRuleTenantID,
+            @QueryParam("name") String queryFirewallRuleName,
+            @QueryParam("description") String queryFirewallRuleDescription,
+            @QueryParam("admin_state_up") Boolean queryFirewallRuleAdminStateIsUp,
+            @QueryParam("status") String queryFirewallRuleStatus,
+            @QueryParam("shared") Boolean queryFirewallRuleIsShared,
+            @QueryParam("firewall_policy_id") String queryFirewallRulePolicyID,
+            @QueryParam("protocol") String queryFirewallRuleProtocol,
+            @QueryParam("ip_version") Integer queryFirewallRuleIpVer,
+            @QueryParam("source_ip_address") String queryFirewallRuleSrcIpAddr,
+            @QueryParam("destination_ip_address") String queryFirewallRuleDstIpAddr,
+            @QueryParam("source_port") Integer queryFirewallRuleSrcPort,
+            @QueryParam("destination_port") Integer queryFirewallRuleDstPort,
+            @QueryParam("position") Integer queryFirewallRulePosition,
+            @QueryParam("action") String queryFirewallRuleAction,
+            @QueryParam("enabled") Boolean queryFirewallRuleIsEnabled,
+            // pagination
+            @QueryParam("limit") String limit,
+            @QueryParam("marker") String marker,
+            @QueryParam("page_reverse") String pageReverse
+            // sorting not supported
+    ) {
+        INeutronFirewallRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronFirewallRuleCRUD(this);
+        if (firewallRuleInterface == null) {
+            throw new ServiceUnavailableException("Firewall Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        List<NeutronFirewallRule> allFirewallRules = firewallRuleInterface.getAllNeutronFirewallRules();
+        List<NeutronFirewallRule> ans = new ArrayList<NeutronFirewallRule>();
+        Iterator<NeutronFirewallRule> i = allFirewallRules.iterator();
+        while (i.hasNext()) {
+            NeutronFirewallRule nsr = i.next();
+            if ((queryFirewallRuleUUID == null ||
+                    queryFirewallRuleUUID.equals(nsr.getFirewallRuleUUID())) &&
+                    (queryFirewallRuleTenantID == null ||
+                            queryFirewallRuleTenantID.equals(nsr.getFirewallRuleTenantID())) &&
+                    (queryFirewallRuleName == null ||
+                            queryFirewallRuleName.equals(nsr.getFirewallRuleName())) &&
+                    (queryFirewallRuleDescription == null ||
+                            queryFirewallRuleDescription.equals(nsr.getFirewallRuleDescription())) &&
+                    (queryFirewallRuleAdminStateIsUp == null ||
+                            queryFirewallRuleAdminStateIsUp.equals(nsr.getFirewallRuleAdminStateIsUp())) &&
+                    (queryFirewallRuleStatus == null ||
+                            queryFirewallRuleStatus.equals(nsr.getFirewallRuleStatus())) &&
+                    (queryFirewallRuleIsShared == null ||
+                            queryFirewallRuleIsShared.equals(nsr.getFirewallRuleIsShared())) &&
+                    (queryFirewallRulePolicyID == null ||
+                            queryFirewallRulePolicyID.equals(nsr.getFirewallRulePolicyID())) &&
+                    (queryFirewallRuleProtocol == null ||
+                            queryFirewallRuleProtocol.equals(nsr.getFirewallRuleProtocol())) &&
+                    (queryFirewallRuleIpVer == null ||
+                            queryFirewallRuleIpVer.equals(nsr.getFirewallRuleIpVer())) &&
+                    (queryFirewallRuleSrcIpAddr == null ||
+                            queryFirewallRuleSrcIpAddr.equals(nsr.getFirewallRuleSrcIpAddr())) &&
+                    (queryFirewallRuleDstIpAddr == null ||
+                            queryFirewallRuleDstIpAddr.equals(nsr.getFirewallRuleDstIpAddr())) &&
+                    (queryFirewallRuleSrcPort == null ||
+                            queryFirewallRuleSrcPort.equals(nsr.getFirewallRuleSrcPort())) &&
+                    (queryFirewallRuleDstPort == null ||
+                            queryFirewallRuleDstPort.equals(nsr.getFirewallRuleDstPort())) &&
+                    (queryFirewallRulePosition == null ||
+                            queryFirewallRulePosition.equals(nsr.getFirewallRulePosition())) &&
+                    (queryFirewallRuleAction == null ||
+                            queryFirewallRuleAction.equals(nsr.getFirewallRuleAction())) &&
+                    (queryFirewallRuleIsEnabled == null ||
+                            queryFirewallRuleIsEnabled.equals(nsr.getFirewallRuleIsEnabled()))) {
+                if (fields.size() > 0) {
+                    ans.add(extractFields(nsr, fields));
+                } else {
+                    ans.add(nsr);
+                }
+            }
+        }
+        //TODO: apply pagination to results
+        return Response.status(200).entity(
+                new NeutronFirewallRuleRequest(ans)).build();
+    }
+
+    /**
+     * Returns a specific Firewall Rule
+     */
+
+    @Path("{firewallRuleUUID}")
+    @GET
+    @Produces({MediaType.APPLICATION_JSON})
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented")})
+    public Response showFirewallRule(@PathParam("firewallRuleUUID") String firewallRuleUUID,
+            // return fields
+            @QueryParam("fields") List<String> fields) {
+        INeutronFirewallRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronFirewallRuleCRUD(this);
+        if (firewallRuleInterface == null) {
+            throw new ServiceUnavailableException("Firewall Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        if (!firewallRuleInterface.neutronFirewallRuleExists(firewallRuleUUID)) {
+            throw new ResourceNotFoundException("Firewall Rule UUID does not exist.");
+        }
+        if (fields.size() > 0) {
+            NeutronFirewallRule ans = firewallRuleInterface.getNeutronFirewallRule(firewallRuleUUID);
+            return Response.status(200).entity(
+                    new NeutronFirewallRuleRequest(extractFields(ans, fields))).build();
+        } else {
+            return Response.status(200)
+                    .entity(new NeutronFirewallRuleRequest(
+                            firewallRuleInterface.getNeutronFirewallRule(firewallRuleUUID)))
+                    .build();
+        }
+    }
+
+    /**
+     * Creates new Firewall Rule
+     */
+
+    @POST
+    @Produces({MediaType.APPLICATION_JSON})
+    @Consumes({MediaType.APPLICATION_JSON})
+    @StatusCodes({
+            @ResponseCode(code = 201, condition = "Created"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented")})
+    public Response createFirewallRules(final NeutronFirewallRuleRequest input) {
+        INeutronFirewallRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronFirewallRuleCRUD(this);
+        if (firewallRuleInterface == null) {
+            throw new ServiceUnavailableException("Firewall Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        INeutronFirewallPolicyCRUD firewallPolicyInterface = NeutronCRUDInterfaces.getINeutronFirewallPolicyCRUD(this);
+        if (firewallPolicyInterface == null) {
+            throw new ServiceUnavailableException("Firewall Policy CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        if (input.isSingleton()) {
+            NeutronFirewallRule singleton = input.getSingleton();
+            if (firewallRuleInterface.neutronFirewallRuleExists(singleton.getFirewallRuleUUID())) {
+                throw new BadRequestException("Firewall Rule UUID already exists");
+            }
+            firewallRuleInterface.addNeutronFirewallRule(singleton);
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallRuleAware.class, this, null);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                    int status = service.canCreateNeutronFirewallRule(singleton);
+                    if (status < 200 || status > 299) {
+                        return Response.status(status).build();
+                    }
+                }
+            }
+            // add rule to cache
+            singleton.initDefaults();
+            firewallRuleInterface.addNeutronFirewallRule(singleton);
+            if (instances != null) {
+                for (Object instance : instances) {
+                    INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                    service.neutronFirewallRuleCreated(singleton);
+                }
+            }
+        } else {
+            List<NeutronFirewallRule> bulk = input.getBulk();
+            Iterator<NeutronFirewallRule> i = bulk.iterator();
+            HashMap<String, NeutronFirewallRule> testMap = new HashMap<String, NeutronFirewallRule>();
+            Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallRuleAware.class, this, null);
+            while (i.hasNext()) {
+                NeutronFirewallRule test = i.next();
+
+                /*
+                 *  Verify that the Firewall rule doesn't already exist
+                 */
+
+                if (firewallRuleInterface.neutronFirewallRuleExists(test.getFirewallRuleUUID())) {
+                    throw new BadRequestException("Firewall Rule UUID already exists");
+                }
+                if (testMap.containsKey(test.getFirewallRuleUUID())) {
+                    throw new BadRequestException("Firewall Rule UUID already exists");
+                }
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                        int status = service.canCreateNeutronFirewallRule(test);
+                        if (status < 200 || status > 299) {
+                            return Response.status(status).build();
+                        }
+                    }
+                }
+            }
+            /*
+             * now, each element of the bulk request can be added to the cache
+             */
+            i = bulk.iterator();
+            while (i.hasNext()) {
+                NeutronFirewallRule test = i.next();
+                firewallRuleInterface.addNeutronFirewallRule(test);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                        service.neutronFirewallRuleCreated(test);
+                    }
+                }
+            }
+        }
+        return Response.status(201).entity(input).build();
+    }
+
+    /**
+     * Updates a Firewall Rule
+     */
+    @Path("{firewallRuleUUID}")
+    @PUT
+    @Produces({MediaType.APPLICATION_JSON})
+    @Consumes({MediaType.APPLICATION_JSON})
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "Bad Request"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 403, condition = "Forbidden"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 501, condition = "Not Implemented")})
+    public Response updateFirewallRule(
+            @PathParam("firewallRuleUUID") String firewallRuleUUID, final NeutronFirewallRuleRequest input) {
+        INeutronFirewallRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronFirewallRuleCRUD(this);
+        if (firewallRuleInterface == null) {
+            throw new ServiceUnavailableException("Firewall Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        /*
+         * verify the Firewall Rule exists
+         */
+        if (!firewallRuleInterface.neutronFirewallRuleExists(firewallRuleUUID)) {
+            throw new ResourceNotFoundException("Firewall Rule UUID does not exist.");
+        }
+        if (!input.isSingleton()) {
+            throw new BadRequestException("Only singleton edit supported");
+        }
+        NeutronFirewallRule delta = input.getSingleton();
+        NeutronFirewallRule original = firewallRuleInterface.getNeutronFirewallRule(firewallRuleUUID);
+
+        /*
+         * updates restricted by Neutron
+         *
+         */
+        if (delta.getFirewallRuleUUID() != null ||
+                delta.getFirewallRuleTenantID() != null ||
+                delta.getFirewallRuleName() != null ||
+                delta.getFirewallRuleDescription() != null ||
+                delta.getFirewallRuleAdminStateIsUp() != null ||
+                delta.getFirewallRuleStatus() != null ||
+                delta.getFirewallRuleIsShared() != null ||
+                delta.getFirewallRulePolicyID() != null ||
+                delta.getFirewallRuleProtocol() != null ||
+                delta.getFirewallRuleIpVer() != null ||
+                delta.getFirewallRuleSrcIpAddr() != null ||
+                delta.getFirewallRuleDstIpAddr() != null ||
+                delta.getFirewallRuleSrcPort() != null ||
+                delta.getFirewallRuleDstPort() != null ||
+                delta.getFirewallRulePosition() != null ||
+                delta.getFirewallRuleAction() != null ||
+                delta.getFirewallRuleIsEnabled() != null) {
+            throw new BadRequestException("Attribute edit blocked by Neutron");
+        }
+
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallRuleAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                int status = service.canUpdateNeutronFirewallRule(delta, original);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * update the object and return it
+         */
+        firewallRuleInterface.updateNeutronFirewallRule(firewallRuleUUID, delta);
+        NeutronFirewallRule updatedFirewallRule = firewallRuleInterface.getNeutronFirewallRule(firewallRuleUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                service.neutronFirewallRuleUpdated(updatedFirewallRule);
+            }
+        }
+        return Response.status(200)
+                .entity(new NeutronFirewallRuleRequest(firewallRuleInterface.getNeutronFirewallRule(firewallRuleUUID)))
+                .build();
+    }
+
+    /**
+     * Deletes a Firewall Rule
+     */
+
+    @Path("{firewallRuleUUID}")
+    @DELETE
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "Unauthorized"),
+            @ResponseCode(code = 404, condition = "Not Found"),
+            @ResponseCode(code = 409, condition = "Conflict"),
+            @ResponseCode(code = 501, condition = "Not Implemented")})
+    public Response deleteFirewallRule(
+            @PathParam("firewallRuleUUID") String firewallRuleUUID) {
+        INeutronFirewallRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronFirewallRuleCRUD(this);
+        if (firewallRuleInterface == null) {
+            throw new ServiceUnavailableException("Firewall Rule CRUD Interface "
+                    + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        /*
+         * verify the Firewall Rule exists and it isn't currently in use
+         */
+        if (!firewallRuleInterface.neutronFirewallRuleExists(firewallRuleUUID)) {
+            throw new ResourceNotFoundException("Firewall Rule UUID does not exist.");
+        }
+        if (firewallRuleInterface.neutronFirewallRuleInUse(firewallRuleUUID)) {
+            return Response.status(409).build();
+        }
+        NeutronFirewallRule singleton = firewallRuleInterface.getNeutronFirewallRule(firewallRuleUUID);
+        Object[] instances = ServiceHelper.getGlobalInstances(INeutronFirewallRuleAware.class, this, null);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                int status = service.canDeleteNeutronFirewallRule(singleton);
+                if (status < 200 || status > 299) {
+                    return Response.status(status).build();
+                }
+            }
+        }
+
+        /*
+         * remove it and return 204 status
+         */
+        firewallRuleInterface.removeNeutronFirewallRule(firewallRuleUUID);
+        if (instances != null) {
+            for (Object instance : instances) {
+                INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance;
+                service.neutronFirewallRuleDeleted(singleton);
+            }
+        }
+        return Response.status(204).build();
+    }
+}
index 3fe03a2dac8de2f64d9ee2b9796befe72ab0e8b1..9abcca7c53466880de769f93324ad09577142bf8 100644 (file)
@@ -8,12 +8,13 @@
 
 package org.opendaylight.controller.networkconfig.neutron.northbound;
 
+import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
+
+import javax.ws.rs.core.Application;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import javax.ws.rs.core.Application;
-import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
 
 
 /**
@@ -34,6 +35,9 @@ public class NeutronNorthboundRSApplication extends Application {
         classes.add(NeutronFloatingIPsNorthbound.class);
         classes.add(NeutronSecurityGroupsNorthbound.class);
         classes.add(NeutronSecurityRulesNorthbound.class);
+        classes.add(NeutronFirewallNorthbound.class);
+        classes.add(NeutronFirewallPolicyNorthbound.class);
+        classes.add(NeutronFirewallRulesNorthbound.class);
         return classes;
     }
 
index 196982b3610ee6f33f2afc8a4685a905780cdb26..746135891ea5acf3b976ae64421dda9a393c4f07 100644 (file)
@@ -44,6 +44,7 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
         <extensions>true</extensions>
         <configuration>
           <instructions>
diff --git a/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerShell.java b/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerShell.java
new file mode 100644 (file)
index 0000000..22bd9c0
--- /dev/null
@@ -0,0 +1,17 @@
+/**
+* Copyright (c) 2014 Inocybe Technologies, and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.topologymanager;
+
+import java.util.List;
+
+public interface ITopologyManagerShell {
+    public List<String> printUserLink();
+    public List<String> addUserLink(String name, String ncStr1, String ncStr2);
+    public List<String> deleteUserLinkShell(String name);
+    public List<String> printNodeEdges();
+}
index 4ccbb0197d4bf1cdc1e6d2e87ed6e1a547ea0425..80d7083ec0dee0059a8b7c0c33720522b65fb4bc 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
 import org.opendaylight.controller.topologymanager.ITopologyManagerClusterWideAware;
+import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -73,6 +74,7 @@ public class Activator extends ComponentActivatorAbstractBase {
 
             c.setInterface(new String[] { IListenTopoUpdates.class.getName(),
                     ITopologyManager.class.getName(),
+                    ITopologyManagerShell.class.getName(),
                     IConfigurationContainerAware.class.getName(),
                     ICacheUpdateAware.class.getName() }, props);
 
index ff1c026a344d74efa5aa1f1b57e05e60775cd1a4..b0e87c48f3e0812fd2e33c7789e5e916479f6465 100644 (file)
@@ -57,6 +57,7 @@ import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
 import org.opendaylight.controller.topologymanager.ITopologyManagerClusterWideAware;
+import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
 import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -71,6 +72,7 @@ import org.slf4j.LoggerFactory;
 public class TopologyManagerImpl implements
         ICacheUpdateAware<Object, Object>,
         ITopologyManager,
+        ITopologyManagerShell,
         IConfigurationContainerAware,
         IListenTopoUpdates,
         IObjectReader,
@@ -1010,4 +1012,82 @@ public class TopologyManagerImpl implements
             }
         }
     }
+
+    public List<String> printUserLink() {
+        List<String> result = new ArrayList<String>();
+        for (String name : this.userLinksDB.keySet()) {
+            TopologyUserLinkConfig linkConfig = userLinksDB.get(name);
+            result.add("Name : " + name);
+            result.add(linkConfig.toString());
+            result.add("Edge " + getLinkTuple(linkConfig));
+            result.add("Reverse Edge " + getReverseLinkTuple(linkConfig));
+        }
+        return result;
+    }
+
+    public List<String> addUserLink(String name, String ncStr1, String ncStr2) {
+        List<String> result = new ArrayList<String>();
+        if ((name == null)) {
+            result.add("Please enter a valid Name");
+            return result;
+        }
+
+        if (ncStr1 == null) {
+            result.add("Please enter two node connector strings");
+            return result;
+        }
+        if (ncStr2 == null) {
+            result.add("Please enter second node connector string");
+            return result;
+        }
+
+        NodeConnector nc1 = NodeConnector.fromString(ncStr1);
+        if (nc1 == null) {
+            result.add("Invalid input node connector 1 string: " + ncStr1);
+            return result;
+        }
+        NodeConnector nc2 = NodeConnector.fromString(ncStr2);
+        if (nc2 == null) {
+            result.add("Invalid input node connector 2 string: " + ncStr2);
+            return result;
+        }
+
+        TopologyUserLinkConfig config = new TopologyUserLinkConfig(name, ncStr1, ncStr2);
+        result.add(this.addUserLink(config).toString());
+        return result;
+    }
+
+    public List<String> deleteUserLinkShell(String name) {
+        List<String> result = new ArrayList<String>();
+        if ((name == null)) {
+            result.add("Please enter a valid Name");
+            return result;
+        }
+        this.deleteUserLink(name);
+        return result;
+    }
+
+    public List<String> printNodeEdges() {
+        List<String> result = new ArrayList<String>();
+        Map<Node, Set<Edge>> nodeEdges = getNodeEdges();
+        if (nodeEdges == null) {
+            return result;
+        }
+        Set<Node> nodeSet = nodeEdges.keySet();
+        if (nodeSet == null) {
+            return result;
+        }
+        result.add("        Node                                         Edge");
+        for (Node node : nodeSet) {
+            Set<Edge> edgeSet = nodeEdges.get(node);
+            if (edgeSet == null) {
+                continue;
+            }
+            for (Edge edge : edgeSet) {
+                result.add(node + "             " + edge);
+            }
+        }
+        return result;
+    }
+
 }
diff --git a/opendaylight/topologymanager/shell/pom.xml b/opendaylight/topologymanager/shell/pom.xml
new file mode 100644 (file)
index 0000000..078b55c
--- /dev/null
@@ -0,0 +1,52 @@
+<?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>topologymanager.shell</artifactId>
+  <version>${topologymanager.shell.version}</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.shell</groupId>
+      <artifactId>org.apache.karaf.shell.console</artifactId>
+      <version>${karaf.shell.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topologymanager</artifactId>
+      <version>${topologymanager.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
+        <configuration>
+          <instructions>
+            <Import-Package>org.apache.felix.service.command,
+              org.apache.karaf.shell.commands,
+              org.apache.karaf.shell.console,
+              *</Import-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/AddUserLink.java b/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/AddUserLink.java
new file mode 100644 (file)
index 0000000..1565a87
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+* Copyright (c) 2014 Inocybe Technologies, and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.topologymanager.shell;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
+
+@Command(scope = "topologymanager", name = "addUserLink", description="Adds user link")
+public class AddUserLink extends OsgiCommandSupport{
+    private ITopologyManagerShell topologyManager;
+
+    @Argument(index=0, name="name", description="name", required=true, multiValued=false)
+    String name = null;
+
+    @Argument(index=1, name="ncStr1", description="ncStr1", required=true, multiValued=false)
+    String ncStr1 = null;
+
+    @Argument(index=2, name="ncStr2", description="ncStr2", required=true, multiValued=false)
+    String ncStr2 = null;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        for(String p : topologyManager.addUserLink(name, ncStr1, ncStr2)) {
+            System.out.println(p);
+        }
+        return null;
+    }
+
+    public void setTopologyManager(ITopologyManagerShell topologyManager){
+        this.topologyManager = topologyManager;
+    }
+}
diff --git a/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/DeleteUserLink.java b/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/DeleteUserLink.java
new file mode 100644 (file)
index 0000000..b226c3c
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+* Copyright (c) 2014 Inocybe Technologies, and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.topologymanager.shell;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
+
+@Command(scope = "topologymanager", name = "deleteUserLink", description="deletes user link")
+public class DeleteUserLink extends OsgiCommandSupport{
+    private ITopologyManagerShell topologyManager;
+
+    @Argument(index=0, name="name", description="name", required=true, multiValued=false)
+    String name = null;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        for(String p : topologyManager.deleteUserLinkShell(name)) {
+            System.out.println(p);
+        }
+        return null;
+    }
+
+    public void setTopologyManager(ITopologyManagerShell topologyManager){
+        this.topologyManager = topologyManager;
+    }
+}
diff --git a/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/PrintNodeEdges.java b/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/PrintNodeEdges.java
new file mode 100644 (file)
index 0000000..9c5e806
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+* Copyright (c) 2014 Inocybe Technologies, and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.topologymanager.shell;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
+
+@Command(scope = "topologymanager", name = "printNodeEdges", description="Prints node edges")
+public class PrintNodeEdges extends OsgiCommandSupport{
+    private ITopologyManagerShell topologyManager;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        for(String p : topologyManager.printNodeEdges()) {
+            System.out.println(p);
+        }
+        return null;
+    }
+
+    public void setTopologyManager(ITopologyManagerShell topologyManager){
+        this.topologyManager = topologyManager;
+    }
+}
diff --git a/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/PrintUserLink.java b/opendaylight/topologymanager/shell/src/main/java/org/opendaylight/controller/topologymanager/shell/PrintUserLink.java
new file mode 100644 (file)
index 0000000..df7ab35
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+* Copyright (c) 2014 Inocybe Technologies, and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.topologymanager.shell;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.topologymanager.ITopologyManagerShell;
+
+@Command(scope = "topologymanager", name = "printUserLink", description="Prints user link")
+public class PrintUserLink extends OsgiCommandSupport{
+    private ITopologyManagerShell topologyManager;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        for(String p : topologyManager.printUserLink()) {
+            System.out.println(p);
+        }
+        return null;
+    }
+
+    public void setTopologyManager(ITopologyManagerShell topologyManager){
+        this.topologyManager = topologyManager;
+    }
+}
diff --git a/opendaylight/topologymanager/shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/opendaylight/topologymanager/shell/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644 (file)
index 0000000..96b0b10
--- /dev/null
@@ -0,0 +1,33 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+    <reference id="topologyManagerRef" interface="org.opendaylight.controller.topologymanager.ITopologyManagerShell"/>
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+
+        <command>
+        <action class="org.opendaylight.controller.topologymanager.shell.AddUserLink">
+            <property name="topologyManager" ref="topologyManagerRef"/>
+            </action>
+        </command>
+
+        <command>
+        <action class="org.opendaylight.controller.topologymanager.shell.DeleteUserLink">
+            <property name="topologyManager" ref="topologyManagerRef"/>
+            </action>
+        </command>
+
+        <command>
+        <action class="org.opendaylight.controller.topologymanager.shell.PrintNodeEdges">
+            <property name="topologyManager" ref="topologyManagerRef"/>
+            </action>
+        </command>
+
+        <command>
+        <action class="org.opendaylight.controller.topologymanager.shell.PrintUserLink">
+            <property name="topologyManager" ref="topologyManagerRef"/>
+            </action>
+        </command>
+
+    </command-bundle>
+
+
+</blueprint>