Merge "Simplify method isMutualExclusive in Subnet. Remove redundant 'if' statements."
authorMadhu Venugopal <mavenugo@gmail.com>
Mon, 23 Dec 2013 19:24:23 +0000 (19:24 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 23 Dec 2013 19:24:23 +0000 (19:24 +0000)
289 files changed:
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/AbstractDynamicWrapper.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/AttributeHolder.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/BaseJMXRegistrator.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/NestableJMXRegistrator.java [moved from opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/KeyStoreHandler.java with 62% similarity]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionModuleJMXRegistrator.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModule.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/AbstractParallelAPSPTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolConfigBeanMXBean.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModule.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleField.java
opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorFileNamesValidationTest.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/MbeParser.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangParserWrapper.java [new file with mode: 0644]
opendaylight/config/yang-test/pom.xml
opendaylight/config/yang-test/src/test/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java [new file with mode: 0644]
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDSalNodeConnectorFactory.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDSalNodeFactory.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend
opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-flow-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/queue-types.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/meter-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/meter-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/port-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/queue-statistics.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/statistics-types.yang
opendaylight/md-sal/pom.xml
opendaylight/md-sal/remoterpc-routingtable/implementation/pom.xml [moved from opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml with 98% similarity]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java [moved from opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java with 100% similarity]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java [moved from opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java with 100% similarity]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java [moved from opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java with 100% similarity]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java [moved from opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java with 100% similarity]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java [moved from opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java with 100% similarity]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java [moved from opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java with 95% similarity]
opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java [moved from opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java with 100% similarity]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/pom.xml [moved from opendaylight/md-sal/zeromq-routingtable/integrationtest/pom.xml with 98% similarity]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java [moved from opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java with 99% similarity]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/src/test/resources/logback.xml [moved from opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/resources/logback.xml with 100% similarity]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/pom.xml [new file with mode: 0644]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/RouteIdentifierImpl.java [new file with mode: 0644]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/Router.java [new file with mode: 0644]
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcAvailabilityListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingBrokerImplModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/DataBrokerImplModule.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/sal/binding/codegen/RuntimeCodeGenerator.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRoutingTableImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRoutingTableImpl.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/XtendHelper.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java [moved from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java with 58% similarity]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RoutingContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcContextIdentifier.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcRouter.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-util/pom.xml
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonBasicDataTypesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonBasicYangTypesTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonBasicYangTypesTest.java with 87% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonChoiceCaseTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonIdentityrefTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonIdentityrefTest.java with 61% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonLeafrefType.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonLeafrefType.java with 75% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonWithAugmentTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonWithAugmentTest.java with 66% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromJsonToCompositeNodeTest.java with 73% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ReadConfAndOperDataTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfImplTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonBasicDataTypesTest.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonChoiceCaseTest.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/structures/Lf.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/structures/LfLst.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/structures/LstItem.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNodeTest.java with 65% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/augmentation/augment-container.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-container.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/augmentation/augment-leaf.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaf.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/augmentation/augment-leaflist.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaflist.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/augmentation/augment-list.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-list.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/augmentation/xml/data.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/xml/data.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/augmentation/yang.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/yang.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/choice.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/choice.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_case_defined_without_case.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_case_defined_without_case.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_container.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_container.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_leaflist.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_leaflist.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_list.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_list.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_more_choices_same_level.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_more_choices_same_level.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_more_choices_same_level_various_paths_err.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_more_choices_same_level_various_paths_err.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_no_first_case.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_no_first_case.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_random_level.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_random_level.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_three_choices_same_level.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_three_choices_same_level.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/choice/xml/data_various_path_err.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/choice/xml/data_various_path_err.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/identityref/identity-module.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/identityref/identity-module.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/identityref/identityref-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/cont-augment-module.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/cont-augment-module.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/main-module.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/main-module.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/xml/data_absolut_ref_to_existing_leaf.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/xml/data_absolut_ref_to_existing_leaf.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/xml/data_from_leafref_to_leafref.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/xml/data_from_leafref_to_leafref.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/xml/data_ref_to_non_existing_leaf.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/xml/data_ref_to_non_existing_leaf.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/xml/data_ref_to_not_leaf.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/xml/data_ref_to_not_leaf.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/xml/data_relativ_ref_from_leaflist_to_existing_leaf.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/xml/data_relativ_ref_from_leaflist_to_existing_leaf.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/leafref/xml/data_relativ_ref_to_existing_leaf.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/leafref/xml/data_relativ_ref_to_existing_leaf.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/simple-data-types.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-data-types/simple-data-types.yang with 90% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/xml/data.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-data-types/xml/data.xml with 80% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-yang-types/simple-yang-types.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/simple-yang-types.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-yang-types/xml/awaited_output_data.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output_data.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-yang-types/xml/awaited_output_empty_data.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output_empty_data.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-yang-types/xml/data.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/data.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-yang-types/xml/empty_data.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/empty_data.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/aug-referenced-elements-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/eferenced-elements-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/rinstance-identifier-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/yang/basic-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/yang/referenced-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/array-with-null.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/array-with-null.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/empty-data.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/empty-data1.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/empty-data1.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/identity-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/identityref-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/json/data.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/multiple-items-in-list.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/multiple-items-in-list.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/multiple-leaflist-items.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/multiple-leaflist-items.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/simple-container-yang/simple-container.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container-yang/simple-container.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/simple-container.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-container.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/simple-list-yang/simple-list1.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list-yang/simple-list1.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/simple-list-yang/simple-list2.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list-yang/simple-list2.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/simple-list.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/simple-list.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/wrong-top-level1.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level1.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/wrong-top-level2.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level2.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/wrong-top-level3.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-composite-node/wrong-top-level3.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-container-yang/data-container.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container-yang/data-container.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-container.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-list-yang/data-container.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-container.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-list-yang/data-list.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list-yang/data-list.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-list.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-list.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-nmspc-in-attributes.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/empty-data.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/empty-data.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/identity-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/identityref-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-default-nmspc-in-element.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-default-nmspc-in-parrent-element.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-nmspc-in-element.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-nmspc-in-parrent-element.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-no-nmspc-value-with-prefix.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-no-nmspc-value-without-prefix.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/yang-augments/general-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/yang-augments/identity-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/yang-augments/identityref-module.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/identityref/identityref-module.yang with 69% similarity]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatistics.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/pom.xml
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
opendaylight/netconf/ietf-netconf-monitoring-extension/pom.xml [new file with mode: 0644]
opendaylight/netconf/ietf-netconf-monitoring-extension/src/main/yang/ietf-netconf-monitoring-extension.yang [new file with mode: 0644]
opendaylight/netconf/netconf-api/pom.xml
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfMessage.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/AdditionalHeaderUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/AdditionalHeaderParserTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java
opendaylight/netconf/netconf-monitoring/pom.xml
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/MonitoringSession.java
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java
opendaylight/netconf/netconf-ssh/pom.xml
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java [new file with mode: 0644]
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderInterface.java [new file with mode: 0644]
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/RSAKey.java [deleted file]
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java
opendaylight/netconf/netconf-ssh/src/main/resources/RSA.pk [new file with mode: 0644]
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/SSHServerTest.java [moved from opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/ssh/SSHServerTest.java with 53% similarity]
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageAdditionalHeader.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactory.java
opendaylight/netconf/pom.xml
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/NorthboundApplication.java
opendaylight/northbound/subnets/src/main/resources/WEB-INF/web.xml
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServiceShim.java
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/Subnet.java
opendaylight/switchmanager/api/src/test/java/org/opendaylight/controller/switchmanager/SubnetTest.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java
opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java
opendaylight/usermanager/implementation/pom.xml
opendaylight/web/flows/src/main/resources/js/page.js

index c257e55dc088b7b7d80bb99fea333e5aacc33c6e..264751318c3570415f412a82b4df7d992853c451 100644 (file)
@@ -16,7 +16,7 @@ import javax.management.ObjectName;
 /**
  * Represents functionality provided by configuration transaction.
  */
-public interface ConfigTransactionController extends LookupRegistry, ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+public interface ConfigTransactionController extends LookupRegistry, ServiceReferenceWritableRegistry {
 
     /**
      * Create new configuration bean.
index 772617e97d8492898d2e587ba804798cfbd9d643..376ecdb52a2f7324a1c5a9d02e2c9dea3f871a80 100644 (file)
@@ -65,8 +65,9 @@ public interface LookupRegistry {
      */
     void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException;
 
+
     /**
-     * @return qnames of all ModuleFactory instances in the system
+     * @return qNames of all ModuleFactory instances in the system
      */
     Set<String> getAvailableModuleFactoryQNames();
 
index f84fcd48c9b871913554b26d18b2ef8b945f48f5..d7e94e8a7631d64a55eb43729cfc83d6bd823e6a 100644 (file)
@@ -16,24 +16,24 @@ public interface ServiceReferenceReadableRegistry {
 
     /**
      * Lookup object name by fully qualified service interface name and service reference name.
-     * @param serviceInterfaceName service interface name
+     * @param serviceInterfaceQName service interface name
      * @param refName service reference name supplied in
      * {@link org.opendaylight.controller.config.api.ConfigTransactionController#saveServiceReference(String, String, javax.management.ObjectName)}
      * @throws java.lang.IllegalArgumentException if module not found
      */
-    ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName);
+    ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName);
 
     /**
      * Get mapping of services to reference names and module object names.
      */
-    Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping();
+    Map<String /* serviceInterfaceQName */, Map<String/* refName */, ObjectName>> getServiceMapping();
 
     /**
      * Get current mapping between reference names and module object names for given service interface name.
-     * @param serviceInterfaceName service interface name
+     * @param serviceInterfaceQName service interface name
      * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName
      */
-    Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName);
+    Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName);
 
     /**
      * Find all available service interface names of a module.
@@ -50,4 +50,13 @@ public interface ServiceReferenceReadableRegistry {
      */
     String getServiceInterfaceName(String namespace, String localName);
 
+    /**
+     * @return ObjectName with type=Service that was created using
+     * {@link org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry#saveServiceReference(String, String,
+     * javax.management.ObjectName)}
+     */
+    ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException;
+
+    void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException;
+
 }
index f3d6d16d6c1e0660874551785f443fe18976089c..fa2aa1f56e0d1fe5eef418038ccd3c39a80260a7 100644 (file)
@@ -13,17 +13,18 @@ import javax.management.ObjectName;
 public interface ServiceReferenceWritableRegistry extends ServiceReferenceReadableRegistry {
     /**
      * Create or update reference name to objectName. Reference name is unique per service interface name.
+     * @return created or updated object name containing service name and reference name
      * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName
      * @throws InstanceNotFoundException if search did not find exactly one instance
      */
-    void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException;
+    ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException;
 
     /**
      * Remove service reference.
      * @return true iif removed
      * @throws IllegalArgumentException if service interface name is not advertised by any module
      */
-    boolean removeServiceReference(String serviceInterfaceName, String refName);
+    void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException;
 
     /**
      * Remove all service references.
index cc1d89761c2ef8784b6f79019101fa76a21361c1..3baa1039e0bd1c868c28b6d8d5f7ea35c8da3dc7 100644 (file)
@@ -25,21 +25,23 @@ import java.util.Set;
  * is defined as {@link #ON_DOMAIN} and at least one key-value pair. The only
  * mandatory property is {@link #TYPE_KEY}. All transaction related mbeans have
  * {@link #TRANSACTION_NAME_KEY} property set.
- *
  */
 @ThreadSafe
 public class ObjectNameUtil {
 
     public static final String ON_DOMAIN = ConfigRegistryConstants.ON_DOMAIN;
     public static final String MODULE_FACTORY_NAME_KEY = "moduleFactoryName";
+    public static final String SERVICE_QNAME_KEY = "serviceQName";
     public static final String INSTANCE_NAME_KEY = "instanceName";
     public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
     public static final String TYPE_CONFIG_REGISTRY = ConfigRegistryConstants.TYPE_CONFIG_REGISTRY;
     public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
     public static final String TYPE_MODULE = "Module";
+    public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
     public static final String TYPE_RUNTIME_BEAN = "RuntimeBean";
-
     public static final String TRANSACTION_NAME_KEY = "TransactionName";
+    public static final String REF_NAME_KEY = "RefName";
+    private static final String REPLACED_QUOTATION_MARK = "\\?";
 
     public static ObjectName createON(String on) {
         try {
@@ -57,10 +59,10 @@ public class ObjectNameUtil {
         return ConfigRegistryConstants.createON(name, key, value);
     }
 
-    public static ObjectName createON(String name, Map<String, String> attribs) {
+    public static ObjectName createON(String domain, Map<String, String> attribs) {
         Hashtable<String, String> table = new Hashtable<>(attribs);
         try {
-            return new ObjectName(name, table);
+            return new ObjectName(domain, table);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
@@ -76,21 +78,21 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createTransactionModuleON(String transactionName,
-            ModuleIdentifier moduleIdentifier) {
+                                                       ModuleIdentifier moduleIdentifier) {
         return createTransactionModuleON(transactionName,
                 moduleIdentifier.getFactoryName(),
                 moduleIdentifier.getInstanceName());
     }
 
     public static ObjectName createTransactionModuleON(String transactionName,
-            String moduleName, String instanceName) {
-        Map<String, String> onParams = createModuleON(moduleName, instanceName);
+                                                       String moduleName, String instanceName) {
+        Map<String, String> onParams = createModuleMap(moduleName, instanceName);
         onParams.put(TRANSACTION_NAME_KEY, transactionName);
         return createON(ON_DOMAIN, onParams);
     }
 
     public static ObjectName createTransactionModuleON(String transactionName,
-            ObjectName on) {
+                                                       ObjectName on) {
         return createTransactionModuleON(transactionName, getFactoryName(on),
                 getInstanceName(on));
     }
@@ -101,14 +103,73 @@ public class ObjectNameUtil {
                 moduleIdentifier.getInstanceName());
     }
 
+    public static ObjectName createReadOnlyServiceON(String serviceQName, String refName) {
+        Map<String, String> onParams = createServiceMap(serviceQName, refName);
+        return createON(ON_DOMAIN, onParams);
+    }
+
+    public static ObjectName createTransactionServiceON(String transactionName, String serviceQName, String refName) {
+        Map<String, String> onParams = createServiceON(transactionName, serviceQName, refName);
+        return createON(ON_DOMAIN, onParams);
+    }
+
+    public static String getServiceQName(ObjectName objectName) {
+        checkType(objectName, TYPE_SERVICE_REFERENCE);
+        String quoted = objectName.getKeyProperty(SERVICE_QNAME_KEY);
+        String result = unquoteAndUnescape(objectName, quoted);
+        return result;
+    }
+
+    // ObjectName supports quotation and ignores tokens like =, but fails to ignore ? sign.
+    // It must be replaced with another character that hopefully does not collide
+    // with actual value.
+    private static String unquoteAndUnescape(ObjectName objectName, String quoted) {
+        if (quoted == null) {
+            throw new IllegalArgumentException("Cannot find " + SERVICE_QNAME_KEY + " in " + objectName);
+        }
+        if (quoted.startsWith("\"") == false || quoted.endsWith("\"") == false) {
+            throw new IllegalArgumentException("Quotes not found in " + objectName);
+        }
+        String substring = quoted.substring(1);
+        substring = substring.substring(0, substring.length() - 1);
+        substring = substring.replace(REPLACED_QUOTATION_MARK, "?");
+        return substring;
+    }
+
+    private static String quoteAndEscapeValue(String serviceQName) {
+        return "\"" + serviceQName.replace("?", REPLACED_QUOTATION_MARK) + "\"";
+    }
+
+    public static String getReferenceName(ObjectName objectName) {
+        checkType(objectName, TYPE_SERVICE_REFERENCE);
+        return objectName.getKeyProperty(REF_NAME_KEY);
+    }
+
+    private static Map<String, String> createServiceON(String transactionName, String serviceQName,
+                                                       String refName) {
+        Map<String, String> result = new HashMap<>(createServiceMap(serviceQName, refName));
+        result.put(TRANSACTION_NAME_KEY, transactionName);
+        return result;
+    }
+
+    private static Map<String, String> createServiceMap(String serviceQName,
+                                                        String refName) {
+        Map<String, String> onParams = new HashMap<>();
+        onParams.put(TYPE_KEY, TYPE_SERVICE_REFERENCE);
+        onParams.put(SERVICE_QNAME_KEY, quoteAndEscapeValue(serviceQName));
+        onParams.put(REF_NAME_KEY, refName);
+        return onParams;
+    }
+
+
     public static ObjectName createReadOnlyModuleON(String moduleName,
-            String instanceName) {
-        Map<String, String> onParams = createModuleON(moduleName, instanceName);
+                                                    String instanceName) {
+        Map<String, String> onParams = createModuleMap(moduleName, instanceName);
         return createON(ON_DOMAIN, onParams);
     }
 
-    private static Map<String, String> createModuleON(String moduleName,
-            String instanceName) {
+    private static Map<String, String> createModuleMap(String moduleName,
+                                                       String instanceName) {
         Map<String, String> onParams = new HashMap<>();
         onParams.put(TYPE_KEY, TYPE_MODULE);
         onParams.put(MODULE_FACTORY_NAME_KEY, moduleName);
@@ -117,10 +178,12 @@ public class ObjectNameUtil {
     }
 
     public static String getFactoryName(ObjectName objectName) {
+        checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
         return objectName.getKeyProperty(MODULE_FACTORY_NAME_KEY);
     }
 
     public static String getInstanceName(ObjectName objectName) {
+        checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
         return objectName.getKeyProperty(INSTANCE_NAME_KEY);
     }
 
@@ -132,6 +195,7 @@ public class ObjectNameUtil {
      * Sanitize on: keep only mandatory attributes of module + metadata.
      */
     public static ObjectName withoutTransactionName(ObjectName inputON) {
+        checkTypeOneOf(inputON, TYPE_MODULE, TYPE_SERVICE_REFERENCE);
         if (getTransactionName(inputON) == null) {
             throw new IllegalArgumentException(
                     "Expected ObjectName with transaction:" + inputON);
@@ -140,14 +204,18 @@ public class ObjectNameUtil {
             throw new IllegalArgumentException("Expected different domain: "
                     + inputON);
         }
-        String moduleName = getFactoryName(inputON);
-        String instanceName = getInstanceName(inputON);
-
-
+        Map<String, String> outputProperties;
+        if (inputON.getKeyProperty(TYPE_KEY).equals(TYPE_MODULE)) {
+            String moduleName = getFactoryName(inputON);
+            String instanceName = getInstanceName(inputON);
+            outputProperties = new HashMap<>(createModuleMap(moduleName, instanceName));
+        } else {
+            String serviceQName = getServiceQName(inputON);
+            String refName = getReferenceName(inputON);
+            outputProperties = new HashMap<>(createServiceMap(serviceQName, refName));
+        }
         Map<String, String> allProperties = getAdditionalProperties(inputON);
-        Map<String, String> outputProperties = new HashMap<>(createModuleON(moduleName, instanceName));
-
-        for(Entry<String, String> entry: allProperties.entrySet()) {
+        for (Entry<String, String> entry : allProperties.entrySet()) {
             if (entry.getKey().startsWith("X-")) {
                 outputProperties.put(entry.getKey(), entry.getValue());
             }
@@ -155,6 +223,13 @@ public class ObjectNameUtil {
         return createON(ON_DOMAIN, outputProperties);
     }
 
+    public static ObjectName withTransactionName(ObjectName inputON, String transactionName) {
+        Map<String, String> additionalProperties = getAdditionalProperties(inputON);
+        additionalProperties.put(TRANSACTION_NAME_KEY, transactionName);
+        return createON(inputON.getDomain(), additionalProperties);
+
+    }
+
     private static void assertDoesNotContain(
             Map<String, String> additionalProperties, String key) {
         if (additionalProperties.containsKey(key)) {
@@ -165,7 +240,7 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createRuntimeBeanName(String moduleName,
-            String instanceName, Map<String, String> additionalProperties) {
+                                                   String instanceName, Map<String, String> additionalProperties) {
         // check that there is no overwriting of default attributes
         assertDoesNotContain(additionalProperties, MODULE_FACTORY_NAME_KEY);
         assertDoesNotContain(additionalProperties, INSTANCE_NAME_KEY);
@@ -217,8 +292,18 @@ public class ObjectNameUtil {
         }
     }
 
+    public static void checkTypeOneOf(ObjectName objectName, String ... types) {
+        for(String type: types) {
+            if (type.equals(objectName.getKeyProperty(TYPE_KEY))) {
+                return;
+            }
+        }
+        throw new IllegalArgumentException("Wrong type, expected one of " + Arrays.asList(types)
+                + ", got " + objectName);
+    }
+
     public static ObjectName createModulePattern(String moduleName,
-            String instanceName) {
+                                                 String instanceName) {
         if (moduleName == null)
             moduleName = "*";
         if (instanceName == null)
@@ -235,7 +320,7 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createModulePattern(String ifcName,
-            String instanceName, String transactionName) {
+                                                 String instanceName, String transactionName) {
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
                 + ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
                 + "=" + ifcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
@@ -244,7 +329,7 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createRuntimeBeanPattern(String moduleName,
-            String instanceName) {
+                                                      String instanceName) {
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
                 + ObjectNameUtil.TYPE_KEY + "="
                 + ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
@@ -255,7 +340,7 @@ public class ObjectNameUtil {
     }
 
     public static ModuleIdentifier fromON(ObjectName objectName,
-            String expectedType) {
+                                          String expectedType) {
         checkType(objectName, expectedType);
         String factoryName = getFactoryName(objectName);
         if (factoryName == null)
@@ -268,4 +353,7 @@ public class ObjectNameUtil {
         return new ModuleIdentifier(factoryName, instanceName);
     }
 
+    public static boolean isServiceReference(ObjectName objectName) {
+        return TYPE_SERVICE_REFERENCE.equals(objectName.getKeyProperty(TYPE_KEY));
+    }
 }
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java
new file mode 100644 (file)
index 0000000..8c32507
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.config.manager.impl;
+
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+
+public interface CloseableServiceReferenceReadableRegistry  extends AutoCloseable, ServiceReferenceReadableRegistry {
+
+
+    void close();
+
+}
index e3311c747f872f601b0448e01d7e864163a15a75..19231705d1614f696e2e764260d971c59c513ecd 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.controller.config.manager.impl;
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
-import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
@@ -104,7 +103,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
     private List<ModuleFactory> lastListOfFactories = Collections.emptyList();
 
     @GuardedBy("this") // switched in every 2ndPC
-    private ServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
+    private CloseableServiceReferenceReadableRegistry  readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
 
     // constructor
     public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
@@ -298,8 +297,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             OsgiRegistration osgiRegistration = null;
             if (entry.hasOldModule()) {
                 ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo();
-                DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo
-                        .getReadableModule();
+                DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo.getReadableModule();
                 currentConfig.remove(entry.getIdentifier());
 
                 // test if old instance == new instance
@@ -368,7 +366,9 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
         version = configTransactionController.getVersion();
 
         // switch readable Service Reference Registry
-        this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(configTransactionController.getWritableRegistry(), this);
+        this.readableSRRegistry.close();
+        this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(
+                configTransactionController.getWritableRegistry(), this, baseJMXRegistrator);
 
         return new CommitStatus(newInstances, reusedInstances,
                 recreatedInstances);
@@ -525,8 +525,8 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
     // service reference functionality:
     @Override
-    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -535,8 +535,8 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
     }
 
     @Override
-    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -549,11 +549,28 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
         return readableSRRegistry.getServiceInterfaceName(namespace, localName);
     }
 
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        readableSRRegistry.checkServiceReferenceExists(objectName);
+    }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        return readableSRRegistry.getServiceReference(serviceInterfaceQName, refName);
+    }
+
     @Override
     public Set<String> getAvailableModuleFactoryQNames() {
         return ModuleQNameUtil.getQNames(resolver.getAllFactories());
     }
 
+    @Override
+    public String toString() {
+        return "ConfigRegistryImpl{" +
+                "versionCounter=" + versionCounter +
+                ", version=" + version +
+                '}';
+    }
 }
 
 /**
@@ -579,12 +596,12 @@ class ConfigHolder {
     }
 
     private void add(ModuleInternalInfo configInfo) {
-        ModuleInternalInfo oldValue = currentConfig.put(configInfo.getName(),
+        ModuleInternalInfo oldValue = currentConfig.put(configInfo.getIdentifier(),
                 configInfo);
         if (oldValue != null) {
             throw new IllegalStateException(
                     "Cannot overwrite module with same name:"
-                            + configInfo.getName() + ":" + configInfo);
+                            + configInfo.getIdentifier() + ":" + configInfo);
         }
     }
 
index 17ce0781546e231a5f81b2a8ca1b276f5a046d74..e0d1a42661362a0ef425526bec8e9abc5e4633b9 100644 (file)
@@ -95,7 +95,7 @@ class ConfigTransactionControllerImpl implements
         this.currentlyRegisteredFactories = currentlyRegisteredFactories;
         this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
         this.transactionStatus = new TransactionStatus();
-        this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus);
+        this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus, writableSRRegistry);
         this.transactionsMBeanServer = transactionsMBeanServer;
         this.configMBeanServer = configMBeanServer;
         this.blankTransaction = blankTransaction;
@@ -165,15 +165,14 @@ class ConfigTransactionControllerImpl implements
             throws InstanceAlreadyExistsException {
         transactionStatus.checkNotCommitStarted();
         transactionStatus.checkNotAborted();
-        ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getName();
+        ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier();
         dependencyResolverManager.assertNotExists(moduleIdentifier);
 
         ModuleFactory moduleFactory = factoriesHolder
                 .findByModuleName(moduleIdentifier.getFactoryName());
 
         Module module;
-        DependencyResolver dependencyResolver = dependencyResolverManager
-                .getOrCreate(moduleIdentifier);
+        DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
         try {
             BundleContext bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
             module = moduleFactory.createModule(
@@ -412,7 +411,7 @@ class ConfigTransactionControllerImpl implements
         close();
     }
 
-    private void close() {
+    public void close() {
         //FIXME: should not close object that was retrieved in constructor, a wrapper object should do that perhaps
         txLookupRegistry.close();
     }
@@ -523,8 +522,8 @@ class ConfigTransactionControllerImpl implements
 
 
     @Override
-    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -533,8 +532,8 @@ class ConfigTransactionControllerImpl implements
     }
 
     @Override
-    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -548,13 +547,13 @@ class ConfigTransactionControllerImpl implements
     }
 
     @Override
-    public synchronized void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
-        writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, objectName);
+    public synchronized ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
+        return writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, moduleON);
     }
 
     @Override
-    public synchronized boolean removeServiceReference(String serviceInterfaceName, String refName) {
-        return writableSRRegistry.removeServiceReference(serviceInterfaceName, refName);
+    public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException {
+        writableSRRegistry.removeServiceReference(serviceInterfaceName, refName);
     }
 
     @Override
@@ -581,4 +580,13 @@ class ConfigTransactionControllerImpl implements
         return txLookupRegistry.getAvailableModuleFactoryQNames();
     }
 
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        writableSRRegistry.checkServiceReferenceExists(objectName);
+    }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        return writableSRRegistry.getServiceReference(serviceInterfaceQName, refName);
+    }
 }
index 12db6c8f89e489114d0ad96b3e5e88ed1a97a4f3..a7d426ebdd78aa9d940b818f6f57ec8e58cd119c 100644 (file)
@@ -117,6 +117,13 @@ class ConfigTransactionLookupRegistry  implements LookupRegistry, Closeable {
         return ModuleQNameUtil.getQNames(allCurrentFactories);
     }
 
+
+    @Override
+    public String toString() {
+        return "ConfigTransactionLookupRegistry{" +
+                "transactionIdentifier=" + transactionIdentifier +
+                '}';
+    }
 }
 
 interface TransactionJMXRegistratorFactory {
index 14a706dd9b990e9251233aacef2db022502fb1dc..941aec10969fd90c700d257579b02c88520e40e9 100644 (file)
@@ -90,11 +90,6 @@ public class ModuleInternalInfo implements Comparable<ModuleInternalInfo>,
         return osgiRegistration;
     }
 
-    @Deprecated
-    public ModuleIdentifier getName() {
-        return name;
-    }
-
     /**
      * Get index representing dependency ordering within a transaction.
      */
@@ -111,7 +106,7 @@ public class ModuleInternalInfo implements Comparable<ModuleInternalInfo>,
     }
 
     public DestroyedModule toDestroyedModule() {
-        return new DestroyedModule(getName(),
+        return new DestroyedModule(getIdentifier(),
                 getReadableModule().getInstance(), getModuleJMXRegistrator(),
                 getOsgiRegistration(), getOrderingIdx());
     }
index 7fedcdf71ce7ce28974cc06a1e72c42720b04248..0faa32b7dc4e181962802d8d5e1345472d8378d9 100644 (file)
@@ -13,42 +13,52 @@ import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReference;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBeanImpl;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceJMXRegistration;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceTransactionRegistratorFactory;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceTransactionRegistratorFactoryImpl;
 import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
     private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class);
 
     private final Map<String, ModuleFactory> factories;
     private final Map<String, Set<String>> factoryNamesToQNames;
     // validator of incoming ObjectNames - throws InstanceNotFoundException if not found either in registry or transaction
     private final LookupRegistry lookupRegistry;
+    private final ServiceReferenceRegistrator serviceReferenceRegistrator;
     // helper method for getting QName of SI from namespace + local name
     private final Map<String /* namespace */, Map<String /* local name */, ServiceInterfaceAnnotation>> namespacesToAnnotations;
     // all Service Interface qNames for sanity checking
     private final Set<String /* qName */> allQNames;
 
     // actual reference database
-    private final Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> refNames;
+    private final Map<ServiceReference, ModuleIdentifier> refNames = new HashMap<>();
+    private final boolean writable;
+    private final Map<ServiceReference, Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>> mBeans = new HashMap<>();
 
     /**
      * Static constructor for config registry. Since only transaction can write to this registry, it will
      * return blank state.
      */
-    public static ServiceReferenceReadableRegistry createInitialSRLookupRegistry() {
+    public static CloseableServiceReferenceReadableRegistry createInitialSRLookupRegistry() {
         // since this is initial state, just throw exception:
         LookupRegistry lookupRegistry = new LookupRegistry() {
             @Override
@@ -73,36 +83,99 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
 
             @Override
             public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
-                throw new InstanceNotFoundException("Cannot find " + objectName);
+                throw new InstanceNotFoundException("Cannot find " + objectName + " - Tried to use mocking registry");
             }
 
             @Override
             public Set<String> getAvailableModuleFactoryQNames() {
                 throw new UnsupportedOperationException();
             }
+
+            @Override
+            public String toString() {
+                return "initial";
+            }
+        };
+        ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactory(){
+            @Override
+            public ServiceReferenceRegistrator create() {
+                return new ServiceReferenceRegistrator() {
+                    @Override
+                    public String getNullableTransactionName() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    @Override
+                    public ServiceReferenceJMXRegistration registerMBean(ServiceReferenceMXBeanImpl object, ObjectName on) throws InstanceAlreadyExistsException {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    @Override
+                    public void close() {
+
+                    }
+                };
+            }
         };
         return new ServiceReferenceRegistryImpl(Collections.<String, ModuleFactory>emptyMap(), lookupRegistry,
-                Collections.<String /* qName */, Map<String /* refName */, ModuleIdentifier>>emptyMap());
+                serviceReferenceRegistratorFactory, false);
     }
 
     /**
      * Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data.
      */
     public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
-            LookupRegistry lookupRegistry, Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
+                                                    ConfigTransactionLookupRegistry txLookupRegistry,
+                                                    Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
 
+        if (txLookupRegistry == null) {
+            throw new IllegalArgumentException("txLookupRegistry is null");
+        }
         ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldReadableRegistry;
         Map<String, ModuleFactory> factories = extractFactoriesMap(currentlyRegisteredFactories);
-        return new ServiceReferenceRegistryImpl(factories, lookupRegistry, Collections.unmodifiableMap(old.refNames));
+        ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactoryImpl(
+                txLookupRegistry.getTxModuleJMXRegistrator(), txLookupRegistry.getTxModuleJMXRegistrator().getTransactionName());
+        ServiceReferenceRegistryImpl newRegistry = new ServiceReferenceRegistryImpl(factories, txLookupRegistry,
+                serviceReferenceRegistratorFactory, true);
+        copy(old, newRegistry, txLookupRegistry.getTransactionIdentifier().getName());
+        return newRegistry;
     }
 
     /**
      * Copy back state to config registry after commit.
      */
-    public static ServiceReferenceReadableRegistry createSRReadableRegistry(ServiceReferenceWritableRegistry oldWritableRegistry, LookupRegistry lookupRegistry) {
+    public static CloseableServiceReferenceReadableRegistry createSRReadableRegistry(ServiceReferenceWritableRegistry oldWritableRegistry,
+                                                                            LookupRegistry lookupRegistry, BaseJMXRegistrator baseJMXRegistrator) {
         ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldWritableRegistry;
+
         // even if factories do change, nothing in the mapping can change between transactions
-        return new ServiceReferenceRegistryImpl(old.factories, lookupRegistry, Collections.unmodifiableMap(old.refNames));
+        ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactoryImpl(baseJMXRegistrator);
+        ServiceReferenceRegistryImpl newRegistry = new ServiceReferenceRegistryImpl(old.factories, lookupRegistry,
+                serviceReferenceRegistratorFactory, false);
+        copy(old, newRegistry, null);
+        return newRegistry;
+    }
+
+    /**
+     * Fill refNames and mBeans maps from old instance
+     */
+    private static void copy(ServiceReferenceRegistryImpl old, ServiceReferenceRegistryImpl newRegistry, String nullableDstTransactionName) {
+        for (Entry<ServiceReference, Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>> refNameEntry : old.mBeans.entrySet()) {
+            ObjectName currentImplementation;
+            ObjectName currentImplementationSrc = refNameEntry.getValue().getKey().getCurrentImplementation();
+            if (nullableDstTransactionName != null) {
+                currentImplementation = ObjectNameUtil.withTransactionName(currentImplementationSrc, nullableDstTransactionName);
+            } else {
+                currentImplementation = ObjectNameUtil.withoutTransactionName(currentImplementationSrc);
+            }
+            try {
+                boolean skipChecks = true;
+                newRegistry.saveServiceReference(refNameEntry.getKey(), currentImplementation, skipChecks);
+            } catch (InstanceNotFoundException e) {
+                logger.error("Cannot save service reference({}, {})", refNameEntry.getKey(), currentImplementation);
+                throw new IllegalStateException("Possible code error", e);
+            }
+        }
     }
 
     private static Map<String, ModuleFactory> extractFactoriesMap(Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
@@ -114,9 +187,14 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
     }
 
     private ServiceReferenceRegistryImpl(Map<String, ModuleFactory> factories, LookupRegistry lookupRegistry,
-                                         Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> refNamesToCopy) {
+                                         ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory,
+                                         boolean writable) {
         this.factories = factories;
+        this.writable = writable;
         this.lookupRegistry = lookupRegistry;
+
+        this.serviceReferenceRegistrator = serviceReferenceRegistratorFactory.create();
+
         Map<String, Set<String /* QName */>> factoryNamesToQNames = new HashMap<>();
         Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
         Set<String /* qName */> allQNames = new HashSet<>();
@@ -154,22 +232,12 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
         }
         this.namespacesToAnnotations = Collections.unmodifiableMap(namespacesToAnnotations);
         // copy refNames
-        Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> deepCopy = new HashMap<>();
-        for (Entry<String, Map<String, ModuleIdentifier>> outerROEntry: refNamesToCopy.entrySet()) {
-            Map<String /* refName */, ModuleIdentifier> innerWritableMap = new HashMap<>();
-            deepCopy.put(outerROEntry.getKey(), innerWritableMap);
-            for (Entry<String, ModuleIdentifier> innerROEntry:  outerROEntry.getValue().entrySet()) {
-                innerWritableMap.put(innerROEntry.getKey(), innerROEntry.getValue());
-            }
-        }
-        this.refNames = deepCopy;
         logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
-        logger.trace("refNames:{}", refNames);
     }
 
 
     @Override
-    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+    public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
         lookupRegistry.checkConfigBeanExists(objectName);
 
         String factoryName = ObjectNameUtil.getFactoryName(objectName);
@@ -183,7 +251,7 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
     }
 
     @Override
-    public String getServiceInterfaceName(String namespace, String localName) {
+    public synchronized String getServiceInterfaceName(String namespace, String localName) {
         Map<String /* localName */, ServiceInterfaceAnnotation> ofNamespace = namespacesToAnnotations.get(namespace);
         if (ofNamespace == null) {
             logger.error("Cannot find namespace {} in {}", namespace, namespacesToAnnotations);
@@ -197,23 +265,19 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
         return sia.value();
     }
 
-
-
     // reading:
 
     @Override
-    public Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
+    public synchronized Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
         Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> result = new HashMap<>();
-        for (Entry<String /* qName */, Map<String, ModuleIdentifier>> outerEntry: refNames.entrySet()) {
-            String qName = outerEntry.getKey();
-            Map<String /* refName */, ObjectName> innerMap = new HashMap<>();
-            result.put(qName, innerMap);
-            for (Entry<String /* refName */, ModuleIdentifier> innerEntry: outerEntry.getValue().entrySet()) {
-                ModuleIdentifier moduleIdentifier = innerEntry.getValue();
-                ObjectName on;
-                on = getObjectName(moduleIdentifier);
-                innerMap.put(innerEntry.getKey(), on);
+        for (Entry<ServiceReference, ModuleIdentifier> entry: refNames.entrySet()) {
+            String qName = entry.getKey().getServiceInterfaceName();
+            Map<String /* refName */, ObjectName> innerMap = result.get(qName);
+            if (innerMap == null) {
+                innerMap = new HashMap<>();
+                result.put(qName, innerMap);
             }
+            innerMap.put(entry.getKey().getRefName(), getObjectName(entry.getValue()));
         }
         return result;
     }
@@ -230,116 +294,227 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        Map<String, ModuleIdentifier> innerMap = refNames.get(serviceInterfaceName);
-        if (innerMap == null) {
-            logger.error("Cannot find qname {} in {}", serviceInterfaceName, refName);
-            throw new IllegalArgumentException("Cannot find " + serviceInterfaceName);
-        }
-        ModuleIdentifier moduleIdentifier = innerMap.get(refName);
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceQName, refName);
+        ModuleIdentifier moduleIdentifier = refNames.get(serviceReference);
         if (moduleIdentifier == null) {
-            logger.error("Cannot find refName {} in {}, using qname {}", refName, innerMap, serviceInterfaceName);
-            throw new IllegalArgumentException("Cannot find module based on service reference " + refName);
+            logger.error("Cannot find qname {} and refName {} in {}", serviceInterfaceQName, refName, refName);
+            throw new IllegalArgumentException("Cannot find " + serviceReference);
         }
         return getObjectName(moduleIdentifier);
     }
 
     @Override
-    public  Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        Map<String, ModuleIdentifier> innerMap = refNames.get(serviceInterfaceName);
+    public synchronized Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        Map<String, Map<String, ObjectName>> serviceMapping = getServiceMapping();
+        Map<String, ObjectName> innerMap = serviceMapping.get(serviceInterfaceQName);
         if (innerMap == null) {
-            logger.error("Cannot find qname {} in {}", serviceInterfaceName, refNames);
-            throw new IllegalArgumentException("Cannot find " + serviceInterfaceName);
+            logger.error("Cannot find qname {} in {}", serviceInterfaceQName, refNames);
+            throw new IllegalArgumentException("Cannot find " + serviceInterfaceQName);
         }
-        Map<String /* refName */, ObjectName> result = new HashMap<>();
-        for (Entry<String/* refName */, ModuleIdentifier> entry: innerMap.entrySet()) {
-            ObjectName on = getObjectName(entry.getValue());
-            result.put(entry.getKey(), on);
+        return innerMap;
+    }
+
+    @Override
+    public synchronized ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceQName, refName);
+        if (mBeans.containsKey(serviceReference) == false) {
+            throw new InstanceNotFoundException("Cannot find " + serviceReference);
+        }
+        return getServiceON(serviceReference);
+    }
+
+    @Override
+    public synchronized void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        String actualTransactionName = ObjectNameUtil.getTransactionName(objectName);
+        String expectedTransactionName = serviceReferenceRegistrator.getNullableTransactionName();
+        if (writable & actualTransactionName == null || (writable && actualTransactionName.equals(expectedTransactionName) == false)) {
+            throw new IllegalArgumentException("Mismatched transaction name in " + objectName);
+        }
+        String serviceQName = ObjectNameUtil.getServiceQName(objectName);
+        String referenceName = ObjectNameUtil.getReferenceName(objectName);
+        ServiceReference serviceReference = new ServiceReference(serviceQName, referenceName);
+        if (refNames.containsKey(serviceReference) == false) {
+            logger.warn("Cannot find {} in {}", serviceReference, refNames);
+            throw new InstanceNotFoundException("Service reference not found:" + objectName);
         }
-        return result;
     }
 
     // writing:
 
+    private void assertWritable() {
+        if (writable == false) {
+            throw new IllegalStateException("Cannot write to readable registry");
+        }
+    }
+
     @Override
-    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName)  throws InstanceNotFoundException {
+    public synchronized ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON)  throws InstanceNotFoundException {
+        assertWritable();
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceName, refName);
+        return saveServiceReference(serviceReference, moduleON);
+    }
+
+    private synchronized ObjectName saveServiceReference(ServiceReference serviceReference, ObjectName moduleON)
+            throws InstanceNotFoundException{
+        return saveServiceReference(serviceReference, moduleON, false);
+    }
+
+    private synchronized ObjectName saveServiceReference(ServiceReference serviceReference, ObjectName moduleON,
+                                                         boolean skipChecks) throws InstanceNotFoundException {
+
         // make sure it is found
-        lookupRegistry.checkConfigBeanExists(objectName);
-        String factoryName = ObjectNameUtil.getFactoryName(objectName);
+        if (skipChecks == false) {
+            lookupRegistry.checkConfigBeanExists(moduleON);
+        }
+        String factoryName = ObjectNameUtil.getFactoryName(moduleON);
+        String instanceName = ObjectNameUtil.getInstanceName(moduleON);
+        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
+
         // check that service interface name exist
-        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
+        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(moduleIdentifier.getFactoryName());
         if (serviceInterfaceQNames == null) {
-            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName);
-            throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
+            logger.error("Possible error in code: cannot find factoryName {} in {}, {}", moduleIdentifier.getFactoryName(),
+                    factoryNamesToQNames, moduleIdentifier);
+            throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + moduleIdentifier.getFactoryName());
         }
         // supplied serviceInterfaceName must exist in this collection
-        if (serviceInterfaceQNames.contains(serviceInterfaceName) == false) {
-            logger.error("Cannot find qname {} with factory name {}, found {}", serviceInterfaceName, factoryName, serviceInterfaceQNames);
-            throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName + " within factory " + factoryName );
+        if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
+            logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName() + " within factory " + moduleIdentifier.getFactoryName());
         }
-        String instanceName = ObjectNameUtil.getInstanceName(objectName);
-        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
-        Map<String /* refName */, ModuleIdentifier> ofQName = refNames.get(serviceInterfaceName);
-        // might be null
-        if (ofQName == null) {
-            ofQName = new HashMap<>();
-            refNames.put(serviceInterfaceName, ofQName);
+
+
+        // create service reference object name, put to mBeans
+        ObjectName result = getServiceON(serviceReference);
+        Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> mxBeanEntry = mBeans.get(serviceReference);
+        if (mxBeanEntry == null) {
+            // create dummy mx bean
+            ServiceReferenceMXBeanImpl dummyMXBean = new ServiceReferenceMXBeanImpl(moduleON);
+            ServiceReferenceJMXRegistration dummyMXBeanRegistration;
+            try {
+                dummyMXBeanRegistration = serviceReferenceRegistrator.registerMBean(dummyMXBean, result);
+            } catch (InstanceAlreadyExistsException e) {
+                throw new IllegalStateException("Possible error in code. Cannot register " + result, e);
+            }
+            mBeans.put(serviceReference, createMXBeanEntry(dummyMXBean, dummyMXBeanRegistration));
+        } else {
+            // update
+            mxBeanEntry.getKey().setCurrentImplementation(moduleON);
+        }
+        // save to refNames
+        refNames.put(serviceReference, moduleIdentifier);
+        return result;
+    }
+
+    private Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> createMXBeanEntry(
+            final ServiceReferenceMXBeanImpl mxBean, final ServiceReferenceJMXRegistration registration) {
+        return new Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>() {
+            @Override
+            public ServiceReferenceMXBeanImpl getKey() {
+                return mxBean;
+            }
+
+            @Override
+            public ServiceReferenceJMXRegistration getValue() {
+                return registration;
+            }
+
+            @Override
+            public ServiceReferenceJMXRegistration setValue(ServiceReferenceJMXRegistration value) {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    private ObjectName getServiceON(ServiceReference serviceReference) {
+        if (writable) {
+            return ObjectNameUtil.createTransactionServiceON(serviceReferenceRegistrator.getNullableTransactionName(),
+                    serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+        } else {
+            return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
         }
-        ofQName.put(refName, moduleIdentifier);
     }
 
     @Override
-    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
-        // is the qname known?
-        if (allQNames.contains(serviceInterfaceName) == false) {
-            logger.error("Cannot find qname {} in {}", serviceInterfaceName, allQNames);
-            throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName);
+    public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException{
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceName, refName);
+        removeServiceReference(serviceReference);
+    }
+
+    private synchronized void removeServiceReference(ServiceReference serviceReference) throws InstanceNotFoundException {
+        logger.debug("Removing service reference {} from {}", serviceReference, this);
+        assertWritable();
+        // is the qName known?
+        if (allQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
+            logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceName(), allQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName());
+        }
+        ModuleIdentifier removed = refNames.remove(serviceReference);
+        if (removed == null){
+            throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceName());
         }
-        Map<String, ModuleIdentifier> ofQName = refNames.get(serviceInterfaceName);
-        if (ofQName == null) {
-            return false;
+        Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> entry = mBeans.remove(serviceReference);
+        if (entry == null) {
+            throw new IllegalStateException("Possible code error: cannot remove from mBeans: " + serviceReference);
         }
-        return ofQName.remove(refName) != null;
+        entry.getValue().close();
     }
 
     @Override
-    public void removeAllServiceReferences() {
-        refNames.clear();
+    public synchronized void removeAllServiceReferences() {
+        assertWritable();
+        for (ServiceReference serviceReference: mBeans.keySet()) {
+            try {
+                removeServiceReference(serviceReference);
+            } catch (InstanceNotFoundException e) {
+                throw new IllegalStateException("Possible error in code", e);
+            }
+        }
     }
 
     @Override
-    public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
-        lookupRegistry.checkConfigBeanExists(objectName);
-        String factoryName = ObjectNameUtil.getFactoryName(objectName);
+    public synchronized boolean removeServiceReferences(ObjectName moduleObjectName) throws InstanceNotFoundException {
+        assertWritable();
+        Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName);
+        for (ServiceReference sr : serviceReferencesLinkingTo) {
+            removeServiceReference(sr);
+        }
+        return serviceReferencesLinkingTo.isEmpty() == false;
+    }
+
+    private synchronized Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName)  throws InstanceNotFoundException {
+        lookupRegistry.checkConfigBeanExists(moduleObjectName);
+        String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
         // check that service interface name exist
         Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
         if (serviceInterfaceQNames == null) {
-            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName);
+            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
             throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
         }
-        String instanceName = ObjectNameUtil.getInstanceName(objectName);
+        String instanceName = ObjectNameUtil.getInstanceName(moduleObjectName);
         ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
-        boolean found = false;
-        for(String qName: serviceInterfaceQNames){
-            Map<String, ModuleIdentifier> ofQName = refNames.get(qName);
-            if (ofQName != null) {
-                for(Iterator<Entry<String, ModuleIdentifier>> it = ofQName.entrySet ().iterator(); it.hasNext();){
-                    Entry<String, ModuleIdentifier> next = it.next();
-                    if (next.getValue().equals(moduleIdentifier)) {
-                        found = true;
-                        it.remove();
-                    }
-                }
+        Set<ServiceReference> result = new HashSet<>();
+        for (Entry<ServiceReference, ModuleIdentifier> entry : refNames.entrySet()) {
+            if (entry.getValue().equals(moduleIdentifier)) {
+                result.add(entry.getKey());
             }
         }
-        return found;
+        return result;
     }
 
+
     @Override
     public String toString() {
         return "ServiceReferenceRegistryImpl{" +
+                "lookupRegistry=" + lookupRegistry +
                 "refNames=" + refNames +
                 ", factoryNamesToQNames=" + factoryNamesToQNames +
                 '}';
     }
+
+    @Override
+    public void close() {
+        serviceReferenceRegistrator.close();
+    }
 }
index 760fe50e28f533021684f1d1a0bb25685272fac8..925a57b044f44f87c31bf1aa9e8d60d7ebf210c9 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
@@ -37,12 +38,16 @@ final class DependencyResolverImpl implements DependencyResolver,
     private final TransactionStatus transactionStatus;
     @GuardedBy("this")
     private final Set<ModuleIdentifier> dependencies = new HashSet<>();
+    private final ServiceReferenceReadableRegistry readableRegistry;
 
     DependencyResolverImpl(ModuleIdentifier currentModule,
-            TransactionStatus transactionStatus, ModulesHolder modulesHolder) {
+            TransactionStatus transactionStatus, ModulesHolder modulesHolder,
+            ServiceReferenceReadableRegistry readableRegistry) {
+
         this.name = currentModule;
         this.transactionStatus = transactionStatus;
         this.modulesHolder = modulesHolder;
+        this.readableRegistry = readableRegistry;
     }
 
     /**
@@ -52,7 +57,7 @@ final class DependencyResolverImpl implements DependencyResolver,
     @Override
     public void validateDependency(
             Class<? extends AbstractServiceInterface> expectedServiceInterface,
-            ObjectName dependentModuleReadOnlyON, JmxAttribute jmxAttribute) {
+            ObjectName dependentReadOnlyON, JmxAttribute jmxAttribute) {
 
         transactionStatus.checkNotCommitted();
         if (expectedServiceInterface == null) {
@@ -62,22 +67,26 @@ final class DependencyResolverImpl implements DependencyResolver,
         if (jmxAttribute == null)
             throw new NullPointerException("Parameter 'jmxAttribute' is null");
 
-        JmxAttributeValidationException.checkNotNull(dependentModuleReadOnlyON,
+        JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
                 "is null, " + "expected dependency implementing "
                         + expectedServiceInterface, jmxAttribute);
 
+
+
         // check that objectName belongs to this transaction - this should be
         // stripped
         // in DynamicWritableWrapper
         boolean hasTransaction = ObjectNameUtil
-                .getTransactionName(dependentModuleReadOnlyON) != null;
+                .getTransactionName(dependentReadOnlyON) != null;
         JmxAttributeValidationException.checkCondition(
                 hasTransaction == false,
                 format("ObjectName should not contain "
                         + "transaction name. %s set to %s. ", jmxAttribute,
-                        dependentModuleReadOnlyON), jmxAttribute);
+                        dependentReadOnlyON), jmxAttribute);
+
+        dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
 
-        ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(dependentModuleReadOnlyON, ObjectNameUtil
+        ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(dependentReadOnlyON, ObjectNameUtil
                 .TYPE_MODULE);
 
         ModuleFactory foundFactory = modulesHolder.findModuleFactory(moduleIdentifier, jmxAttribute);
@@ -90,7 +99,7 @@ final class DependencyResolverImpl implements DependencyResolver,
                             + "Module name is %s : %s, expected service interface %s, dependent module ON %s , "
                             + "attribute %s",
                     foundFactory.getImplementationName(), foundFactory,
-                    expectedServiceInterface, dependentModuleReadOnlyON,
+                    expectedServiceInterface, dependentReadOnlyON,
                     jmxAttribute);
             throw new JmxAttributeValidationException(message, jmxAttribute);
         }
@@ -99,24 +108,35 @@ final class DependencyResolverImpl implements DependencyResolver,
         }
     }
 
+    // transalate from serviceref to module ON
+    private ObjectName translateServiceRefIfPossible(ObjectName dependentReadOnlyON) {
+        if (ObjectNameUtil.isServiceReference(dependentReadOnlyON)) {
+            String serviceQName = ObjectNameUtil.getServiceQName(dependentReadOnlyON);
+            String refName = ObjectNameUtil.getReferenceName(dependentReadOnlyON);
+            dependentReadOnlyON = ObjectNameUtil.withoutTransactionName( // strip again of transaction name
+                    readableRegistry.lookupConfigBeanByServiceInterfaceName(serviceQName, refName));
+        }
+        return dependentReadOnlyON;
+    }
+
     /**
      * {@inheritDoc}
      */
     //TODO: check for cycles
     @Override
-    public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentON,
+    public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentReadOnlyON,
             JmxAttribute jmxAttribute) {
-        if (expectedType == null || dependentON == null || jmxAttribute == null) {
+        if (expectedType == null || dependentReadOnlyON == null || jmxAttribute == null) {
             throw new IllegalArgumentException(format(
                     "Null parameters not allowed, got {} {} {}", expectedType,
-                    dependentON, jmxAttribute));
+                    dependentReadOnlyON, jmxAttribute));
         }
-
+        dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
         transactionStatus.checkCommitStarted();
         transactionStatus.checkNotCommitted();
 
         ModuleIdentifier dependentModuleIdentifier = ObjectNameUtil.fromON(
-                dependentON, ObjectNameUtil.TYPE_MODULE);
+                dependentReadOnlyON, ObjectNameUtil.TYPE_MODULE);
         Module module = modulesHolder.findModule(dependentModuleIdentifier,
                 jmxAttribute);
         synchronized (this) {
index 645aab37ff770cfc3cbe6399f139a7cf68a07470..afd865c4fc859a1de2e7ea9bbd6885f30be5d036 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.manager.impl.CommitInfo;
 import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
@@ -35,11 +36,13 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
     private final Map<ModuleIdentifier, DependencyResolverImpl> moduleIdentifiersToDependencyResolverMap = new HashMap<>();
     private final ModulesHolder modulesHolder;
     private final TransactionStatus transactionStatus;
+    private final ServiceReferenceReadableRegistry readableRegistry;
 
     public DependencyResolverManager(String transactionName,
-            TransactionStatus transactionStatus) {
+            TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry) {
         this.modulesHolder = new ModulesHolder(transactionName);
         this.transactionStatus = transactionStatus;
+        this.readableRegistry = readableRegistry;
     }
 
     @Override
@@ -48,14 +51,11 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
     }
 
     public synchronized DependencyResolverImpl getOrCreate(ModuleIdentifier name) {
-        DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap
-                .get(name);
+        DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name);
         if (dependencyResolver == null) {
             transactionStatus.checkNotCommitted();
-            dependencyResolver = new DependencyResolverImpl(name,
-                    transactionStatus, modulesHolder);
-            moduleIdentifiersToDependencyResolverMap.put(name,
-                    dependencyResolver);
+            dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry);
+            moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
         }
         return dependencyResolver;
     }
index ba2c1089c2bef93bbcacbbc98019c6ab5045043d..6f0d1b2682a00e17b8935cca72c86599cd2b2b63 100644 (file)
@@ -7,16 +7,14 @@
  */
 package org.opendaylight.controller.config.manager.impl.dynamicmbean;
 
-import static java.lang.String.format;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.annotations.Description;
+import org.opendaylight.controller.config.api.annotations.RequireInterface;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
+import org.opendaylight.controller.config.spi.Module;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.management.Attribute;
 import javax.management.AttributeList;
@@ -40,15 +38,17 @@ import javax.management.Notification;
 import javax.management.NotificationListener;
 import javax.management.ObjectName;
 import javax.management.ReflectionException;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.annotations.Description;
-import org.opendaylight.controller.config.api.annotations.RequireInterface;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
-import org.opendaylight.controller.config.spi.Module;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import static java.lang.String.format;
 
 /**
  * Contains common code for readable/rw dynamic mbean wrappers. Routes all
@@ -246,6 +246,7 @@ abstract class AbstractDynamicWrapper implements DynamicMBeanModuleWrapper {
         } catch (InstanceNotFoundException e) {
             new MBeanException(e);
         }
+
         if (obj instanceof ObjectName) {
             AttributeHolder attributeHolder = attributeHolderMap
                     .get(attributeName);
@@ -254,8 +255,42 @@ abstract class AbstractDynamicWrapper implements DynamicMBeanModuleWrapper {
             }
             return obj;
         }
+
+
+        if(isDependencyListAttr(attributeName, obj)) {
+            obj = fixDependencyListAttribute(obj);
+        }
+
         return obj;
+    }
+
+    private Object fixDependencyListAttribute(Object attribute) {
+        if(attribute.getClass().isArray() == false)
+            throw new IllegalArgumentException("Unexpected attribute type, should be an array, but was " + attribute.getClass());
+
+        for (int i = 0; i < Array.getLength(attribute); i++) {
+
+            Object on = Array.get(attribute, i);
+            if(on instanceof ObjectName == false)
+                throw new IllegalArgumentException("Unexpected attribute type, should be an ObjectName, but was " + on.getClass());
+            on = fixObjectName((ObjectName) on);
+
+            Array.set(attribute, i, on);
+        }
+
+        return attribute;
+    }
+
+    private boolean isDependencyListAttr(String attributeName, Object attribute) {
+        if (attributeHolderMap.containsKey(attributeName) == false)
+            return false;
+
+        AttributeHolder attributeHolder = attributeHolderMap.get(attributeName);
 
+        boolean isDepList = true;
+        isDepList &= attributeHolder.getRequireInterfaceOrNull() != null;
+        isDepList &= attribute instanceof ObjectName[];
+        return isDepList;
     }
 
     protected ObjectName fixObjectName(ObjectName on) {
index 109ab10ac2a086e590ab1023bfa2ffd1442e8ad8..9dd6a2269e259cf4ca5ee4e6b1331d85ef015d81 100644 (file)
@@ -7,18 +7,17 @@
  */
 package org.opendaylight.controller.config.manager.impl.dynamicmbean;
 
-import java.lang.reflect.Method;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import org.opendaylight.controller.config.api.annotations.Description;
+import org.opendaylight.controller.config.api.annotations.RequireInterface;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import javax.management.MBeanAttributeInfo;
 import javax.management.ObjectName;
-
-import org.opendaylight.controller.config.api.annotations.Description;
-import org.opendaylight.controller.config.api.annotations.RequireInterface;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 @Immutable
 class AttributeHolder {
@@ -32,6 +31,14 @@ class AttributeHolder {
     private final RequireInterface requireInterfaceAnnotation;
     private final String attributeType;
 
+    public static final Set<Class<?>> PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER = new HashSet<>();
+
+    static {
+        PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.add(ObjectName.class);
+        PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.add(ObjectName[].class);
+        PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.add(List.class);
+    }
+
     public AttributeHolder(String name, Object object, String returnType,
             boolean writable,
             @Nullable RequireInterface requireInterfaceAnnotation,
@@ -114,12 +121,12 @@ class AttributeHolder {
     static RequireInterface findRequireInterfaceAnnotation(final Method setter,
             Set<Class<?>> inspectedInterfaces) {
 
-        // only allow setX(ObjectName y) or setX(ObjectName[] y) to continue
-        if (setter.getParameterTypes().length != 1
-                || (setter.getParameterTypes()[0].equals(ObjectName.class) == false && setter
-                        .getParameterTypes()[0].equals(ObjectName[].class) == false)) {
+        // only allow setX(ObjectName y) or setX(ObjectName[] y) or setX(List<ObjectName> y) to continue
+
+        if (setter.getParameterTypes().length > 1)
+            return null;
+        if(PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.contains(setter.getParameterTypes()[0]) == false)
             return null;
-        }
 
         List<RequireInterface> foundRequireInterfaces = AnnotationsHelper
                 .findMethodAnnotationInSuperClassesAndIfcs(setter, RequireInterface.class, inspectedInterfaces);
index a1cd6b01339dd7fc82864c3219bc5f32fc7de0ba..2ab04e53e304fa8909543ded413b408941566fcc 100644 (file)
@@ -7,7 +7,13 @@
  */
 package org.opendaylight.controller.config.manager.impl.dynamicmbean;
 
-import java.lang.reflect.Method;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
+import org.opendaylight.controller.config.spi.Module;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.annotation.concurrent.ThreadSafe;
 import javax.management.Attribute;
@@ -20,14 +26,7 @@ import javax.management.MBeanOperationInfo;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 import javax.management.ReflectionException;
-
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
-import org.opendaylight.controller.config.spi.Module;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.lang.reflect.Method;
 
 /**
  * Wraps {@link org.opendaylight.controller.config.spi.Module} instance in a
@@ -92,16 +91,11 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper {
 
         try {
             if (attribute.getValue() instanceof ObjectName) {
-                AttributeHolder attributeHolder = attributeHolderMap
-                        .get(attribute.getName());
-                if (attributeHolder.getRequireInterfaceOrNull() != null) {
-                    attribute = new Attribute(attribute.getName(),
-                            fixObjectName((ObjectName) attribute.getValue()));
-                } else {
-                    attribute = new Attribute(attribute.getName(),
-                            attribute.getValue());
-                }
+                attribute = fixDependencyAttribute(attribute);
+            } else if(attribute.getValue() instanceof ObjectName[]) {
+                attribute = fixDependencyListAttribute(attribute);
             }
+
             internalServer.setAttribute(objectNameInternal, attribute);
         } catch (InstanceNotFoundException e) {
             throw new MBeanException(e);
@@ -109,6 +103,39 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper {
 
     }
 
+    private Attribute fixDependencyListAttribute(Attribute attribute) {
+        AttributeHolder attributeHolder = attributeHolderMap
+                .get(attribute.getName());
+        if (attributeHolder.getRequireInterfaceOrNull() != null) {
+            attribute = new Attribute(attribute.getName(),
+                    fixObjectNames((ObjectName[]) attribute.getValue()));
+        }
+        return attribute;
+    }
+
+    private Attribute fixDependencyAttribute(Attribute attribute) {
+        AttributeHolder attributeHolder = attributeHolderMap
+                .get(attribute.getName());
+        if (attributeHolder.getRequireInterfaceOrNull() != null) {
+            attribute = new Attribute(attribute.getName(),
+                    fixObjectName((ObjectName) attribute.getValue()));
+        } else {
+            attribute = new Attribute(attribute.getName(),
+                    attribute.getValue());
+        }
+        return attribute;
+    }
+
+    private ObjectName[] fixObjectNames(ObjectName[] dependencies) {
+        int i = 0;
+
+        for (ObjectName dependencyOn : dependencies) {
+            dependencies[i++] = fixObjectName(dependencyOn);
+        }
+
+        return dependencies;
+    }
+
     @Override
     public AttributeList setAttributes(AttributeList attributes) {
         AttributeList result = new AttributeList();
index 09bc1f818fc563ae11e432cec37e148459a2e7dd..d09fc75d7374f4aef55d96a08ebb291322512d4b 100644 (file)
@@ -14,7 +14,7 @@ import javax.management.ObjectName;
 import javax.management.QueryExp;
 import java.util.Set;
 
-public class BaseJMXRegistrator implements AutoCloseable {
+public class BaseJMXRegistrator implements AutoCloseable, NestableJMXRegistrator {
 
     private final InternalJMXRegistrator internalJMXRegistrator;
 
@@ -50,6 +50,11 @@ public class BaseJMXRegistrator implements AutoCloseable {
         return internalJMXRegistrator.getRegisteredObjectNames();
     }
 
+    @Override
+    public InternalJMXRegistrator createChild() {
+        return internalJMXRegistrator.createChild();
+    }
+
     @Override
     public void close() {
         internalJMXRegistrator.close();
@@ -5,10 +5,9 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.ssh.authentication;
+package org.opendaylight.controller.config.manager.impl.jmx;
 
-import ch.ethz.ssh2.signature.RSAPrivateKey;
+public interface NestableJMXRegistrator {
 
-public interface KeyStoreHandler {
-    public RSAPrivateKey getPrivateKey();
+    InternalJMXRegistrator createChild();
 }
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java
new file mode 100644 (file)
index 0000000..849f752
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.config.manager.impl.jmx;
+
+public class ServiceReference {
+    private final String serviceInterfaceName, refName;
+
+    public ServiceReference(String serviceInterfaceName, String refName) {
+        this.serviceInterfaceName = serviceInterfaceName;
+        this.refName = refName;
+    }
+
+    public String getServiceInterfaceName() {
+        return serviceInterfaceName;
+    }
+
+    public String getRefName() {
+        return refName;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ServiceReference that = (ServiceReference) o;
+
+        if (!refName.equals(that.refName)) return false;
+        if (!serviceInterfaceName.equals(that.serviceInterfaceName)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = serviceInterfaceName.hashCode();
+        result = 31 * result + refName.hashCode();
+        return result;
+    }
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java
new file mode 100644 (file)
index 0000000..759541d
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.config.manager.impl.jmx;
+
+import javax.management.ObjectName;
+
+public interface ServiceReferenceMXBean {
+
+    ObjectName getCurrentImplementation();
+
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java
new file mode 100644 (file)
index 0000000..dedeeed
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.config.manager.impl.jmx;
+
+import javax.management.ObjectName;
+
+public class ServiceReferenceMXBeanImpl implements ServiceReferenceMXBean {
+    private ObjectName currentImplementation;
+
+    public ServiceReferenceMXBeanImpl(ObjectName currentImplementation) {
+        this.currentImplementation = currentImplementation;
+    }
+
+    @Override
+    public ObjectName getCurrentImplementation() {
+        return currentImplementation;
+    }
+
+    public void setCurrentImplementation(ObjectName currentImplementation) {
+        this.currentImplementation = currentImplementation;
+    }
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java
new file mode 100644 (file)
index 0000000..160ee18
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.config.manager.impl.jmx;
+
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator.InternalJMXRegistration;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+public interface ServiceReferenceRegistrator extends AutoCloseable {
+
+    public String getNullableTransactionName();
+
+    ServiceReferenceJMXRegistration registerMBean(ServiceReferenceMXBeanImpl object,
+                                                          ObjectName on) throws InstanceAlreadyExistsException;
+
+    @Override
+    void close();
+
+    public static class ServiceReferenceJMXRegistration implements AutoCloseable {
+        private final InternalJMXRegistration registration;
+
+        ServiceReferenceJMXRegistration(InternalJMXRegistration registration) {
+            this.registration = registration;
+        }
+
+        @Override
+        public void close() {
+            registration.close();
+        }
+    }
+
+    public static interface ServiceReferenceTransactionRegistratorFactory {
+        public ServiceReferenceRegistrator create();
+    }
+
+    public static class ServiceReferenceRegistratorImpl implements ServiceReferenceRegistrator {
+        private final InternalJMXRegistrator currentJMXRegistrator;
+        private final String nullableTransactionName;
+
+        public ServiceReferenceRegistratorImpl(NestableJMXRegistrator parentRegistrator, String nullableTransactionName){
+            currentJMXRegistrator = parentRegistrator.createChild();
+            this.nullableTransactionName = nullableTransactionName;
+        }
+
+        public String getNullableTransactionName() {
+            return nullableTransactionName;
+        }
+
+
+        public ServiceReferenceJMXRegistration registerMBean(ServiceReferenceMXBeanImpl object,
+                                                             ObjectName on) throws InstanceAlreadyExistsException {
+            String actualTransactionName = ObjectNameUtil.getTransactionName(on);
+            boolean broken = false;
+            broken |= (nullableTransactionName == null) != (actualTransactionName == null);
+            broken |= (nullableTransactionName != null) && nullableTransactionName.equals(actualTransactionName) == false;
+            if (broken) {
+                throw new IllegalArgumentException("Transaction name mismatch between expected "
+                        + nullableTransactionName + ", got " + actualTransactionName + " in " + on);
+            }
+            if (ObjectNameUtil.isServiceReference(on) == false) {
+                throw new IllegalArgumentException("Invalid type of " + on);
+            }
+            return new ServiceReferenceJMXRegistration(currentJMXRegistrator.registerMBean(object, on));
+        }
+
+
+        @Override
+        public void close() {
+            currentJMXRegistrator.close();
+        }
+        public static interface ServiceReferenceTransactionRegistratorFactory {
+            public ServiceReferenceRegistrator create();
+        }
+    }
+
+
+    public static class ServiceReferenceTransactionRegistratorFactoryImpl implements ServiceReferenceTransactionRegistratorFactory {
+        private final NestableJMXRegistrator parentRegistrator;
+        private final String nullableTransactionName;
+
+        public ServiceReferenceTransactionRegistratorFactoryImpl(TransactionModuleJMXRegistrator parentRegistrator,
+                                                             String nullableTransactionName) {
+            this.parentRegistrator = parentRegistrator;
+            this.nullableTransactionName = nullableTransactionName;
+        }
+
+        public ServiceReferenceTransactionRegistratorFactoryImpl(BaseJMXRegistrator baseJMXRegistrator) {
+            this.parentRegistrator = baseJMXRegistrator;
+            this.nullableTransactionName = null;
+        }
+
+        public ServiceReferenceRegistrator create() {
+            return new ServiceReferenceRegistratorImpl(parentRegistrator, nullableTransactionName);
+        }
+    }
+}
index 546adb0d8900996e60957a8882bcdd6c79a2eb5c..238fd2447e894149b51246e04692dbe1b19bfaa4 100644 (file)
@@ -17,14 +17,14 @@ import javax.management.QueryExp;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator.InternalJMXRegistration;
 
-public class TransactionModuleJMXRegistrator implements Closeable {
-    private final InternalJMXRegistrator childJMXRegistrator;
+public class TransactionModuleJMXRegistrator implements Closeable, NestableJMXRegistrator {
+    private final InternalJMXRegistrator currentJMXRegistrator;
     private final String transactionName;
 
     public TransactionModuleJMXRegistrator(
             InternalJMXRegistrator internalJMXRegistrator,
             String transactionName) {
-        this.childJMXRegistrator = internalJMXRegistrator.createChild();
+        this.currentJMXRegistrator = internalJMXRegistrator.createChild();
         this.transactionName = transactionName;
     }
 
@@ -44,21 +44,29 @@ public class TransactionModuleJMXRegistrator implements Closeable {
 
     public TransactionModuleJMXRegistration registerMBean(Object object,
             ObjectName on) throws InstanceAlreadyExistsException {
-        if (!transactionName.equals(ObjectNameUtil.getTransactionName(on)))
-            throw new IllegalArgumentException(
-                    "Transaction name mismatch between expected "
+        if (transactionName.equals(ObjectNameUtil.getTransactionName(on)) == false) {
+            throw new IllegalArgumentException("Transaction name mismatch between expected "
                             + transactionName + " " + "and " + on);
-        ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_MODULE);
+        }
+        ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_MODULE);
         return new TransactionModuleJMXRegistration(
-                childJMXRegistrator.registerMBean(object, on));
+                currentJMXRegistrator.registerMBean(object, on));
     }
 
     public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
-        return childJMXRegistrator.queryNames(name, query);
+        return currentJMXRegistrator.queryNames(name, query);
     }
 
     @Override
     public void close() {
-        childJMXRegistrator.close();
+        currentJMXRegistrator.close();
+    }
+
+    public String getTransactionName() {
+        return transactionName;
+    }
+
+    public InternalJMXRegistrator createChild() {
+        return currentJMXRegistrator.createChild();
     }
 }
index a7e3fa6c6fa29343f62bffb163fb35719aadae88..81b0921660539b822b4c0f3216b704f052500210 100644 (file)
@@ -7,13 +7,20 @@
  */
 package org.opendaylight.controller.config.manager.impl;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import junit.framework.Assert;
 import org.junit.After;
 import org.mockito.Matchers;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver;
 import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator;
+import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolImpl;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
@@ -24,14 +31,20 @@ import javax.management.InstanceAlreadyExistsException;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 import java.io.Closeable;
+import java.io.InputStream;
 import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
 /**
@@ -53,6 +66,10 @@ public abstract class AbstractConfigTest extends
     protected BundleContext mockedContext = mock(BundleContext.class);
     protected ServiceRegistration<?> mockedServiceRegistration;
 
+    protected  Map<Class, BundleContextServiceRegistrationHandler> getBundleContextServiceRegistrationHandlers() {
+        return Maps.newHashMap();
+    }
+
     // this method should be called in @Before
     protected void initConfigTransactionManagerImpl(
             ModuleFactoriesResolver resolver) {
@@ -61,17 +78,14 @@ public abstract class AbstractConfigTest extends
 
         configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(
                 platformMBeanServer);
-        this.mockedServiceRegistration = mock(ServiceRegistration.class);
-        doNothing().when(mockedServiceRegistration).unregister();
-        doReturn(mockedServiceRegistration).when(mockedContext).registerService(
-                Matchers.any(String[].class), any(Closeable.class),
-                any(Dictionary.class));
+        initBundleContext();
 
         internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
         baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
 
         configRegistry = new ConfigRegistryImpl(resolver,
                 platformMBeanServer, baseJmxRegistrator);
+
         try {
             configRegistryJMXRegistrator.registerToJMX(configRegistry);
         } catch (InstanceAlreadyExistsException e) {
@@ -80,10 +94,41 @@ public abstract class AbstractConfigTest extends
         configRegistryClient = new ConfigRegistryJMXClient(platformMBeanServer);
     }
 
+    private void initBundleContext() {
+        this.mockedServiceRegistration = mock(ServiceRegistration.class);
+        doNothing().when(mockedServiceRegistration).unregister();
+
+        RegisterServiceAnswer answer = new RegisterServiceAnswer();
+
+        doAnswer(answer).when(mockedContext).registerService(Matchers.any(String[].class),
+                any(Closeable.class), Matchers.<Dictionary<String, ?>>any());
+        doAnswer(answer).when(mockedContext).registerService(Matchers.<Class<Closeable>>any(), any(Closeable.class),
+                Matchers.<Dictionary<String, ?>>any());
+    }
+
+
+    public Collection<InputStream> getFilesAsInputStreams(List<String> paths) {
+        final Collection<InputStream> resources = new ArrayList<>();
+        List<String> failedToFind = new ArrayList<>();
+        for (String path : paths) {
+            InputStream resourceAsStream = getClass().getResourceAsStream(path);
+            if (resourceAsStream == null) {
+                failedToFind.add(path);
+            } else {
+                resources.add(resourceAsStream);
+            }
+        }
+        Assert.assertEquals("Some files were not found", Collections.<String>emptyList(), failedToFind);
+
+        return resources;
+    }
+
     @After
     public final void cleanUpConfigTransactionManagerImpl() {
         configRegistryJMXRegistrator.close();
         configRegistry.close();
+        TestingFixedThreadPool.cleanUp();
+        TestingScheduledThreadPoolImpl.cleanUp();
     }
 
     /**
@@ -111,10 +156,10 @@ public abstract class AbstractConfigTest extends
 
     protected void assertStatus(CommitStatus status, int expectedNewInstances,
             int expectedRecreatedInstances, int expectedReusedInstances) {
-        assertEquals(expectedNewInstances, status.getNewInstances().size());
-        assertEquals(expectedRecreatedInstances, status.getRecreatedInstances()
+        assertEquals("New instances mismatch in " + status, expectedNewInstances, status.getNewInstances().size());
+        assertEquals("Recreated instances mismatch in " + status, expectedRecreatedInstances, status.getRecreatedInstances()
                 .size());
-        assertEquals(expectedReusedInstances, status.getReusedInstances()
+        assertEquals("Reused instances mismatch in " + status, expectedReusedInstances, status.getReusedInstances()
                 .size());
     }
 
@@ -150,4 +195,35 @@ public abstract class AbstractConfigTest extends
             Class<? extends Module> configBeanClass, String implementationName) {
         return new ClassBasedModuleFactory(implementationName, configBeanClass);
     }
+
+
+    public static interface BundleContextServiceRegistrationHandler {
+
+       void handleServiceRegistration(Object serviceInstance);
+
+    }
+
+    private class RegisterServiceAnswer implements Answer {
+        @Override
+        public Object answer(InvocationOnMock invocation) throws Throwable {
+            Object[] args = invocation.getArguments();
+
+            Preconditions.checkArgument(args.length == 3);
+
+            Preconditions.checkArgument(args[0] instanceof Class);
+            Class<?> serviceType = (Class<?>) args[0];
+            Object serviceInstance = args[1];
+
+            BundleContextServiceRegistrationHandler serviceRegistrationHandler = getBundleContextServiceRegistrationHandlers()
+                    .get(serviceType);
+
+            Preconditions.checkArgument(serviceType.isAssignableFrom(serviceInstance.getClass()));
+
+            if (serviceRegistrationHandler != null) {
+                serviceRegistrationHandler.handleServiceRegistration(serviceType.cast(serviceInstance));
+            }
+
+            return mockedServiceRegistration;
+        }
+    }
 }
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java
new file mode 100644 (file)
index 0000000..6d0b340
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * 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.config.manager.impl;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBean;
+import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.parallelapsp.test.AbstractParallelAPSPTest;
+import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+import javax.management.Attribute;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.withoutTransactionName;
+
+public class ServiceReferenceRegistryImplTest extends AbstractParallelAPSPTest {
+
+
+    @Before
+    public void setUp() {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+                new TestingFixedThreadPoolModuleFactory(),
+                new TestingParallelAPSPModuleFactory(),
+                new TestingScheduledThreadPoolModuleFactory()));
+    }
+
+    @Override
+    protected String getThreadPoolImplementationName() {
+        return TestingFixedThreadPoolModuleFactory.NAME;
+    }
+
+    @Test
+    public void test() throws Exception {
+        ConfigTransactionJMXClient transaction1 = configRegistryClient.createTransaction();
+        // create fixed1
+        int fixedNrOfThreads = 20, scheduledNrOfThreads = 30;
+
+        ObjectName fixedTPTransactionON = transaction1.createModule(getThreadPoolImplementationName(), fixed1);
+        platformMBeanServer.setAttribute(fixedTPTransactionON, new Attribute("ThreadCount", fixedNrOfThreads));
+
+        ObjectName scheduledTPTransactionON = transaction1.createModule(
+                TestingScheduledThreadPoolModuleFactory.NAME, "scheduled1");
+        platformMBeanServer.setAttribute(scheduledTPTransactionON, new Attribute("ThreadCount",
+                scheduledNrOfThreads));
+
+        String refName = "ref";
+        ObjectName serviceReference = transaction1.saveServiceReference(TestingThreadPoolServiceInterface.QNAME, refName,
+                fixedTPTransactionON);
+        // create apsp-parallel
+        createParallelAPSP(transaction1, serviceReference);
+        transaction1.commit();
+        // check fixed1 is used
+        ServiceReferenceMXBean serviceReferenceMXBean = JMX.newMXBeanProxy(platformMBeanServer,
+                withoutTransactionName(serviceReference), ServiceReferenceMXBean.class);
+        assertEquals(withoutTransactionName(fixedTPTransactionON), serviceReferenceMXBean.getCurrentImplementation());
+        checkApspThreadCount(fixedNrOfThreads);
+
+        // switch reference to scheduled
+        ConfigTransactionJMXClient transaction2 = configRegistryClient.createTransaction();
+        transaction2.saveServiceReference(TestingThreadPoolServiceInterface.QNAME, refName,
+                ObjectNameUtil.withTransactionName(scheduledTPTransactionON, transaction2.getTransactionName()));
+        transaction2.commit();
+        // check scheduled is used
+        checkApspThreadCount(scheduledNrOfThreads);
+        // check that dummy MXBean points to scheduled
+        assertEquals(withoutTransactionName(scheduledTPTransactionON), serviceReferenceMXBean.getCurrentImplementation());
+
+        // empty transaction
+        configRegistryClient.createTransaction().commit();
+
+        // get service mapping
+        Map<String,Map<String,ObjectName>> serviceMapping = configRegistryClient.getServiceMapping();
+        Map<String,Map<String,ObjectName>> expectedMapping = ImmutableMap.of(TestingThreadPoolServiceInterface.QNAME,
+                (Map<String, ObjectName>)ImmutableMap.of(refName, withoutTransactionName(scheduledTPTransactionON)));
+        assertEquals(expectedMapping, serviceMapping);
+
+        // destroy all
+        ConfigTransactionJMXClient transaction4 = configRegistryClient.createTransaction();
+        Set<ObjectName> objectNames = transaction4.lookupConfigBeans();
+        for(ObjectName on: objectNames) {
+            transaction4.destroyModule(on);
+        }
+        transaction4.commit();
+
+        serviceMapping = configRegistryClient.getServiceMapping();
+        assertTrue(serviceMapping.isEmpty());
+    }
+
+    private void checkApspThreadCount(int fixedNrOfThreads) throws MBeanException, AttributeNotFoundException,
+            InstanceNotFoundException, ReflectionException {
+        ObjectName apspON = ObjectNameUtil.createReadOnlyModuleON(TestingParallelAPSPModuleFactory.NAME, apsp1);
+        assertEquals(fixedNrOfThreads, platformMBeanServer.getAttribute(apspON, "MaxNumberOfThreads"));
+    }
+}
index 65b010532bfe342dd7db6b155ca8190d61e7b5b9..31e70bd84e66dee4bb1aa8b238d6551ac04c705e 100644 (file)
@@ -20,6 +20,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
@@ -40,7 +41,8 @@ public class DependencyResolverManagerTest {
     @Before
     public void setUp() {
         transactionStatus = mock(TransactionStatus.class);
-        tested = new DependencyResolverManager("txName", transactionStatus);
+        ServiceReferenceReadableRegistry mockedRegistry = mock(ServiceReferenceReadableRegistry.class);
+        tested = new DependencyResolverManager("txName", transactionStatus, mockedRegistry);
         doNothing().when(transactionStatus).checkCommitStarted();
         doNothing().when(transactionStatus).checkNotCommitted();
     }
index 03380392e89c658e276c9af2f65ebbec1529a262..fe322895ab64fd15923680635c77fe765aa651af 100644 (file)
@@ -7,16 +7,19 @@
  */
 package org.opendaylight.controller.config.manager.impl.util;
 
-import java.util.Set;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Throwables;
+import com.google.common.collect.Sets;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
 
-import com.google.common.base.Throwables;
-import com.google.common.collect.Sets;
+import javax.management.ObjectName;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 
 public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
     private Set<ObjectName> unregisterONs;
@@ -37,7 +40,26 @@ public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
             }
         }
         if (lastException != null) {
-            Throwables.propagate(lastException);
+            throw Throwables.propagate(lastException);
         }
     }
+
+    @Test
+    public void testQuotation() throws Exception {
+        String serviceQName = "(namespace?revision=r)qname";
+        String refName = "refName";
+        String transaction = "transaction";
+        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
+
+        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
+
+    }
 }
index 3c55f4dcc05ffaead37a614904de3eed284de874..f4ba5ef887e359b9e5a6ab324ac58cc359ae565f 100644 (file)
@@ -114,8 +114,7 @@ public class TestingParallelAPSPModule implements Module,
 
             if (oldInstance != null) {
                 // changing thread pool is not supported
-                boolean reuse = threadPoolInstance.equals(oldInstance
-                        .getThreadPool());
+                boolean reuse = threadPoolInstance == oldInstance.getThreadPool();
                 if (reuse) {
                     logger.debug("Reusing old instance");
                     instance = oldInstance;
index 3d9d5245ef2886be3eaa937312c247541e50557e..f979a45dd15c8dffcc8297c80502a5287b77a991 100644 (file)
@@ -16,11 +16,11 @@ import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.ObjectName;
 
-abstract class AbstractParallelAPSPTest extends AbstractConfigTest {
+public abstract class AbstractParallelAPSPTest extends AbstractConfigTest {
     protected final String fixed1 = "fixed1";
     protected final String apsp1 = "apsp-parallel";
 
-    abstract String getThreadPoolImplementationName();
+    protected abstract String getThreadPoolImplementationName();
 
     protected ObjectName createParallelAPSP(
             ConfigTransactionJMXClient transaction, ObjectName threadPoolON)
@@ -36,6 +36,7 @@ abstract class AbstractParallelAPSPTest extends AbstractConfigTest {
 
     protected ObjectName createFixed1(ConfigTransactionJMXClient transaction,
             int numberOfThreads) throws InstanceAlreadyExistsException {
+
         ObjectName name = transaction.createModule(
                 getThreadPoolImplementationName(), fixed1);
 
index f9a11301e1aaf09b98d8af43bd965f1f8902e153..978d375cd24df6aff7cb508d4087c9cc1580b696 100644 (file)
@@ -48,7 +48,7 @@ public class DependentWiringTest extends AbstractParallelAPSPTest {
     }
 
     @Override
-    String getThreadPoolImplementationName() {
+    protected String getThreadPoolImplementationName() {
         return TestingFixedThreadPoolModuleFactory.NAME;
     }
 
index e385136abfbc1de0809a8eca94d9af77a5d35efc..642f526efd703730e7c19931496cfb803d0e91cb 100644 (file)
@@ -111,7 +111,7 @@ public class MockedDependenciesTest extends AbstractParallelAPSPTest {
     }
 
     @Override
-    String getThreadPoolImplementationName() {
+    protected String getThreadPoolImplementationName() {
         return threadPoolImplementationName;
     }
 
index 77d1f8bbdfedfca2402b9c310d54cf1413f94340..2b9760cfc4e922fe8663bfd653bc285fc3c1bc4b 100644 (file)
@@ -36,7 +36,7 @@ public class TestingScheduledThreadPoolModule implements Module,
     @Nullable
     private final TestingScheduledThreadPoolImpl oldInstance;
 
-    private final int threadCount = 10;
+    private int threadCount = 10;
     private TestingScheduledThreadPoolImpl instance;
     private RootRuntimeBeanRegistrator runtimeBeanRegistrator;
     private boolean recreate;
@@ -68,6 +68,11 @@ public class TestingScheduledThreadPoolModule implements Module,
         return threadCount;
     }
 
+    @Override
+    public void setThreadCount(int threadCount) {
+        this.threadCount = threadCount;
+    }
+
     @Override
     public Closeable getInstance() {
         assertNotNull(runtimeBeanRegistrator);
index 91a4cff415ac3200366deee7c4324a9755423a89..0a886e5fb0490a663df6429a045d9d23fb2690f0 100644 (file)
@@ -11,8 +11,9 @@ import org.opendaylight.controller.config.api.annotations.AbstractServiceInterfa
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc;
 
-@ServiceInterfaceAnnotation(value = "testing-threadpool", osgiRegistrationType = TestingThreadPoolIfc.class,
-    namespace = "ns", revision = "foo", localName = "bar")
+@ServiceInterfaceAnnotation(value = TestingThreadPoolServiceInterface.QNAME, osgiRegistrationType = TestingThreadPoolIfc.class,
+    namespace = "ns", revision = "foo", localName = "testing-threadpool")
 public interface TestingThreadPoolServiceInterface extends
         AbstractServiceInterface {
+    public static final String QNAME = "(ns?revision=foo)testing-threadpool";
 }
index 8badb75f05c26f0082f00b627eedd91836bd28d5..549ff9ffcfdb9254a4115349d1cbd65520875809 100644 (file)
@@ -148,8 +148,8 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return configRegistryMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return configRegistryMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -158,8 +158,8 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -201,4 +201,15 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     public Set<String> getAvailableModuleFactoryQNames() {
         return configRegistryMXBeanProxy.getAvailableModuleFactoryQNames();
     }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        return configRegistryMXBeanProxy.getServiceReference(serviceInterfaceQName, refName);
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        configRegistryMXBeanProxy.checkServiceReferenceExists(objectName);
+    }
+
 }
index 0db1e5b8224761bc8dbb091f22c1513cf6d5216a..e683d915baea604db86b891e81dc9192b203c4aa 100644 (file)
@@ -164,13 +164,13 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
-    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
-        configTransactionControllerMXBeanProxy.saveServiceReference(serviceInterfaceName,refName,objectName);
+    public ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
+        return configTransactionControllerMXBeanProxy.saveServiceReference(serviceInterfaceName,refName, moduleON);
     }
 
     @Override
-    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
-        return configTransactionControllerMXBeanProxy.removeServiceReference(serviceInterfaceName, refName);
+    public void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException{
+        configTransactionControllerMXBeanProxy.removeServiceReference(serviceInterfaceName, refName);
     }
 
     @Override
@@ -179,8 +179,8 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return configTransactionControllerMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return configTransactionControllerMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -189,8 +189,8 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return configTransactionControllerMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return configTransactionControllerMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -208,6 +208,16 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
         return configTransactionControllerMXBeanProxy.removeServiceReferences(objectName);
     }
 
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        return configTransactionControllerMXBeanProxy.getServiceReference(serviceInterfaceQName, refName);
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        configTransactionControllerMXBeanProxy.checkServiceReferenceExists(objectName);
+    }
+
     @Override
     public void validateBean(ObjectName configBeanON)
             throws ValidationException {
index 65341714df22e7e13315fbcbd6ca44120bf74664..e0d4c8594375c58739a46c1c27760c1a1c9860a1 100644 (file)
@@ -150,7 +150,7 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean {
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
         throw new UnsupportedOperationException();
     }
 
@@ -160,7 +160,7 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean {
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
         throw new UnsupportedOperationException();
     }
 
@@ -178,4 +178,14 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean {
     public Set<String> getAvailableModuleFactoryQNames() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
 }
index 44eb73af79e9c098b343ec7a4debb995e6e44337..4d16f51ae5e8e3068a32a0315dadc82ee16c6f42 100644 (file)
@@ -117,12 +117,12 @@ public class TestingConfigTransactionController implements
     }
 
     @Override
-    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
+    public ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
+    public void removeServiceReference(String serviceInterfaceName, String refName) {
         throw new UnsupportedOperationException();
     }
 
@@ -132,7 +132,7 @@ public class TestingConfigTransactionController implements
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
         throw new UnsupportedOperationException();
     }
 
@@ -142,7 +142,7 @@ public class TestingConfigTransactionController implements
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
         throw new UnsupportedOperationException();
     }
 
@@ -165,4 +165,14 @@ public class TestingConfigTransactionController implements
     public Set<String> getAvailableModuleFactoryQNames() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
 }
index 28e0256c05b0cbd055636aa8cf391be97fba6d21..49a20bd46250da8e2bbe83bc767af1dd75398260 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIf
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.Dependency;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TypedAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribute;
@@ -623,6 +624,7 @@ public class TemplateFactory {
                 }
 
                 boolean isDependency = false;
+                boolean isListOfDependencies = false;
                 Dependency dependency = null;
                 Annotation overrideAnnotation = new Annotation("Override",
                         Collections.<Parameter> emptyList());
@@ -635,12 +637,15 @@ public class TemplateFactory {
                             .getDependency();
                     annotations.add(Annotation
                             .createRequireIfcAnnotation(dependency.getSie()));
+                    if (attributeIfc instanceof ListDependenciesAttribute) {
+                        isListOfDependencies = true;
+                    }
                 }
 
                 String varName = BindingGeneratorUtil
                         .parseToValidParamName(attrEntry.getKey());
                 moduleFields.add(new ModuleField(type, varName, attributeIfc
-                        .getUpperCaseCammelCase(), nullableDefaultWrapped, isDependency, dependency));
+                        .getUpperCaseCammelCase(), nullableDefaultWrapped, isDependency, dependency, isListOfDependencies));
 
                 String getterName = "get"
                         + attributeIfc.getUpperCaseCammelCase();
@@ -657,10 +662,16 @@ public class TemplateFactory {
                             .createDescriptionAnnotation(attributeIfc.getNullableDescription()));
                 }
 
+                String setterBody = "this." + varName + " = " + varName + ";";
+                if (isListOfDependencies) {
+                    String nullCheck = String.format("if (%s == null) throw new IllegalArgumentException(\"Null not supported\");%n",
+                            varName);
+                    setterBody = nullCheck + setterBody;
+                }
                 MethodDefinition setter = new MethodDefinition("void",
                         setterName,
                         Lists.newArrayList(new Field(type, varName)),
-                        annotations, "this." + varName + " = " + varName + ";");
+                        annotations, setterBody);
                 setter.setJavadoc(attributeIfc.getNullableDescription());
 
                 methods.add(getter);
index 5624e169da81d0f69dc2bca15f7dce1de71fab6a..aff7af2811f061ba762d4789e088b4fb3c0c41f1 100644 (file)
@@ -17,12 +17,12 @@ import java.util.List;
 public class ModuleField extends Field {
 
     private final String nullableDefault, attributeName;
-    private final boolean dependent;
+    private final boolean dependent, isListOfDependencies;
     private final Dependency dependency;
 
-    public ModuleField(List<String> modifiers, String type, String name,
+    private ModuleField(List<String> modifiers, String type, String name,
             String attributeName, String nullableDefault, boolean isDependency,
-            Dependency dependency) {
+            Dependency dependency, boolean isListOfDependencies) {
         super(modifiers, type, name);
         this.dependent = isDependency;
         this.dependency = dependency;
@@ -32,12 +32,13 @@ public class ModuleField extends Field {
             nullableDefault = "new " + ArrayList.class.getName() + generics + "()";
         }
         this.nullableDefault = nullableDefault;
+        this.isListOfDependencies = isListOfDependencies;
     }
 
     public ModuleField(String type, String name, String attributeName,
-            String nullableDefault, boolean isDependency, Dependency dependency) {
+            String nullableDefault, boolean isDependency, Dependency dependency, boolean isListOfDependencies) {
         this(Collections.<String> emptyList(), type, name, attributeName,
-                nullableDefault, isDependency, dependency);
+                nullableDefault, isDependency, dependency, isListOfDependencies);
     }
 
     public Dependency getDependency() {
@@ -52,6 +53,10 @@ public class ModuleField extends Field {
         return dependent;
     }
 
+    public boolean isListOfDependencies() {
+        return isListOfDependencies;
+    }
+
     public String getAttributeName() {
         return attributeName;
     }
index f7197d1582ca70193cb21591922f8c77529a31ed..7192ac661f8a6a362c84fec6f52c66ac6b5747ac 100644 (file)
@@ -149,13 +149,19 @@ package ${packageName};
             throw new IllegalArgumentException("Parameter 'other' is null");
         }
         <#list moduleFields as field>
-        <#if field.dependent==true>
-        if (${field.name}Dependency == null) {
-            if (other.${field.name}Dependency != null)
-                return false;
-        } else if (!${field.name}Dependency.equals(other.${field.name}Dependency)) {
+        <#if field.dependent==true && field.listOfDependencies == false>
+        if (${field.name}Dependency != other.${field.name}Dependency) { // reference to dependency must be same
+            return false;
+        }
+        <#elseif field.listOfDependencies>
+        if (${field.name}Dependency.equals(other.${field.name}Dependency) == false) {
             return false;
         }
+        for (int idx = 0; idx < ${field.name}Dependency.size(); idx++) {
+            if (${field.name}Dependency.get(idx) != other.${field.name}Dependency.get(idx)) {
+                return false;
+            }
+        }
         <#else>
         if (${field.name} == null) {
             if (other.${field.name} != null) {
index b49b17e3a00d372e46597e95d41278b4a9e5c1de..e33f1cddc43c2ffc6bf48491dcc6612ae9e3078d 100644 (file)
@@ -42,7 +42,7 @@ public class JMXGeneratorFileNamesValidationTest extends JMXGeneratorTest {
         } catch (RuntimeException e) {
             final Throwable cause = e.getCause();
             assertNotNull(cause);
-            assertTrue(cause instanceof IllegalStateException);
+            assertTrue(cause.toString() + " is unexpected", cause instanceof IllegalStateException);
             assertThat(cause.getMessage(),
                     containsString("Name conflict in generated files"));
             assertThat(cause.getMessage(), containsString("DtoA.java"));
index 211da6bfefdc62df10906eff27b30655e90eb790..2be6c81ee75ae0438e4114711f590f4d670d0b9b 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.controller.config.yang.store.impl;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
 import org.apache.commons.io.IOUtils;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
@@ -22,13 +21,10 @@ 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.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -37,26 +33,11 @@ public class MbeParser {
     public YangStoreSnapshotImpl parseYangFiles(
             Collection<? extends InputStream> allInput)
             throws YangStoreException {
-        YangParserImpl parser = new YangParserImpl();
+        YangParserImpl parser = YangParserWrapper.getYangParserInstance();
 
-        List<InputStream> bufferedInputStreams = new ArrayList<>();
-        for (InputStream is : allInput) {
-            String content;
-            try {
-                content = IOUtils.toString(is);
-            } catch (IOException e) {
-                throw new YangStoreException("Can not get yang as String from "
-                        + is, e);
-            }
-            InputStream buf = new ByteArrayInputStream(content.getBytes());
-            bufferedInputStreams.add(buf);
-        }
-
-        Map<InputStream, Module> allYangModules = parser
-                .parseYangModelsFromStreamsMapped(bufferedInputStreams);
+        Map<InputStream, Module> allYangModules = YangParserWrapper.parseYangFiles(parser, allInput);
 
-        SchemaContext resolveSchemaContext = parser.resolveSchemaContext(Sets
-                .newHashSet(allYangModules.values()));
+        SchemaContext resolveSchemaContext = YangParserWrapper.getSchemaContextFromModules(parser, allYangModules);
 
         // JMX generator
 
@@ -115,7 +96,7 @@ public class MbeParser {
 
     public Map<Module, String> parseYangFilesToString(
             Collection<? extends InputStream> allYangs) {
-        YangParserImpl parser = new YangParserImpl();
+        YangParserImpl parser = YangParserWrapper.getYangParserInstance();
 
         Map<InputStream, Module> allYangModules = parser
                 .parseYangModelsFromStreamsMapped(Lists.newArrayList(allYangs));
diff --git a/opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangParserWrapper.java b/opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangParserWrapper.java
new file mode 100644 (file)
index 0000000..7c42818
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.config.yang.store.impl;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.io.IOUtils;
+import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+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.parser.impl.YangParserImpl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public class YangParserWrapper {
+
+    /**
+     * throw IllegalStateException if it is unable to parse yang files
+     */
+    public static SchemaContext parseYangFiles(Collection<? extends InputStream> yangFilesAsInputStreams) {
+        YangParserImpl parser = getYangParserInstance();
+        Map<InputStream, Module> mappedYangModules = null;
+        try {
+            mappedYangModules = parseYangFiles(parser, yangFilesAsInputStreams);
+        } catch (YangStoreException e) {
+            throw new IllegalStateException("Unable to parse yang files", e);
+        }
+        return getSchemaContextFromModules(parser, mappedYangModules);
+    }
+
+    static YangParserImpl getYangParserInstance() {
+        return new YangParserImpl();
+    }
+
+    static SchemaContext getSchemaContextFromModules(YangModelParser parser, Map<InputStream, Module> allYangModules) {
+        return parser.resolveSchemaContext(Sets
+                .newHashSet(allYangModules.values()));
+    }
+
+    static Map<InputStream, Module> parseYangFiles(YangModelParser parser, Collection<? extends InputStream> allInput) throws YangStoreException {
+        List<InputStream> bufferedInputStreams = new ArrayList<>();
+        for (InputStream is : allInput) {
+            String content;
+            try {
+                content = IOUtils.toString(is);
+            } catch (IOException e) {
+                throw new YangStoreException("Can not get yang as String from "
+                        + is, e);
+            }
+            InputStream buf = new ByteArrayInputStream(content.getBytes());
+            bufferedInputStreams.add(buf);
+        }
+
+        return parser
+                .parseYangModelsFromStreamsMapped(bufferedInputStreams);
+    }
+}
index 149348df4b2234e7c54c49f59fd7f7118e9d0c91..b1f7013abef241620ff02d393751133270e78bcb 100644 (file)
             <artifactId>slf4j-api</artifactId>
         </dependency>
         <dependency>
-         <groupId>org.opendaylight.yangtools.model</groupId>
-         <artifactId>ietf-inet-types</artifactId>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.bgpcep</groupId>
+            <artifactId>mockito-configuration</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-manager</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-manager</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-util</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 
diff --git a/opendaylight/config/yang-test/src/test/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java b/opendaylight/config/yang-test/src/test/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java
new file mode 100644 (file)
index 0000000..50e1d4b
--- /dev/null
@@ -0,0 +1,89 @@
+package org.opendaylight.controller.config.yang.test.impl;
+
+import com.google.common.collect.Lists;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.List;
+
+public class NetconfTestImplModuleTest  extends AbstractConfigTest {
+
+    public static final String TESTING_DEP_PREFIX = "testing-dep";
+    private NetconfTestImplModuleFactory factory;
+    private final String instanceName = "n1";
+
+    @Before
+    public void setUp() {
+
+        factory = new NetconfTestImplModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+                new DepTestImplModuleFactory()));
+    }
+
+    @Test
+    public void testDependencyList() throws InstanceAlreadyExistsException, ValidationException,
+            ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        ObjectName on = createInstance(transaction, instanceName, 4);
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertBeanCount(4 + 1, DepTestImplModuleFactory.NAME);
+        assertStatus(status, 1 + 4 + 1, 0, 0);
+
+        transaction = configRegistryClient.createTransaction();
+
+        NetconfTestImplModuleMXBean proxy = transaction.newMXBeanProxy(ObjectNameUtil.withoutTransactionName(on),
+                NetconfTestImplModuleMXBean.class);
+        proxy.getComplexList();
+        List<ObjectName> testingDeps = proxy.getTestingDeps();
+        ObjectName testingDep = proxy.getTestingDep();
+
+        Assert.assertEquals(TESTING_DEP_PREFIX, ObjectNameUtil.getInstanceName(testingDep));
+        assertTestingDeps(testingDeps, 4);
+
+        transaction.abortConfig();
+    }
+
+    private void assertTestingDeps(List<ObjectName> testingDeps, int i) {
+        Assert.assertEquals(i, testingDeps.size());
+
+        int c = 1;
+        for (ObjectName testingDep : testingDeps) {
+            Assert.assertEquals(TESTING_DEP_PREFIX + Integer.toString(c++), ObjectNameUtil.getInstanceName(testingDep));
+        }
+    }
+
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, int depsCount)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        NetconfTestImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, NetconfTestImplModuleMXBean.class);
+
+        ObjectName dep = transaction.createModule(DepTestImplModuleFactory.NAME, TESTING_DEP_PREFIX);
+        mxBean.setTestingDep(dep);
+
+        ArrayList<ObjectName> testingDeps = Lists.newArrayList();
+        for (int i = 0; i < depsCount; i++) {
+            dep = transaction.createModule(DepTestImplModuleFactory.NAME, TESTING_DEP_PREFIX + Integer.toString(i + 1));
+            testingDeps.add(dep);
+        }
+        mxBean.setTestingDeps(testingDeps);
+
+        return nameCreated;
+    }
+
+}
index e519a04a57ccebfa3ee935c8c549a2f7a96491d7..b0f7ad89a4b81694c889c52e51f5cc00947c8c4f 100644 (file)
           <artifactId>ietf-netconf-monitoring</artifactId>
           <version>${netconf.version}</version>
         </dependency>
+        <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>ietf-netconf-monitoring-extension</artifactId>
+          <version>${netconf.version}</version>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-persister-impl</artifactId>
         <dependency>
               <groupId>org.opendaylight.controller</groupId>
               <artifactId>
-                  zeromq-routingtable.implementation
+                  remoterpc-routingtable.implementation
               </artifactId>
               <version>0.4.1-SNAPSHOT</version>
         </dependency>
index 2815422274fad3c61cfa95ba724969eadf30d001..84d1c913c413ef5e1978aded60ff85c200437169 100644 (file)
@@ -61,7 +61,7 @@
   <logger name="org.opendaylight.controller.sal.implementation" level="INFO"/>
   <logger name="org.opendaylight.controller.sal.implementation.internal.Inventory" level="INFO"/>
   <logger name="org.opendaylight.controller.sal.implementation.internal.Topology" level="INFO"/>
-     <!-- zeromq router and zeromq routing table -->
+     <!-- remoterpc router and remoterpc routing table -->
   <logger name="org.opendaylight.controller.sal.connector.remoterpc" level="INFO" />
   <!-- Functional Modules -->
   <logger name="org.opendaylight.controller.arphandler" level="INFO"/>
index 45fb11a83eda110b96b1588dd43b0c8fd6c7b164..3d6a0292ef67225079b11759a3560bdfddf85377 100644 (file)
@@ -2930,8 +2930,16 @@ public class ForwardingRulesManager implements
         }
         if (target != null) {
             // Update Configuration database
-            target.toggleInstallation();
-            target.setStatus(StatusCode.SUCCESS.toString());
+            if (target.getHardTimeout() != null || target.getIdleTimeout() != null) {
+                /*
+                 * No need for checking if actual values: these strings were
+                 * validated at configuration creation. Also, after a switch
+                 * down scenario, no use to reinstall a timed flow. Mark it as
+                 * "do not install". User can manually toggle it.
+                 */
+                target.toggleInstallation();
+            }
+            target.setStatus(StatusCode.GONE.toString());
             staticFlows.put(key, target);
         }
 
index b460edff7438f24e649d2178c55b4cfc89a354a7..95acbcdb1338e10827d76c4d5d19718094db83d0 100644 (file)
@@ -8,7 +8,6 @@ import static org.opendaylight.controller.sal.compatibility.NodeMapping.*
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
 import org.apache.felix.dm.Component
 import java.util.Arrays
-import org.opendaylight.yangtools.yang.binding.NotificationListener
 import java.util.Dictionary
 import java.util.Hashtable
 import org.opendaylight.controller.sal.utils.GlobalConstants
@@ -30,6 +29,9 @@ import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService
 import org.opendaylight.controller.sal.discovery.IDiscoveryService
 import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
 
 class ComponentActivator extends ComponentActivatorAbstractBase implements BindingAwareConsumer {
 
@@ -44,9 +46,16 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi
     @Property
     DataPacketAdapter dataPacket = new DataPacketAdapter;
 
+    @Property
+    org.opendaylight.controller.sal.utils.INodeFactory nodeFactory = new MDSalNodeFactory
+
+    @Property
+    org.opendaylight.controller.sal.utils.INodeConnectorFactory nodeConnectorFactory = new MDSalNodeConnectorFactory
+
+
     override protected init() {
-        Node.NodeIDType.registerIDType(MD_SAL_TYPE, NodeKey);
-        NodeConnector.NodeConnectorIDType.registerIDType(MD_SAL_TYPE, NodeConnectorKey, MD_SAL_TYPE);
+        Node.NodeIDType.registerIDType(MD_SAL_TYPE, String);
+        NodeConnector.NodeConnectorIDType.registerIDType(MD_SAL_TYPE, String, MD_SAL_TYPE);
     }
 
     override start(BundleContext context) {
@@ -71,25 +80,38 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi
         // Inventory Service
         inventory.dataService = session.getSALService(DataBrokerService);
         inventory.flowStatisticsService = session.getRpcService(OpendaylightFlowStatisticsService);
+        inventory.flowTableStatisticsService = session.getRpcService(OpendaylightFlowTableStatisticsService);
+        inventory.nodeConnectorStatisticsService = session.getRpcService(OpendaylightPortStatisticsService);
         inventory.topologyDiscovery = session.getRpcService(FlowTopologyDiscoveryService);
+               inventory.dataProviderService = session.getSALService(DataProviderService)
 
         subscribe.registerNotificationListener(dataPacket)
 
     }
 
     override protected getGlobalImplementations() {
-        return Arrays.asList(this, flow, inventory, dataPacket)
+        return Arrays.asList(this, flow, inventory, dataPacket, nodeFactory, nodeConnectorFactory)
     }
 
     override protected configureGlobalInstance(Component c, Object imp) {
         configure(imp, c);
     }
 
+    private def dispatch configure(MDSalNodeFactory imp, Component it) {
+        setInterface(org.opendaylight.controller.sal.utils.INodeFactory.name, properties);
+    }
+
+    private def dispatch configure(MDSalNodeConnectorFactory imp, Component it) {
+        setInterface(org.opendaylight.controller.sal.utils.INodeConnectorFactory.name, properties);
+    }
+
     private def dispatch configure(ComponentActivator imp, Component it) {
         add(
             createServiceDependency().setService(BindingAwareBroker) //
             .setCallbacks("setBroker", "setBroker") //
             .setRequired(true))
+
+
     }
 
     private def dispatch configure(DataPacketAdapter imp, Component it) {
@@ -114,7 +136,7 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi
         add(
             createServiceDependency() //
             .setService(IPluginOutReadService) //
-            .setCallbacks("setReadPublisher", "setReadPublisher") //
+            .setCallbacks("setReadPublisher", "unsetReadPublisher") //
             .setRequired(false))
         add(
             createServiceDependency() //
@@ -137,6 +159,7 @@ class ComponentActivator extends ComponentActivatorAbstractBase implements Bindi
     private def Dictionary<String, Object> properties() {
         val props = new Hashtable<String, Object>();
         props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString, MD_SAL_TYPE)
+        props.put("protocolName", MD_SAL_TYPE);
         return props;
     }
 }
index ce6af6469ef1a55f04b679ef367a6dd797b8359c..f1c19b127f86ccf2d61ec6f179aaab3911962617 100644 (file)
@@ -15,8 +15,9 @@ class DataPacketAdapter implements PacketProcessingListener {
         dataPacketPublisher.receiveDataPacket(inPacket);
     }
 
-    public static def RawPacket toRawPacket(PacketReceived received) {
+    public static def RawPacket toRawPacket(PacketReceived received) {        
         val ret = new RawPacket(received.payload);
+        ret.setIncomingNodeConnector(NodeMapping.toADNodeConnector(received.ingress))
         return ret;
     }
 
index ad6009c827a365ff40ebdce31cb1c87e92efb7f8..4e6e49eac70cefd3576754d542e159c649fa457b 100644 (file)
@@ -1,5 +1,9 @@
 package org.opendaylight.controller.sal.compatibility;
 
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
 import static org.opendaylight.controller.sal.match.MatchType.DL_DST;
 import static org.opendaylight.controller.sal.match.MatchType.DL_SRC;
 import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE;
@@ -8,11 +12,6 @@ import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
 
-
-import org.opendaylight.controller.sal.core.NodeConnector;
-
-
-
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchField;
 import org.opendaylight.controller.sal.match.MatchType;
@@ -22,14 +21,11 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-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.l2.types.rev130827.EtherType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
@@ -53,9 +49,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 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.match.layer._4.match.UdpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+
 import com.google.common.net.InetAddresses;
-import static org.opendaylight.controller.sal.compatibility.NodeMapping.*;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.*;
 
 public class FromSalConversionsUtils {
 
@@ -63,19 +58,7 @@ public class FromSalConversionsUtils {
 
     }
 
-    public static GetNodeConnectorStatisticsInput nodeConnectorStatistics(
-            NodeConnector connector) {
-        GetNodeConnectorStatisticsInputBuilder target = new GetNodeConnectorStatisticsInputBuilder();
-
-        NodeRef nodeRef = toNodeRef(connector.getNode());
-        target.setNode(nodeRef);
-
-        NodeConnectorRef nodeConnectorRef = toNodeConnectorRef(connector);
-        target.setNodeConnector(nodeConnectorRef);
-
-        return target.build();
-    }
-
+    @SuppressWarnings("unused")
     private static Address addressFromAction(InetAddress inetAddress) {
         String strInetAddresss = InetAddresses.toAddrString(inetAddress);
         if (inetAddress instanceof Inet4Address) {
@@ -196,7 +179,7 @@ public class FromSalConversionsUtils {
         MatchField vlan = sourceMatch.getField(MatchType.DL_VLAN);
         if (vlan != null && vlan.getValue() != null) {
             VlanIdBuilder vlanIDBuilder = new VlanIdBuilder();
-            vlanIDBuilder.setVlanId(new VlanId((int) (NetUtils
+            vlanIDBuilder.setVlanId(new VlanId((NetUtils
                     .getUnsignedShort((short) vlan.getValue()))));
             vlanMatchBuild.setVlanId(vlanIDBuilder.build());
         }
@@ -270,7 +253,7 @@ public class FromSalConversionsUtils {
 
         InetAddress inetDestAddress = null;
         MatchField netDest = sourceMatch.getField(MatchType.NW_DST);
-        if (netSource != null && netSource.getValue() != null) {
+        if (netDest != null && netDest.getValue() != null) {
             inetDestAddress = (InetAddress) (netDest.getValue());
         }
 
@@ -371,5 +354,76 @@ public class FromSalConversionsUtils {
                 .setIpv6Destination(new Ipv6Prefix(inetDstAddressString));
         return layer6MatchBuild.build();
     }
+    
+    public static boolean flowEquals(Flow statsFlow, Flow storedFlow) {
+        if (statsFlow.getClass() != storedFlow.getClass()) {
+            return false;
+        }
+        if (statsFlow.getBufferId()== null) {
+            if (storedFlow.getBufferId() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getBufferId().equals(storedFlow.getBufferId())) {
+            return false;
+        }
+        if (statsFlow.getContainerName()== null) {
+            if (storedFlow.getContainerName()!= null) {
+                return false;
+            }
+        } else if(!statsFlow.getContainerName().equals(storedFlow.getContainerName())) {
+            return false;
+        }
+        if (statsFlow.getCookie()== null) {
+            if (storedFlow.getCookie()!= null) {
+                return false;
+            }
+        } else if(!statsFlow.getCookie().equals(storedFlow.getCookie())) {
+            return false;
+        }
+        if (statsFlow.getMatch()== null) {
+            if (storedFlow.getMatch() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getMatch().equals(storedFlow.getMatch())) {
+            return false;
+        }
+        if (statsFlow.getCookie()== null) {
+            if (storedFlow.getCookie()!= null) {
+                return false;
+            }
+        } else if(!statsFlow.getCookie().equals(storedFlow.getCookie())) {
+            return false;
+        }
+        if (statsFlow.getHardTimeout() == null) {
+            if (storedFlow.getHardTimeout() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getHardTimeout().equals(storedFlow.getHardTimeout() )) {
+            return false;
+        }
+        if (statsFlow.getIdleTimeout()== null) {
+            if (storedFlow.getIdleTimeout() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getIdleTimeout().equals(storedFlow.getIdleTimeout())) {
+            return false;
+        }
+        if (statsFlow.getPriority() == null) {
+            if (storedFlow.getPriority() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getPriority().equals(storedFlow.getPriority())) {
+            return false;
+        }
+        if (statsFlow.getTableId() == null) {
+            if (storedFlow.getTableId() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getTableId().equals(storedFlow.getTableId())) {
+            return false;
+        }
+        return true;
+    }
+
 
 }
index 8ac6f1b0500d1834fa6883de70a7ae3c6eb601bb..31ae745d73054ed0c046d94c05c8f38ba26f786f 100644 (file)
@@ -9,7 +9,6 @@ import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
 
 import static extension org.opendaylight.controller.sal.common.util.Arguments.*
 import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
@@ -19,9 +18,7 @@ import org.opendaylight.controller.sal.reader.NodeConnectorStatistics
 import org.opendaylight.controller.sal.reader.FlowOnNode
 import org.opendaylight.controller.sal.reader.NodeDescription
 import org.slf4j.LoggerFactory
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsInputBuilder
 import java.util.ArrayList
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsInputBuilder
 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService
@@ -45,17 +42,64 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkUtilizationNormal
 import org.opendaylight.controller.sal.topology.TopoEdgeUpdate
 import org.opendaylight.controller.sal.discovery.IDiscoveryService
-
-class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInReadService, IPluginInInventoryService, OpendaylightInventoryListener, FlowTopologyDiscoveryListener {
+import org.opendaylight.controller.sal.reader.IPluginOutReadService
+import java.util.List
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate
+import org.opendaylight.controller.sal.reader.NodeTableStatistics
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatistics
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder
+
+class InventoryAndReadAdapter implements IPluginInTopologyService,
+                                                                                        IPluginInReadService,
+                                                                                        IPluginInInventoryService,
+                                                                                        OpendaylightInventoryListener,
+                                                                                        FlowTopologyDiscoveryListener,
+                                                                                        OpendaylightFlowStatisticsListener,
+                                                                                        OpendaylightFlowTableStatisticsListener,
+                                                                                        OpendaylightPortStatisticsListener {
 
     private static val LOG = LoggerFactory.getLogger(InventoryAndReadAdapter);
 
+       private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue;
     @Property
     DataBrokerService dataService;
 
+    @Property
+    DataProviderService dataProviderService;
+
     @Property
     OpendaylightFlowStatisticsService flowStatisticsService;
 
+    @Property
+    OpendaylightPortStatisticsService nodeConnectorStatisticsService;
+    
+    @Property
+    OpendaylightFlowTableStatisticsService flowTableStatisticsService;
+
     @Property
     IPluginOutInventoryService inventoryPublisher;
 
@@ -67,6 +111,22 @@ class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInRead
 
     @Property
     FlowTopologyDiscoveryService topologyDiscovery;
+    
+    @Property
+    List<IPluginOutReadService> statisticsPublisher = new ArrayList<IPluginOutReadService>();
+       
+    def setReadPublisher(IPluginOutReadService listener) {
+       statisticsPublisher.add(listener);
+    }
+    
+    def unsetReadPublisher (IPluginOutReadService listener) {
+       if( listener != null)
+               statisticsPublisher.remove(listener);
+    }
+
+    protected def startChange() {
+        return dataProviderService.beginTransaction;
+    }
 
     override getTransmitRate(NodeConnector connector) {
         val nodeConnector = readFlowCapableNodeConnector(connector.toNodeConnectorRef);
@@ -74,82 +134,206 @@ class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInRead
     }
 
     override readAllFlow(Node node, boolean cached) {
-        val input = new GetAllFlowStatisticsInputBuilder;
-        input.setNode(node.toNodeRef);
-        val result = flowStatisticsService.getAllFlowStatistics(input.build)
 
-        val statistics = result.get.result;
         val output = new ArrayList<FlowOnNode>();
-        for (stat : statistics.flowStatistics) {
-            // FIXME: Create FlowOnNode
-        }
+               val tableRef = InstanceIdentifier.builder(Nodes)
+                                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                                       .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
+               
+               val it = this.startChange();
+               
+               val table= it.readConfigurationData(tableRef) as Table;
+               
+               if(table != null){
+                       LOG.info("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
+                       
+                       for(flow : table.flow){
+                               
+                               val adsalFlow = ToSalConversionsUtils.toFlow(flow);
+                               val statsFromDataStore = flow.getAugmentation(FlowStatisticsData) as FlowStatisticsData;
+                               
+                               if(statsFromDataStore != null){
+                                       val it = new FlowOnNode(adsalFlow);
+                                       byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
+                                       packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
+                                       durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
+                                       durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
+                                       
+                                       output.add(it);
+                               }
+                       }
+               }
+        
+        //TODO (main): Shell we send request to the switch? It will make async request to the switch.
+        // Once plugin receive response, it will let adaptor know through onFlowStatisticsUpdate()
+        // If we assume that md-sal statistics manager will always be running, then its not required
+        // But if not, then sending request will collect the latest data for adaptor atleast.
+        val input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder;
+        input.setNode(node.toNodeRef);
+        flowStatisticsService.getAllFlowsStatisticsFromAllFlowTables(input.build)
+        
         return output;
     }
 
     override readAllNodeConnector(Node node, boolean cached) {
-        val input = new GetAllNodeConnectorStatisticsInputBuilder();
+       
+       val ret = new ArrayList<NodeConnectorStatistics>();
+               val nodeRef = InstanceIdentifier.builder(Nodes)
+                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                                                       .toInstance();
+               
+               val provider = this.startChange();
+               
+               val dsNode= provider.readConfigurationData(nodeRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+               
+               if(dsNode != null){
+                       
+                       for (dsNodeConnector : dsNode.nodeConnector){
+                               val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
+                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector, dsNodeConnector.key)
+                                                                       .toInstance();
+                               
+                               val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+                               
+                               if(nodeConnectorFromDS != null){
+                                       val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
+                                       
+                                       ret.add(toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,dsNode.id,dsNodeConnector.id));
+                               }
+                       }
+               }
+
+               //TODO: Refer TODO (main)
+        val input = new GetAllNodeConnectorsStatisticsInputBuilder();
         input.setNode(node.toNodeRef);
-        val result = flowStatisticsService.getAllNodeConnectorStatistics(input.build());
-        val statistics = result.get.result.nodeConnectorStatistics;
-        val ret = new ArrayList<NodeConnectorStatistics>();
-        for (stat : statistics) {
-            ret.add(stat.toNodeConnectorStatistics())
-        }
+        nodeConnectorStatisticsService.getAllNodeConnectorsStatistics(input.build());
         return ret;
     }
 
     override readAllNodeTable(Node node, boolean cached) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+       val ret = new ArrayList<NodeTableStatistics>();
+       
+               val dsFlowCapableNode= readFlowCapableNode(node.toNodeRef)
+               
+               if(dsFlowCapableNode != null){
+                       
+                       for (table : dsFlowCapableNode.table){
+                               
+                               val tableStats = table.getAugmentation(FlowTableStatisticsData) as FlowTableStatisticsData;
+                               
+                               if(tableStats != null){
+                                       ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node));
+                               }
+                       }
+               }
+
+               //TODO: Refer TODO (main)
+        val input = new GetFlowTablesStatisticsInputBuilder();
+        input.setNode(node.toNodeRef);
+        flowTableStatisticsService.getFlowTablesStatistics(input.build);
+        return ret;
     }
 
     override readDescription(Node node, boolean cached) {
-        val capableNode = readFlowCapableNode(node.toNodeRef)
-
-        val it = new NodeDescription()
-        manufacturer = capableNode.manufacturer
-        serialNumber = capableNode.serialNumber
-        software = capableNode.software
-        description = capableNode.description
-
-        return it;
-    }
-
-    override readFlow(Node node, Flow flow, boolean cached) {
-        val input = flowStatisticsInput(node, flow);
-        val output = flowStatisticsService.getFlowStatistics(input);
-
-        try {
-            val statistics = output.get().getResult();
-            if (statistics != null) {
-                val it = new FlowOnNode(flow);
-                byteCount = statistics.byteCount.value.longValue
-                durationNanoseconds = statistics.duration.getNanosecond().getValue().intValue();
-                durationSeconds = statistics.duration.getSecond().getValue().intValue();
-                packetCount = statistics.getPacketCount().getValue().longValue();
-                return it;
-            }
-        } catch (Exception e) {
-            LOG.error("Read flow not processed", e);
-        }
-        return null;
+        return toNodeDescription(node.toNodeRef);
+       }
+
+    override readFlow(Node node, Flow targetFlow, boolean cached) {
+               var FlowOnNode ret= null;
+               
+               val tableRef = InstanceIdentifier.builder(Nodes)
+                                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
+                                                       .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
+               
+               val it = this.startChange();
+               
+               val table= it.readConfigurationData(tableRef) as Table;
+               
+               if(table != null){
+                       LOG.info("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
+                       
+                       for(mdsalFlow : table.flow){
+                               if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){
+                                       val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData) as FlowStatisticsData;
+                                       
+                                       if(statsFromDataStore != null){
+                                               LOG.debug("Found matching flow in the data store flow table ");
+                                               val it = new FlowOnNode(targetFlow);
+                                               byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
+                                               packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
+                                               durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
+                                               durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
+                                               
+                                               ret = it;
+                                       }
+                               }                       
+                       }
+               }
+        
+        //TODO: Refer TODO (main)
+        val input = new GetFlowStatisticsFromFlowTableInputBuilder;
+        input.setNode(node.toNodeRef);
+        input.fieldsFrom(MDFlowMapping.toMDSalflow(targetFlow));
+        flowStatisticsService.getFlowStatisticsFromFlowTable(input.build)
+        
+        return ret;
+       
     }
 
     override readNodeConnector(NodeConnector connector, boolean cached) {
+       var NodeConnectorStatistics  nodeConnectorStatistics = null;
+       
+               val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
+                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(connector.node))
+                                                                       .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector, InventoryMapping.toNodeConnectorKey(connector))
+                                                                       .toInstance();
+               val provider = this.startChange();
+                               
+               val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+                               
+               if(nodeConnectorFromDS != null){
+                       val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
+                       if(nodeConnectorStatsFromDs != null) {
+                               nodeConnectorStatistics = toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,
+                                                                                                                                               InventoryMapping.toNodeKey(connector.node).id,
+                                                                                                                                               InventoryMapping.toNodeConnectorKey(connector).id);
+                       }
+               }
+
+               //TODO: Refer TODO (main)
+        val input = new GetNodeConnectorStatisticsInputBuilder();
+        input.setNode(connector.node.toNodeRef);
+        input.setNodeConnectorId(InventoryMapping.toNodeConnectorKey(connector).id);
+        nodeConnectorStatisticsService.getNodeConnectorStatistics(input.build());
+        return nodeConnectorStatistics;
+    }
 
-        val getNodeConnectorStatisticsInput = FromSalConversionsUtils.nodeConnectorStatistics(connector);
-        val future = flowStatisticsService.getNodeConnectorStatistics(getNodeConnectorStatisticsInput);
-        try {
-            val rpcResult = future.get();
-            val output = rpcResult.getResult();
-
-            if (output != null) {
-                return output.toNodeConnectorStatistics;
-            }
-        } catch (Exception e) {
-            LOG.error("Read node connector not processed", e);
-        }
-
-        return null;
+    override readNodeTable(NodeTable nodeTable, boolean cached) {
+       var NodeTableStatistics nodeStats = null
+       
+       val tableRef = InstanceIdentifier.builder(Nodes)
+                                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(nodeTable.node))
+                                                       .augmentation(FlowCapableNode).child(Table, new TableKey(nodeTable.ID as Short)).toInstance();
+               
+               val it = this.startChange();
+               
+               val table= it.readConfigurationData(tableRef) as Table;
+               
+               if(table != null){
+                       val tableStats = table.getAugmentation(FlowTableStatisticsData) as FlowTableStatisticsData;
+                               
+                       if(tableStats != null){
+                               nodeStats =  toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node);
+                       }
+               }
+
+               //TODO: Refer TODO (main)
+        val input = new GetFlowTablesStatisticsInputBuilder();
+        input.setNode(nodeTable.node.toNodeRef);
+        flowTableStatisticsService.getFlowTablesStatistics(input.build);
+        
+        return nodeStats;
     }
 
     override onNodeConnectorRemoved(NodeConnectorRemoved update) {
@@ -157,17 +341,45 @@ class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInRead
     }
 
     override onNodeRemoved(NodeRemoved notification) {
-        // NOOP
+        val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
+
+        inventoryPublisher.updateNode(notification.nodeRef.toADNode, UpdateType.REMOVED, properties);
     }
 
     override onNodeConnectorUpdated(NodeConnectorUpdated update) {
-        val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
-        inventoryPublisher.updateNodeConnector(update.nodeConnectorRef.toADNodeConnector, UpdateType.CHANGED, properties);
+        val properties = new java.util.HashSet<org.opendaylight.controller.sal.core.Property>();
+
+
+        val org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> identifier = update.nodeConnectorRef.value as org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>;
+        var updateType = UpdateType.CHANGED;
+        if ( this._dataService.readOperationalData(identifier) == null ){
+            updateType = UpdateType.ADDED;
+        }
+
+        var nodeConnector = update.nodeConnectorRef.toADNodeConnector
+
+
+        properties.add(new org.opendaylight.controller.sal.core.Name(nodeConnector.ID.toString()));
+
+        inventoryPublisher.updateNodeConnector(nodeConnector , updateType , properties);
     }
 
     override onNodeUpdated(NodeUpdated notification) {
         val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
-        inventoryPublisher.updateNode(notification.nodeRef.toADNode, UpdateType.CHANGED, properties);
+        val org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> identifier = notification.nodeRef.value  as org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>;
+
+        var updateType = UpdateType.CHANGED;
+        if ( this._dataService.readOperationalData(identifier) == null ){
+            updateType = UpdateType.ADDED;
+        }
+        inventoryPublisher.updateNode(notification.nodeRef.toADNode, updateType, properties);
+        
+               //Notify the listeners of IPluginOutReadService
+        
+        for (statsPublisher : statisticsPublisher){
+                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+                       statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,toNodeDescription(notification.nodeRef));
+               }
     }
 
     override getNodeProps() {
@@ -182,10 +394,6 @@ class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInRead
         return null;
     }
 
-    override readNodeTable(NodeTable table, boolean cached) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-
     private def FlowCapableNode readFlowCapableNode(NodeRef ref) {
         val dataObject = dataService.readOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
         val node = dataObject.checkInstanceOf(
@@ -200,26 +408,61 @@ class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInRead
         return node.getAugmentation(FlowCapableNodeConnector);
     }
 
-    private static def toNodeConnectorStatistics(
-        org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics output) {
-        val it = new NodeConnectorStatistics
-
-        collisionCount = output.getCollisionCount().longValue();
-        receiveCRCErrorCount = output.getReceiveCrcError().longValue();
-        receiveFrameErrorCount = output.getReceiveFrameError().longValue();
-        receiveOverRunErrorCount = output.getReceiveOverRunError().longValue();
+    private def toNodeConnectorStatistics(
+        org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics nodeConnectorStatistics, NodeId nodeId, NodeConnectorId nodeConnectorId) {
+               
+                       val it = new NodeConnectorStatistics();
+                       
+                       receivePacketCount = nodeConnectorStatistics.packets.received.longValue;
+                       transmitPacketCount = nodeConnectorStatistics.packets.transmitted.longValue;
+                       
+                       receiveByteCount = nodeConnectorStatistics.bytes.received.longValue;
+                       transmitByteCount = nodeConnectorStatistics.bytes.transmitted.longValue;
+                       
+                       receiveDropCount = nodeConnectorStatistics.receiveDrops.longValue;
+                       transmitDropCount = nodeConnectorStatistics.transmitDrops.longValue;
+                       
+                       receiveErrorCount = nodeConnectorStatistics.receiveErrors.longValue;
+                       transmitErrorCount = nodeConnectorStatistics.transmitErrors.longValue;
+                       
+                       receiveFrameErrorCount = nodeConnectorStatistics.receiveFrameError.longValue;
+                       receiveOverRunErrorCount = nodeConnectorStatistics.receiveOverRunError.longValue;
+                       receiveCRCErrorCount = nodeConnectorStatistics.receiveCrcError.longValue;
+                       collisionCount = nodeConnectorStatistics.collisionCount.longValue;
+                       
+                       val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
+                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(nodeId))
+                                                               .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector,new NodeConnectorKey(nodeConnectorId)).toInstance;
+                       
+                       nodeConnector = NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef));
+                       
+                       return it;
+    }
 
-        receiveDropCount = output.getReceiveDrops().longValue();
-        receiveErrorCount = output.getReceiveErrors().longValue();
-        receivePacketCount = output.getPackets().getReceived().longValue();
-        receiveByteCount = output.getBytes().getReceived().longValue();
+       private def toNodeTableStatistics(
+               org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics tableStats,
+               Short tableId,Node node){
+               var it = new NodeTableStatistics();
+               
+               activeCount = tableStats.activeFlows.value.intValue;
+               lookupCount = tableStats.packetsLookedUp.value.intValue;
+               matchedCount = tableStats.packetsMatched.value.intValue;
+               name = tableId.toString;
+               nodeTable = new NodeTable(NodeMapping.MD_SAL_TYPE,tableId,node);
+               return it;
+       }
+       
+       private def toNodeDescription(NodeRef nodeRef){
+               val capableNode = readFlowCapableNode(nodeRef);
 
-        transmitDropCount = output.getTransmitDrops().longValue();
-        transmitErrorCount = output.getTransmitErrors().longValue();
-        transmitPacketCount = output.getPackets().getTransmitted().longValue();
-        transmitByteCount = output.getBytes().getTransmitted().longValue();
+        val it = new NodeDescription()
+        manufacturer = capableNode.manufacturer
+        serialNumber = capableNode.serialNumber
+        software = capableNode.software
+        description = capableNode.description
+        
         return it;
-    }
+       }
 
     override sollicitRefresh() {
         topologyDiscovery.solicitRefresh
@@ -248,5 +491,78 @@ class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInRead
     def Edge toADEdge(Link link) {
         new Edge(link.source.toADNodeConnector,link.destination.toADNodeConnector)
     }
-
+       
+       /*
+        * OpendaylightFlowStatisticsListener interface implementation
+        */
+       override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
+               throw new UnsupportedOperationException("TODO: auto-generated method stub")
+       }
+       
+       override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
+               
+               val adsalFlowsStatistics = new ArrayList<FlowOnNode>();
+               
+               for(flowStats : notification.flowAndStatisticsMapList){
+                       if(flowStats.tableId == 0)
+                               adsalFlowsStatistics.add(toFlowOnNode(flowStats));
+               }
+               
+               for (statsPublisher : statisticsPublisher){
+                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+                       statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics);
+               }
+               
+       }
+       /*
+        * OpendaylightFlowTableStatisticsListener interface implementation
+        */     
+       override onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
+               var adsalFlowTableStatistics = new ArrayList<NodeTableStatistics>();
+               
+               for(stats : notification.flowTableAndStatisticsMap){
+                       if (stats.tableId.value == 0){
+                               val it = new NodeTableStatistics();
+                               activeCount = stats.activeFlows.value.intValue;
+                               lookupCount = stats.packetsLookedUp.value.longValue;
+                               matchedCount = stats.packetsMatched.value.longValue;
+                               
+                               adsalFlowTableStatistics.add(it);
+                       }
+               }
+               for (statsPublisher : statisticsPublisher){
+                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+                       statsPublisher.nodeTableStatisticsUpdated(nodeRef.toADNode,adsalFlowTableStatistics);
+               }
+       }
+       
+       /*
+        * OpendaylightPortStatisticsUpdate interface implementation
+        */
+       override onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) {
+               
+               val adsalPortStatistics  = new ArrayList<NodeConnectorStatistics>();
+               
+               for(nodeConnectorStatistics : notification.nodeConnectorStatisticsAndPortNumberMap){
+                       adsalPortStatistics.add(toNodeConnectorStatistics(nodeConnectorStatistics,notification.id,nodeConnectorStatistics.nodeConnectorId));
+               }
+               
+               for (statsPublisher : statisticsPublisher){
+                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
+                       statsPublisher.nodeConnectorStatisticsUpdated(nodeRef.toADNode,adsalPortStatistics);
+               }
+               
+       }
+       
+       private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap){
+               
+               val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap));
+               
+               byteCount = flowAndStatsMap.byteCount.value.longValue;
+               packetCount = flowAndStatsMap.packetCount.value.longValue;
+               durationSeconds = flowAndStatsMap.duration.second.value.intValue;
+               durationNanoseconds = flowAndStatsMap.duration.nanosecond.value.intValue;
+               
+               return it;
+       }
 }
index 6cf728cde967d2ca1ed250dc93198a061a226795..2f458c41ddfc8dce40325338fe015ba41e8c4118 100644 (file)
@@ -5,7 +5,6 @@ import java.math.BigInteger
 import java.net.Inet4Address
 import java.net.Inet6Address
 import java.util.ArrayList
-import java.util.List
 import org.opendaylight.controller.sal.action.Controller
 import org.opendaylight.controller.sal.action.Drop
 import org.opendaylight.controller.sal.action.Flood
@@ -40,7 +39,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddF
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsInputBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder
@@ -67,7 +65,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.hw.path.action._case.HwPathActionBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.loopback.action._case.LoopbackActionBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder
@@ -106,6 +103,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCaseBuilder
 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.instruction.ApplyActionsCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder
 
 public class MDFlowMapping {
 
@@ -142,13 +141,6 @@ public class MDFlowMapping {
         return it.build;
     }
 
-    public static def flowStatisticsInput(Node sourceNode, Flow sourceFlow) {
-        val source = flowAdded(sourceFlow);
-        val it = new GetFlowStatisticsInputBuilder(source as org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow);
-        node = sourceNode.toNodeRef();
-        return it.build();
-    }
-
     public static def removeFlowInput(Node sourceNode, Flow sourceFlow) {
         val source = flowAdded(sourceFlow);
         val it = new RemoveFlowInputBuilder(source as org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow);
@@ -355,7 +347,7 @@ public class MDFlowMapping {
     }
 
     public static def Uri toUri(NodeConnector connector) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        return new NodeConnectorId(connector.ID as String);
     }
 
     public static def MacAddress toMacAddress(byte[] bytes) {
@@ -367,4 +359,25 @@ public class MDFlowMapping {
         }
         return new MacAddress(sb.toString());
     }
+       
+       public static def toMDSalflow(Flow sourceFlow) {
+        if (sourceFlow == null)
+            throw new IllegalArgumentException();
+        val it = new FlowBuilder();
+
+        hardTimeout = sourceFlow.hardTimeout as int
+        idleTimeout = sourceFlow.idleTimeout as int
+        cookie = BigInteger.valueOf(sourceFlow.id)
+        priority = sourceFlow.priority as int
+
+        val sourceActions = sourceFlow.actions;
+        val targetActions = new ArrayList<Action>();
+        for (sourceAction : sourceActions) {
+            targetActions.add(sourceAction.toAction());
+        }
+        instructions = targetActions.toApplyInstruction();
+        match = sourceFlow.match.toMatch();
+        return it.build();
+       }
+       
 }
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDSalNodeConnectorFactory.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDSalNodeConnectorFactory.java
new file mode 100644 (file)
index 0000000..5b4b16a
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.controller.sal.compatibility;
+
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.utils.INodeConnectorFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MDSalNodeConnectorFactory implements INodeConnectorFactory{
+    private Logger logger = LoggerFactory.getLogger(MDSalNodeConnectorFactory.class);
+
+    @Override
+    public NodeConnector fromStringNoNode(String type, String id, Node node) {
+        try {
+            return new NodeConnector(type, id, node);
+        } catch (ConstructionException e) {
+            logger.error("Could not construct NodeConnector", e);
+        }
+        return null;
+
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDSalNodeFactory.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDSalNodeFactory.java
new file mode 100644 (file)
index 0000000..e36ebd7
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.sal.compatibility;
+
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.INodeFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MDSalNodeFactory implements INodeFactory{
+    private Logger logger = LoggerFactory.getLogger(MDSalNodeFactory.class);
+
+    @Override
+    public Node fromString(String type, String id) {
+
+        try {
+            return new Node(type, id);
+        } catch (ConstructionException e) {
+            logger.error("Could not construct Node", e);
+        }
+        return null;
+    }
+}
index 4c9a9e6658145c481c153e9747434ef65b395443..6bfee578abc0ce56d78ce7aaa432bd4cee7aecd6 100644 (file)
@@ -10,17 +10,19 @@ import static extension org.opendaylight.controller.sal.common.util.Arguments.*;
 
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
 import org.opendaylight.controller.sal.core.ConstructionException
 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.NodeId
+
 
 public class NodeMapping {
 
     public static val MD_SAL_TYPE = "MD_SAL";
     private static val NODE_CLASS = org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-    private static val NODECONNECTOR_CLASS = org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.
-        NodeConnector;
+    private static val NODECONNECTOR_CLASS = org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 
     private new() {
         throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
@@ -33,7 +35,7 @@ public class NodeMapping {
         val arg = node.getPath().get(1);
         val item = arg.checkInstanceOf(IdentifiableItem);
         val nodeKey = item.getKey().checkInstanceOf(NodeKey);
-        return new Node(MD_SAL_TYPE, nodeKey);
+        return new Node(MD_SAL_TYPE, nodeKey.getId().getValue().toString());
     }
 
     public static def toADNodeConnector(NodeConnectorRef source) throws ConstructionException {
@@ -44,20 +46,22 @@ public class NodeMapping {
         val arg = path.getPath().get(2);
         val item = arg.checkInstanceOf(IdentifiableItem);
         val connectorKey = item.getKey().checkInstanceOf(NodeConnectorKey);
-        return new NodeConnector(MD_SAL_TYPE, connectorKey, node);
+        return new NodeConnector(MD_SAL_TYPE, connectorKey.getId().getValue().toString(), node);
     }
-
+    
     public static def toNodeRef(Node node) {
         checkArgument(MD_SAL_TYPE.equals(node.getType()));
-        val nodeKey = node.ID.checkInstanceOf(NodeKey);
+        var nodeId = node.ID.checkInstanceOf(String)
+        val nodeKey = new NodeKey(new NodeId(nodeId));
         val nodePath = InstanceIdentifier.builder().node(Nodes).child(NODE_CLASS, nodeKey).toInstance();
         return new NodeRef(nodePath);
     }
-
+    
     public static def toNodeConnectorRef(NodeConnector nodeConnector) {
         val node = nodeConnector.node.toNodeRef();
         val nodePath = node.getValue() as InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
-        val connectorKey = nodeConnector.ID.checkInstanceOf(NodeConnectorKey);
+        var nodeConnectorId = nodeConnector.ID.checkInstanceOf(String)
+        val connectorKey = new NodeConnectorKey(new NodeConnectorId(nodeConnectorId));
         val path = InstanceIdentifier.builder(nodePath).child(NODECONNECTOR_CLASS, connectorKey).toInstance();
         return new NodeConnectorRef(path);
     }
@@ -65,5 +69,5 @@ public class NodeMapping {
     public static def toADNode(NodeRef node) throws ConstructionException {
         return toADNode(node.getValue());
     }
-
+    
 }
index a8349be1b410f2abcd3714de6ba141e8257c02d0..37bb2778584dc6deb08add85d63eee4ca9489acd 100644 (file)
@@ -1,6 +1,25 @@
 package org.opendaylight.controller.sal.compatibility;
 
-import com.google.common.net.InetAddresses;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
+import static org.opendaylight.controller.sal.match.MatchType.DL_DST;
+import static org.opendaylight.controller.sal.match.MatchType.DL_SRC;
+import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE;
+import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN;
+import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN_PR;
+import static org.opendaylight.controller.sal.match.MatchType.NW_DST;
+import static org.opendaylight.controller.sal.match.MatchType.NW_PROTO;
+import static org.opendaylight.controller.sal.match.MatchType.NW_SRC;
+import static org.opendaylight.controller.sal.match.MatchType.NW_TOS;
+import static org.opendaylight.controller.sal.match.MatchType.TP_DST;
+import static org.opendaylight.controller.sal.match.MatchType.TP_SRC;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 import org.opendaylight.controller.sal.action.Controller;
 import org.opendaylight.controller.sal.action.Drop;
@@ -33,7 +52,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.ActionList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCase;
@@ -88,26 +106,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
 
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
-import static org.opendaylight.controller.sal.match.MatchType.DL_DST;
-import static org.opendaylight.controller.sal.match.MatchType.DL_SRC;
-import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE;
-import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN;
-import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN_PR;
-import static org.opendaylight.controller.sal.match.MatchType.NW_DST;
-import static org.opendaylight.controller.sal.match.MatchType.NW_PROTO;
-import static org.opendaylight.controller.sal.match.MatchType.NW_SRC;
-import static org.opendaylight.controller.sal.match.MatchType.NW_TOS;
-import static org.opendaylight.controller.sal.match.MatchType.TP_DST;
-import static org.opendaylight.controller.sal.match.MatchType.TP_SRC;
+import com.google.common.net.InetAddresses;
 
 public class ToSalConversionsUtils {
 
@@ -484,11 +483,11 @@ public class ToSalConversionsUtils {
     private static void fillFromArp(Match target, ArpMatch source) {
         Ipv4Prefix sourceAddress = source.getArpSourceTransportAddress();
         if (sourceAddress != null) {
-            target.setField(NW_SRC, (InetAddress) inetAddressFrom(sourceAddress), null);
+            target.setField(NW_SRC, inetAddressFrom(sourceAddress), null);
         }
         Ipv4Prefix destAddress = source.getArpTargetTransportAddress();
         if (destAddress != null) {
-            target.setField(NW_DST, (InetAddress) inetAddressFrom(destAddress), null);
+            target.setField(NW_DST, inetAddressFrom(destAddress), null);
         }
         ArpSourceHardwareAddress sourceHwAddress = source.getArpSourceHardwareAddress();
         if (sourceHwAddress != null) {
@@ -506,22 +505,22 @@ public class ToSalConversionsUtils {
     private static void fillFromIpv6(Match target, Ipv6Match source) {
         Ipv6Prefix sourceAddress = source.getIpv6Source();
         if (sourceAddress != null) {
-            target.setField(NW_SRC, (InetAddress) inetAddressFrom(sourceAddress), null);
+            target.setField(NW_SRC, inetAddressFrom(sourceAddress), null);
         }
         Ipv6Prefix destAddress = source.getIpv6Destination();
         if (destAddress != null) {
-            target.setField(NW_DST, (InetAddress) inetAddressFrom(destAddress), null);
+            target.setField(NW_DST, inetAddressFrom(destAddress), null);
         }
     }
 
     private static void fillFromIpv4(Match target, Ipv4Match source) {
         Ipv4Prefix sourceAddress = source.getIpv4Source();
         if (sourceAddress != null) {
-            target.setField(NW_SRC, (InetAddress) inetAddressFrom(sourceAddress), null);
+            target.setField(NW_SRC, inetAddressFrom(sourceAddress), null);
         }
         Ipv4Prefix destAddress = source.getIpv4Destination();
         if (destAddress != null) {
-            target.setField(NW_DST, (InetAddress) inetAddressFrom(destAddress), null);
+            target.setField(NW_DST, inetAddressFrom(destAddress), null);
         }
     }
 
index 09585d6273a0c2cecd32e90d4f442313bf685946..149544b6c4e76509af96635ccc7fd21423dc9935 100644 (file)
@@ -8,6 +8,8 @@ import java.util.concurrent.Future;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.common.util.Futures;
 import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.compatibility.FromSalConversionsUtils;
+import org.opendaylight.controller.sal.compatibility.InventoryMapping;
 import org.opendaylight.controller.sal.compatibility.NodeMapping;
 import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.core.ConstructionException;
@@ -19,87 +21,78 @@ import org.opendaylight.controller.sal.reader.IReadServiceListener;
 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
 import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowTableStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowTableStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowTableStatisticsOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.NodeConnectorStatisticsUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.flow.statistics.output.FlowStatistics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.flow.statistics.output.FlowStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.node.connector.statistics.output.NodeConnectorStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.statistics.Duration;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.statistics.DurationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.Bytes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.Packets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService, IReadServiceListener {
+public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService, IReadServiceListener{
 
     private static final Logger LOG = LoggerFactory.getLogger(FlowStatisticsAdapter.class);
     private IReadService readDelegate;
     private NotificationProviderService notifier;
 
     @Override
-    public Future<RpcResult<GetAllFlowStatisticsOutput>> getAllFlowStatistics(GetAllFlowStatisticsInput input) {
-        GetAllFlowStatisticsOutput rpcResultType = null;
-        boolean rpcResultBool = false;
-
-        try {
-            Node adNode = NodeMapping.toADNode(input.getNode());
-            List<FlowOnNode> flowsOnNode = readDelegate.readAllFlows(adNode);
-            List<FlowStatistics> flowsStatistics = toOdFlowsStatistics(flowsOnNode);
-            GetAllFlowStatisticsOutputBuilder builder = new GetAllFlowStatisticsOutputBuilder();
-            rpcResultType = builder.setFlowStatistics(flowsStatistics).build();
-            rpcResultBool = true;
-        } catch (ConstructionException e) {
-            LOG.error(e.getMessage());
-        }
+    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> getAggregateFlowStatisticsFromFlowTableForAllFlows(
+            GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput input) {
+        //TODO: No supported API exist in AD-SAL, it can either be implemented by fetching all the stats of the flows and 
+        // generating aggregate flow statistics out of those individual flow stats.
+        return null;
+    }
 
-        return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
+    @Override
+    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> getAggregateFlowStatisticsFromFlowTableForGivenMatch(
+            GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
+        //TODO: No supported API exist in AD-SAL, it can either be implemented by fetching all the stats of the flows and 
+        // generating aggregate flow statistics out of those individual flow stats.
+        return null;
     }
 
     @Override
-    public Future<RpcResult<GetAllNodeConnectorStatisticsOutput>> getAllNodeConnectorStatistics(
-            GetAllNodeConnectorStatisticsInput input) {
-        GetAllNodeConnectorStatisticsOutput rpcResultType = null;
+    public Future<RpcResult<GetAllFlowStatisticsFromFlowTableOutput>> getAllFlowStatisticsFromFlowTable(
+            GetAllFlowStatisticsFromFlowTableInput input) {
+        GetAllFlowStatisticsFromFlowTableOutput rpcResultType = null;
         boolean rpcResultBool = false;
 
         try {
             Node adNode = NodeMapping.toADNode(input.getNode());
-            List<NodeConnectorStatistics> nodesConnectorStatistics = readDelegate.readNodeConnectors(adNode);
-            List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.node.connector.statistics.output.NodeConnectorStatistics> odNodesConnectorStatistics;
-            odNodesConnectorStatistics = toOdNodesConnectorStatistics(nodesConnectorStatistics);
-            GetAllNodeConnectorStatisticsOutputBuilder builder = new GetAllNodeConnectorStatisticsOutputBuilder();
-            rpcResultType = builder.setNodeConnectorStatistics(odNodesConnectorStatistics).build();
+            List<FlowOnNode> flowsOnNode = readDelegate.readAllFlows(adNode);
+            List<FlowAndStatisticsMapList> flowsStatistics = toOdFlowsStatistics(flowsOnNode);
+            GetAllFlowStatisticsFromFlowTableOutputBuilder builder = new GetAllFlowStatisticsFromFlowTableOutputBuilder();
+            builder.setTransactionId(new TransactionId(new BigInteger("0")));
+            rpcResultType = builder.setFlowAndStatisticsMapList(flowsStatistics).build();
+            
             rpcResultBool = true;
         } catch (ConstructionException e) {
             LOG.error(e.getMessage());
@@ -108,17 +101,24 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
         return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
     }
 
+    /**
+     * Essentially this API will return the same result as getAllFlowStatisticsFromFlowTable
+     */
     @Override
-    public Future<RpcResult<GetFlowStatisticsOutput>> getFlowStatistics(GetFlowStatisticsInput input) {
-        GetFlowStatisticsOutput rpcResultType = null;
+    public Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> getAllFlowsStatisticsFromAllFlowTables(
+            GetAllFlowsStatisticsFromAllFlowTablesInput input) {
+        
+        GetAllFlowsStatisticsFromAllFlowTablesOutput rpcResultType = null;
         boolean rpcResultBool = false;
 
         try {
-            Node node = NodeMapping.toADNode(input.getNode());
-            Flow flow = ToSalConversionsUtils.toFlow(input);
-            FlowOnNode readFlow = readDelegate.readFlow(node, flow);
-            FlowStatistics flowOnNodeToFlowStatistics = toOdFlowStatistics(readFlow);
-            rpcResultType = new GetFlowStatisticsOutputBuilder(flowOnNodeToFlowStatistics).build();
+            Node adNode = NodeMapping.toADNode(input.getNode());
+            List<FlowOnNode> flowsOnNode = readDelegate.readAllFlows(adNode);
+            List<FlowAndStatisticsMapList> flowsStatistics = toOdFlowsStatistics(flowsOnNode);
+            GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder builder = new GetAllFlowsStatisticsFromAllFlowTablesOutputBuilder();
+            builder.setTransactionId(new TransactionId(new BigInteger("0")));
+            rpcResultType = builder.setFlowAndStatisticsMapList(flowsStatistics).build();
+            
             rpcResultBool = true;
         } catch (ConstructionException e) {
             LOG.error(e.getMessage());
@@ -128,38 +128,18 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
     }
 
     @Override
-    public Future<RpcResult<GetFlowTableStatisticsOutput>> getFlowTableStatistics(GetFlowTableStatisticsInput input) {
-        GetFlowTableStatisticsOutput rpcResultType = null;
+    public Future<RpcResult<GetFlowStatisticsFromFlowTableOutput>> getFlowStatisticsFromFlowTable(
+            GetFlowStatisticsFromFlowTableInput input) {
+        GetFlowStatisticsFromFlowTableOutput rpcResultType = null;
         boolean rpcResultBool = false;
 
         try {
             Node node = NodeMapping.toADNode(input.getNode());
-            List<NodeTableStatistics> nodesTable = readDelegate.readNodeTable(node);
-            NodeTableStatistics nodeTable = null;
-            if (!nodesTable.isEmpty()) {
-                nodeTable = nodesTable.get(0);
-                rpcResultType = toOdTableStatistics(nodeTable);
-                rpcResultBool = true;
-            }
-        } catch (ConstructionException e) {
-            LOG.error(e.getMessage());
-        }
-
-        return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
-    }
-
-    @Override
-    public Future<RpcResult<GetNodeConnectorStatisticsOutput>> getNodeConnectorStatistics(
-            GetNodeConnectorStatisticsInput input) {
-        GetNodeConnectorStatisticsOutput rpcResultType = null;
-        boolean rpcResultBool = false;
-
-        NodeConnectorRef nodeConnector = input.getNodeConnector();
-        try {
-            NodeConnectorStatistics nodeConnectorStats = readDelegate.readNodeConnector(NodeMapping
-                    .toADNodeConnector(nodeConnector));
-            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.node.connector.statistics.output.NodeConnectorStatistics odNodeConnectorStatistics = toOdNodeConnectorStatistics(nodeConnectorStats);
-            rpcResultType = new GetNodeConnectorStatisticsOutputBuilder(odNodeConnectorStatistics).build();
+            Flow flow = ToSalConversionsUtils.toFlow(input);
+            FlowOnNode readFlow = readDelegate.readFlow(node, flow);
+            List<FlowAndStatisticsMapList> flowOnNodeToFlowStatistics = new ArrayList<FlowAndStatisticsMapList>();
+            flowOnNodeToFlowStatistics.add(toOdFlowStatistics(readFlow));
+            rpcResultType = new GetFlowStatisticsFromFlowTableOutputBuilder().setFlowAndStatisticsMapList(flowOnNodeToFlowStatistics).build();
             rpcResultBool = true;
         } catch (ConstructionException e) {
             LOG.error(e.getMessage());
@@ -169,59 +149,74 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
     }
 
     @Override
-    public void descriptionStatisticsUpdated(Node node, NodeDescription nodeDescription) {
-
-        // TODO which *StatisticsUpdated interface should be used?
-
+    public void nodeFlowStatisticsUpdated(Node node, List<FlowOnNode> flowStatsList) {
+        List<FlowAndStatisticsMapList> flowStatistics = toOdFlowsStatistics(flowStatsList);
+        FlowsStatisticsUpdateBuilder flowsStatisticsUpdateBuilder = new FlowsStatisticsUpdateBuilder();
+        flowsStatisticsUpdateBuilder.setFlowAndStatisticsMapList(flowStatistics);
+        flowsStatisticsUpdateBuilder.setMoreReplies(false);
+        flowsStatisticsUpdateBuilder.setTransactionId(null);
+        flowsStatisticsUpdateBuilder.setId(InventoryMapping.toNodeKey(node).getId());
+        notifier.publish(flowsStatisticsUpdateBuilder.build());
     }
 
     @Override
     public void nodeConnectorStatisticsUpdated(Node node, List<NodeConnectorStatistics> ncStatsList) {
-        for (NodeConnectorStatistics ndConStats : ncStatsList) {
-            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.node.connector.statistics.output.NodeConnectorStatistics odNodeConnectorStatistics;
-            odNodeConnectorStatistics = toOdNodeConnectorStatistics(ndConStats);
-            NodeConnectorStatisticsUpdatedBuilder statisticsBuilder = new NodeConnectorStatisticsUpdatedBuilder(
-                    odNodeConnectorStatistics);
-            notifier.publish(statisticsBuilder.build());
-        }
-    }
-
-    @Override
-    public void nodeFlowStatisticsUpdated(Node node, List<FlowOnNode> flowStatsList) {
-        for (FlowOnNode flowOnNode : flowStatsList) {
-            FlowStatistics flowStatistics = toOdFlowStatistics(flowOnNode);
-            FlowStatisticsUpdatedBuilder statisticsBuilder = new FlowStatisticsUpdatedBuilder(flowStatistics);
-            notifier.publish(statisticsBuilder.build());
-        }
+        NodeConnectorStatisticsUpdateBuilder nodeConnectorStatisticsUpdateBuilder = new NodeConnectorStatisticsUpdateBuilder();
+        List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatistics = toOdNodeConnectorStatistics(ncStatsList);
+        
+        nodeConnectorStatisticsUpdateBuilder.setNodeConnectorStatisticsAndPortNumberMap(nodeConnectorStatistics);
+        nodeConnectorStatisticsUpdateBuilder.setMoreReplies(false);
+        nodeConnectorStatisticsUpdateBuilder.setTransactionId(null);
+        nodeConnectorStatisticsUpdateBuilder.setId(InventoryMapping.toNodeKey(node).getId());
+        notifier.publish(nodeConnectorStatisticsUpdateBuilder.build());
     }
 
     @Override
     public void nodeTableStatisticsUpdated(Node node, List<NodeTableStatistics> tableStatsList) {
-        // TODO : Not implemented by AD-SAL.
+        
+        FlowTableStatisticsUpdateBuilder flowTableStatisticsUpdateBuilder = new FlowTableStatisticsUpdateBuilder();  
+        
+        List<FlowTableAndStatisticsMap>  flowTableStatistics = toOdFlowTableStatistics(tableStatsList);
+        flowTableStatisticsUpdateBuilder.setFlowTableAndStatisticsMap(flowTableStatistics);
+        flowTableStatisticsUpdateBuilder.setMoreReplies(false);
+        flowTableStatisticsUpdateBuilder.setTransactionId(null);
+        flowTableStatisticsUpdateBuilder.setId(InventoryMapping.toNodeKey(node).getId());
+        notifier.publish(flowTableStatisticsUpdateBuilder.build());
+}
+
+        @Override
+    public void descriptionStatisticsUpdated(Node node, NodeDescription nodeDescription) {
+            // TODO which *StatisticsUpdated interface should be used?
+        
     }
 
-    private List<FlowStatistics> toOdFlowsStatistics(List<FlowOnNode> flowsOnNode) {
-        List<FlowStatistics> flowsStatistics = new ArrayList<>();
+    private List<FlowAndStatisticsMapList> toOdFlowsStatistics(List<FlowOnNode> flowsOnNode) {
+        List<FlowAndStatisticsMapList> flowsStatistics = new ArrayList<>();
         for (FlowOnNode flowOnNode : flowsOnNode) {
             flowsStatistics.add(toOdFlowStatistics(flowOnNode));
         }
         return flowsStatistics;
     }
 
-    private FlowStatistics toOdFlowStatistics(FlowOnNode flowOnNode) {
-        FlowStatisticsBuilder builder = new FlowStatisticsBuilder();
+    private FlowAndStatisticsMapList toOdFlowStatistics(FlowOnNode flowOnNode) {
+        FlowAndStatisticsMapListBuilder builder = new FlowAndStatisticsMapListBuilder();
 
         builder.setByteCount(toCounter64(flowOnNode.getByteCount()));
         builder.setPacketCount(toCounter64(flowOnNode.getPacketCount()));
         builder.setDuration(extractDuration(flowOnNode));
-
+        builder.setMatch(FromSalConversionsUtils.toMatch(flowOnNode.getFlow().getMatch()));
+        builder.setPriority((int)flowOnNode.getFlow().getPriority());
+        builder.setHardTimeout((int)flowOnNode.getFlow().getHardTimeout());
+        builder.setIdleTimeout((int)flowOnNode.getFlow().getIdleTimeout());
+        //TODO: actions to instruction conversion
+        builder.setInstructions(null);
         return builder.build();
     }
 
-    private Duration extractDuration(FlowOnNode flowOnNode) {
+    private org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.Duration extractDuration(FlowOnNode flowOnNode) {
         DurationBuilder builder = new DurationBuilder();
-        builder.setNanosecond(toCounter64(flowOnNode.getDurationNanoseconds()));
-        builder.setSecond(toCounter64(flowOnNode.getDurationSeconds()));
+        builder.setNanosecond(new Counter32((long)flowOnNode.getDurationNanoseconds()));
+        builder.setSecond(new Counter32((long)flowOnNode.getDurationSeconds()));
         return builder.build();
     }
 
@@ -231,38 +226,43 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
         return new Counter64(byteCountBigInt);
     }
 
-    private Counter64 toCounter64(int num) {
-        String byteCountStr = String.valueOf(num);
-        BigInteger byteCountBigInt = new BigInteger(byteCountStr);
-        return new Counter64(byteCountBigInt);
-    }
-
-    private List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.node.connector.statistics.output.NodeConnectorStatistics> toOdNodesConnectorStatistics(
-            List<NodeConnectorStatistics> nodesConnectorStatistics) {
-        List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.node.connector.statistics.output.NodeConnectorStatistics> odNodesConnectorStatistics = new ArrayList<>();
-        for (NodeConnectorStatistics nodeConnectorStatistics : nodesConnectorStatistics) {
-            odNodesConnectorStatistics.add(toOdNodeConnectorStatistics(nodeConnectorStatistics));
+    private List<FlowTableAndStatisticsMap> toOdFlowTableStatistics(List<NodeTableStatistics> tableStatsList) {
+        
+        List<FlowTableAndStatisticsMap> flowTableStatsMap = new ArrayList<FlowTableAndStatisticsMap>();
+        for (NodeTableStatistics nodeTableStatistics : tableStatsList) {
+            FlowTableAndStatisticsMapBuilder flowTableAndStatisticsMapBuilder = new FlowTableAndStatisticsMapBuilder();
+            flowTableAndStatisticsMapBuilder.setActiveFlows(new Counter32((long) nodeTableStatistics.getActiveCount()));
+            flowTableAndStatisticsMapBuilder.setPacketsLookedUp(toCounter64(nodeTableStatistics.getLookupCount()));
+            flowTableAndStatisticsMapBuilder.setPacketsMatched(toCounter64(nodeTableStatistics.getMatchedCount()));
+            flowTableAndStatisticsMapBuilder.setActiveFlows(new Counter32((long) nodeTableStatistics.getActiveCount()));
+            flowTableAndStatisticsMapBuilder.setTableId(new TableId((short)nodeTableStatistics.getNodeTable().getID()));
+            flowTableStatsMap.add(flowTableAndStatisticsMapBuilder.build());
         }
-        return odNodesConnectorStatistics;
+        
+        return flowTableStatsMap;
     }
 
-    private org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.all.node.connector.statistics.output.NodeConnectorStatistics toOdNodeConnectorStatistics(
-            NodeConnectorStatistics ndConStats) {
-        NodeConnectorStatisticsBuilder builder = new NodeConnectorStatisticsBuilder();
-
-        builder.setBytes(extractBytes(ndConStats));
-        builder.setCollisionCount(toBI(ndConStats.getCollisionCount()));
-        builder.setDuration(null);
-        builder.setPackets(extractPackets(ndConStats));
-        builder.setReceiveCrcError(toBI(ndConStats.getReceiveCRCErrorCount()));
-        builder.setReceiveDrops(toBI(ndConStats.getReceiveDropCount()));
-        builder.setReceiveErrors(toBI(ndConStats.getReceiveErrorCount()));
-        builder.setReceiveFrameError(toBI(ndConStats.getReceiveFrameErrorCount()));
-        builder.setReceiveOverRunError(toBI(ndConStats.getReceiveOverRunErrorCount()));
-        builder.setTransmitDrops(toBI(ndConStats.getTransmitDropCount()));
-        builder.setTransmitErrors(toBI(ndConStats.getTransmitErrorCount()));
-
-        return builder.build();
+    private List<NodeConnectorStatisticsAndPortNumberMap> toOdNodeConnectorStatistics(
+            List<NodeConnectorStatistics> ncStatsList) {
+        List<NodeConnectorStatisticsAndPortNumberMap> nodeConnectorStatisticsList = new ArrayList<NodeConnectorStatisticsAndPortNumberMap>();
+        for(NodeConnectorStatistics ofNodeConnectorStatistics : ncStatsList){
+            NodeConnectorStatisticsAndPortNumberMapBuilder nodeConnectorStatisticsAndPortNumberMapBuilder = new NodeConnectorStatisticsAndPortNumberMapBuilder();
+            
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setBytes(extractBytes(ofNodeConnectorStatistics));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setCollisionCount(toBI(ofNodeConnectorStatistics.getCollisionCount()));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setDuration(null);
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setPackets(extractPackets(ofNodeConnectorStatistics));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setReceiveCrcError(toBI(ofNodeConnectorStatistics.getReceiveCRCErrorCount()));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setReceiveDrops(toBI(ofNodeConnectorStatistics.getReceiveDropCount()));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setReceiveErrors(toBI(ofNodeConnectorStatistics.getReceiveErrorCount()));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setReceiveFrameError(toBI(ofNodeConnectorStatistics.getReceiveFrameErrorCount()));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setReceiveOverRunError(toBI(ofNodeConnectorStatistics.getReceiveOverRunErrorCount()));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setTransmitDrops(toBI(ofNodeConnectorStatistics.getTransmitDropCount()));
+            nodeConnectorStatisticsAndPortNumberMapBuilder.setTransmitErrors(toBI(ofNodeConnectorStatistics.getTransmitErrorCount()));
+            nodeConnectorStatisticsList.add(nodeConnectorStatisticsAndPortNumberMapBuilder.build());
+        }
+        
+        return nodeConnectorStatisticsList;
     }
 
     private BigInteger toBI(long num) {
@@ -292,49 +292,4 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
         return builder.build();
     }
 
-    private GetFlowTableStatisticsOutput toOdTableStatistics(NodeTableStatistics nodeTable) {
-        GetFlowTableStatisticsOutputBuilder builder = new GetFlowTableStatisticsOutputBuilder();
-
-        builder.setActive(toCounter64(nodeTable.getActiveCount()));
-        builder.setLookup(toCounter64(nodeTable.getLookupCount()));
-        builder.setMatched(toCounter64(nodeTable.getMatchedCount()));
-
-        return builder.build();
-    }
-
-    @Override
-    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> getAggregateFlowStatisticsFromFlowTableForAllFlows(
-            GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput input) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> getAggregateFlowStatisticsFromFlowTableForGivenMatch(
-            GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Future<RpcResult<GetAllFlowStatisticsFromFlowTableOutput>> getAllFlowStatisticsFromFlowTable(
-            GetAllFlowStatisticsFromFlowTableInput input) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> getAllFlowsStatisticsFromAllFlowTables(
-            GetAllFlowsStatisticsFromAllFlowTablesInput input) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Future<RpcResult<GetFlowStatisticsFromFlowTableOutput>> getFlowStatisticsFromFlowTable(
-            GetFlowStatisticsFromFlowTableInput input) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
 }
index 5203d3c1a8165932e78fbe4fbe0f739b45926f0d..6fcadea8bf378af897d36bd916c72997eca6c08c 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef
 
 class FlowTransaction extends AbstractTransaction {
     
@@ -32,6 +33,7 @@ class FlowTransaction extends AbstractTransaction {
             val tableInstanceId = instanceId.firstIdentifierOf(Table);
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new RemoveFlowInputBuilder(flow);
+            builder.setFlowRef(new FlowRef(instanceId));
             builder.setNode(new NodeRef(nodeInstanceId));
             builder.setFlowTable(new FlowTableRef(tableInstanceId));
             _salFlowService.removeFlow(builder.build());            
@@ -45,6 +47,7 @@ class FlowTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new UpdateFlowInputBuilder();
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setFlowRef(new FlowRef(instanceId));
             val ufb = new UpdatedFlowBuilder(updatedFlow);
             builder.setUpdatedFlow((ufb.build()));
             val ofb = new OriginalFlowBuilder(originalFlow);
@@ -61,6 +64,7 @@ class FlowTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new AddFlowInputBuilder(flow);
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setFlowRef(new FlowRef(instanceId));
             builder.setFlowTable(new FlowTableRef(tableInstanceId));
             _salFlowService.addFlow(builder.build());            
         }
index 54382ea0560b561018005f9f86542c91dbd153be..d68ffa09fa571beb2d679ebe9250eeae841199ed 100644 (file)
@@ -2,26 +2,18 @@ package org.opendaylight.controller.frm.group
 
 import org.opendaylight.controller.frm.AbstractTransaction
 import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
 import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder
 
 class GroupTransaction extends AbstractTransaction {
     
@@ -39,6 +31,7 @@ class GroupTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new RemoveGroupInputBuilder(group);
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setGroupRef(new GroupRef(instanceId));
             _groupService.removeGroup(builder.build());            
         }
     }
@@ -50,6 +43,7 @@ class GroupTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new UpdateGroupInputBuilder();
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setGroupRef(new GroupRef(instanceId));
             val ufb = new UpdatedGroupBuilder(updatedGroup);
             builder.setUpdatedGroup((ufb.build()));
             val ofb = new OriginalGroupBuilder(originalGroup);
@@ -65,6 +59,7 @@ class GroupTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new AddGroupInputBuilder(group);
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setGroupRef(new GroupRef(instanceId));
             _groupService.addGroup(builder.build());            
         }
     }
index 3ed1f4073565ec64cac14d265a8c9a307181fa47..d64f2518a8287d761aadac55b87a95d4c7704d8b 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.met
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter
 import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef
 
 class MeterTransaction extends AbstractTransaction {
     
@@ -30,6 +31,7 @@ class MeterTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new RemoveMeterInputBuilder(meter);
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setMeterRef(new MeterRef(instanceId));
             _salMeterService.removeMeter(builder.build());            
         }
     }
@@ -41,6 +43,7 @@ class MeterTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new UpdateMeterInputBuilder();
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setMeterRef(new MeterRef(instanceId));
             val ufb = new UpdatedMeterBuilder(updatedMeter);
             builder.setUpdatedMeter((ufb.build()));
             val ofb = new OriginalMeterBuilder(originalMeter);
@@ -56,6 +59,7 @@ class MeterTransaction extends AbstractTransaction {
             val nodeInstanceId = instanceId.firstIdentifierOf(Node);
             val builder = new AddMeterInputBuilder(meter);
             builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setMeterRef(new MeterRef(instanceId));
             _salMeterService.addMeter(builder.build());            
         }
     }
index 8c874e2fe80a60f345f67fe091cde4a883fcc631..4442fbb3358001297434fee652faad30bb5712c4 100644 (file)
@@ -84,6 +84,10 @@ module opendaylight-group-types {
        description "Check chaining for loops and delete";
     }
     
+    typedef group-ref {
+        type instance-identifier;
+    }
+    
     grouping group {
         
         leaf group-type {
@@ -102,10 +106,6 @@ module opendaylight-group-types {
             type string; 
         }
         
-        leaf install {
-            type boolean; 
-        } 
-        
         leaf barrier {
             type boolean; 
         }       
index b380af22129c44f068bb02d50aa57283e8bfbac0..d84b2f08511f466848886cb75aa4f418341d5563 100644 (file)
@@ -112,6 +112,10 @@ module opendaylight-meter-types {
         }
     }
     
+    typedef meter-ref {
+        type instance-identifier;
+    }
+    
     grouping meter {
         
         leaf flags {
@@ -120,11 +124,12 @@ module opendaylight-meter-types {
         
         leaf meter-id {
             type meter-id;
-        }
+        }       
         
-        leaf install {
+        leaf barrier {
             type boolean; 
         }
+        
         leaf meter-name {
             type string;
         }
index 2bcd40522330901eaaf08824d68680cfdb48d381..a0beb2a84c936f51b83c20bd469b235563857949 100644 (file)
@@ -12,6 +12,10 @@ module opendaylight-flow-types {
         description "Initial revision of flow service";
     }
     
+    typedef flow-ref {
+        type instance-identifier;
+    }
+    
     typedef output-port-values {
         type enumeration {
             enum MAX {
index f0b7e97a15ff5b2a221ed9e15212b7516459de7f..bc05894da82637cfae12f61257fc79bdd2609500 100644 (file)
@@ -4,6 +4,7 @@ module opendaylight-port-types {
 
     import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
     import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+    import opendaylight-queue-types {prefix queue-types; revision-date "2013-09-25";}
     
     revision "2013-09-25" {
         description "Initial revision of Port Inventory model";
@@ -86,6 +87,13 @@ module opendaylight-port-types {
         uses flow-capable-port;
     }
     
+    grouping queues {
+       list queue {
+               key "queue-id";
+               uses queue-types:queue-packet;
+       }
+    }
+    
     grouping flow-capable-port {    
                 
         uses common-port;
@@ -126,6 +134,8 @@ module opendaylight-port-types {
             units "kbps";
             description "Max port bit rate in kbps";            
         }
+        
+        uses queues;
     }    
     
     grouping port-mod {
index 57a92378c095d6c020af990e750d90d85452d9fc..06f832e114dab818e3e888bbdbcf0113485b2983 100644 (file)
@@ -9,6 +9,11 @@ module opendaylight-queue-types {
         description "Initial revision of Queue Inventory model";
     }
     
+    typedef queue-id {
+            type yang:counter32;
+            description "id for the specific queue.";  
+        }
+    
     typedef queue-properties {
         type enumeration {
             enum min_rate;
@@ -37,8 +42,6 @@ module opendaylight-queue-types {
         }
            
     }
-    
-    
       
     grouping queue-prop-max-rate       {
                
@@ -54,7 +57,7 @@ module opendaylight-queue-types {
                
                
         leaf queue-id {
-            type uint32;
+            type queue-id;
             description "id for the specific queue.";  
         }
         
index 07678f57e1b429d8655fa3665d26eaa9c83f74d8..d6a31c30deeae87f619e157c39901ee3456f9e1a 100644 (file)
@@ -51,6 +51,9 @@ module sal-flow {
 
     rpc add-flow {
         input {
+            leaf flow-ref {
+                type types:flow-ref;
+            }
             uses node-flow;
             uses tr:transaction-aware;
         }
@@ -61,6 +64,9 @@ module sal-flow {
 
     rpc remove-flow {
         input {
+            leaf flow-ref {
+                type types:flow-ref;
+            }
             uses node-flow;
             uses tr:transaction-aware;
         }
@@ -71,6 +77,9 @@ module sal-flow {
 
     rpc update-flow {
         input {
+            leaf flow-ref {
+                type types:flow-ref;
+            }
             uses flow-update;
             uses tr:transaction-aware;
         }
@@ -80,15 +89,28 @@ module sal-flow {
     }
 
     notification flow-added {
+        leaf flow-ref {
+            type types:flow-ref;
+        }
         uses node-flow;
+        uses tr:transaction-aware;
     }
 
     notification flow-updated {
+        leaf flow-ref {
+            type types:flow-ref;
+        }
         uses node-flow;
+        uses tr:transaction-aware;
+        
     }
 
     notification flow-removed {
+        leaf flow-ref {
+            type types:flow-ref;
+        }
         uses node-flow;
+        uses tr:transaction-aware;
     }
     
     notification switch-flow-removed {
index 9106bca8a4826619f09062a3c3322b16e3551621..6cc1537ebc11c5d8f05a5921badbe79c300c8a12 100644 (file)
@@ -31,6 +31,9 @@ module sal-group {
 
     rpc add-group {
         input {
+            leaf group-ref {
+                type group-type:group-ref;
+            }
             uses node-group;
             uses tr:transaction-aware;
         }
@@ -41,6 +44,9 @@ module sal-group {
 
     rpc remove-group {
         input {
+            leaf group-ref {
+                type group-type:group-ref;
+            }
             uses node-group;
             uses tr:transaction-aware;
         }
@@ -51,6 +57,9 @@ module sal-group {
 
     rpc update-group {
         input {
+            leaf group-ref {
+                type group-type:group-ref;
+            }
             uses group-update;
             uses tr:transaction-aware;
         }
@@ -60,14 +69,26 @@ module sal-group {
     } 
 
     notification group-added {
+        leaf group-ref {
+            type group-type:group-ref;
+        }
         uses node-group;
+        uses tr:transaction-aware;
     }
 
     notification group-updated {
+        leaf group-ref {
+            type group-type:group-ref;
+        }
         uses node-group;
+        uses tr:transaction-aware;
     }
 
     notification group-removed {
+        leaf group-ref {
+            type group-type:group-ref;
+        }
         uses node-group;
+        uses tr:transaction-aware;
     }    
 }
\ No newline at end of file
index c187181e5e89099cc4720031cd3fa888629d69a2..6205fed529d85a849ea77bdf5c6ff87b0b5c1331 100644 (file)
@@ -31,6 +31,9 @@ module sal-meter {
 
     rpc add-meter {
         input {
+            leaf meter-ref {
+                type meter-type:meter-ref;
+            }
             uses node-meter;
             uses tr:transaction-aware;            
         }
@@ -41,6 +44,10 @@ module sal-meter {
 
     rpc remove-meter {
         input {
+            leaf meter-ref {
+                type meter-type:meter-ref;
+            }
+            
             uses node-meter;
             uses tr:transaction-aware;            
         }
@@ -51,6 +58,10 @@ module sal-meter {
 
     rpc update-meter {
         input {
+            leaf meter-ref {
+                type meter-type:meter-ref;
+            }
+            
             uses meter-update;
             uses tr:transaction-aware;            
         }
@@ -60,14 +71,26 @@ module sal-meter {
     }
         
     notification meter-added {
+        leaf meter-ref {
+            type meter-type:meter-ref;
+        }
         uses node-meter;
+        uses tr:transaction-aware;
     }
 
     notification meter-updated {
+        leaf meter-ref {
+            type meter-type:meter-ref;
+        }
         uses node-meter;
+        uses tr:transaction-aware;
     }
 
     notification meter-removed {
+        leaf meter-ref {
+            type meter-type:meter-ref;
+        }
         uses node-meter;
+        uses tr:transaction-aware;
     }
 }
\ No newline at end of file
index d49675ad39366bb3e8c9b3a5a191f2a677683ce7..6795e6fd67a8090e525546deb18658f6dc5930d3 100644 (file)
@@ -43,9 +43,14 @@ module sal-port {
         output {
             uses port-type:flow-capable-port;
         }
-    }  
+    }
+    
+    notification port-updated {
+        uses port-update;
+        uses tr:transaction-aware;
+    }
     
     notification port-removed {
-        uses node-port;
+        uses node-port;       
     }
 }
\ No newline at end of file
index 3bd37bcf3387ae4500f45d372f6a6454c949526f..7bbcca3a1258a36997449ccfc17c3858bb0d362f 100644 (file)
@@ -115,7 +115,7 @@ module opendaylight-flow-statistics {
         }
        }    
        
-    // RPC calls to fetch flow statistics
+    // RPC calls to fetch aggregate flow statistics
     rpc get-aggregate-flow-statistics-from-flow-table-for-all-flows {
        description "Fetch aggregate statistics for all the flows present in the specific flow table of the switch"; 
         input {
@@ -150,76 +150,4 @@ module opendaylight-flow-statistics {
                uses stat-types:aggregate-flow-statistics;
                uses tr:transaction-aware;
     }
-       
-       //Keeping flow statistics RPC call for backward compatibility for sal-compatibility layer --START
-       rpc get-flow-statistics {
-        input {
-            uses inv:node-context-ref;
-            uses flow-types:flow;
-        }
-        output {
-            uses flow-types:flow-statistics;
-        }
-    }
-
-    rpc get-all-flow-statistics {
-        input {
-            uses inv:node-context-ref;
-        }
-        output {
-            list flow-statistics {
-                uses flow-types:flow-statistics;
-            }
-        }
-    }
-
-    notification flow-statistics-updated {
-        uses flow-types:flow-statistics;
-    }
-       
-       //Keeping flow statistics RPC call for backward compatibility for sal-compatibility layer --END
-       
-       //RPC call to fetch node connector statistics
-    rpc get-node-connector-statistics {
-        input {
-            uses inv:node-context-ref;
-            leaf node-connector {
-                type inv:node-connector-ref;
-            }
-        }
-        output {
-            uses stat-types:node-connector-statistics;
-        }
-    }
-
-    rpc get-all-node-connector-statistics {
-        input {
-            uses inv:node-context-ref;
-        }
-        output {
-            list node-connector-statistics {
-                uses stat-types:node-connector-statistics;
-            }
-        }
-    }
-
-    rpc get-flow-table-statistics {
-        input {
-            uses inv:node-context-ref;
-        }
-        output {
-            uses flow-types:flow-table-statistics;
-        }
-    }
-
-    notification flow-table-statistics-updated {
-        leaf flow-table {
-            type flow:flow-table-ref;
-        }
-        uses flow-types:flow-table-statistics;
-    }
-
-    notification node-connector-statistics-updated {
-        uses stat-types:node-connector-statistics;
-    }
 }
index ebc6ead25e227cfce37cf6a216304fee3e083504..5640858d516c341c9dd167fe43fe321a00fc3220 100644 (file)
@@ -18,11 +18,11 @@ module opendaylight-group-statistics {
        grouping group-statistics {
         container group-statistics {
             //config "false";
-            uses group-types:group-statistics-reply;
+            uses group-types:group-statistics;
         }
        }    
     
-    augment "/inv:nodes/inv:node" {
+    augment "/inv:nodes/inv:node/group-types:group" {
         ext:augment-identifier "node-group-statistics";
         uses group-statistics;
     }
@@ -30,11 +30,11 @@ module opendaylight-group-statistics {
        grouping group-desc {
         container group-desc {
             //config "false";
-            uses group-types:group-desc-stats-reply;
+            uses group-types:group;
         }
        }
     
-    augment "/inv:nodes/inv:node" {
+    augment "/inv:nodes/inv:node/group-types:group" {
         ext:augment-identifier "node-group-desc-stats";
         uses group-desc;
     }
index e3b2a3fc6477430d676e0542b5db91667a704ba5..b2cf78b61de21902c31c6ae2b91d2112ca0d41de 100644 (file)
@@ -4,6 +4,7 @@ module opendaylight-meter-statistics {
 
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
     import opendaylight-meter-types {prefix meter-types;revision-date "2013-09-18";}
     import flow-capable-transaction {prefix tr;}
     
@@ -15,19 +16,19 @@ module opendaylight-meter-statistics {
         description "Initial revision of meter statistics service";
     }
 
-    augment "/inv:nodes/inv:node" {
+    augment "/inv:nodes/inv:node/flow-node:meter" {
         ext:augment-identifier "node-meter-statistics";
         container meter-statistics {
             //config "false";
-            uses meter-types:meter-statistics-reply;
+            uses meter-types:meter-statistics;
         }
     }
 
-    augment "/inv:nodes/inv:node" {
+    augment "/inv:nodes/inv:node/flow-node:meter" {
         ext:augment-identifier "node-meter-config-stats";
         container meter-config-stats {
             //config "false";
-            uses meter-types:meter-config-stats-reply;
+            uses meter-types:meter;
         }
     }
     
index 0cb6a60cfe0e5dd23d918be3879859c848ab55dc..787a4e6aa0ef2fe3b26931877aa56a608450eda8 100644 (file)
@@ -30,19 +30,19 @@ module opendaylight-port-statistics {
        }    
        
     // RPC calls
-    rpc get-all-ports-statistics {
-       description "Get statistics for all the ports from the node";
+    rpc get-all-node-connectors-statistics {
+       description "Get statistics for all node connectors from the node";
         input {
             uses inv:node-context-ref;
         }
         output {
-            uses stat-types:node-connector-statistics;
+                       uses node-connector-statistics-and-port-number-map;
             uses tr:transaction-aware;
         }
     }
     
-    rpc get-port-statistics {
-       description "Get statistics for given port from the node";
+    rpc get-node-connector-statistics {
+       description "Get statistics for given node connector from the node";
        input {
                uses inv:node-context-ref;
                leaf node-connector-id {
@@ -55,9 +55,9 @@ module opendaylight-port-statistics {
        }
     }
     
-    //Notification for port statistics update
+    //Notification for node connector statistics update
        grouping node-connector-statistics-and-port-number-map {
-               description "List of flow and statistics map";
+               description "List of map - node connectors and their statistics";
                list node-connector-statistics-and-port-number-map {
                        key "node-connector-id";
                        leaf node-connector-id {
@@ -67,7 +67,7 @@ module opendaylight-port-statistics {
                }
        }
 
-       notification port-statistics-update {
+       notification node-connector-statistics-update {
         leaf moreReplies {
             type boolean;
         }
diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/queue-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/queue-statistics.yang
new file mode 100644 (file)
index 0000000..7665ef7
--- /dev/null
@@ -0,0 +1,101 @@
+module opendaylight-queue-statistics {
+    namespace "urn:opendaylight:queue:statistics";
+    prefix queuestat;
+
+       import flow-capable-transaction {prefix tr;}
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}   
+    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
+    import opendaylight-queue-types {prefix queue-types;revision-date "2013-09-25";}
+    import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
+
+    contact
+        "Anilkumar Vishnoi
+        Email: avishnoi@in.ibm.com";
+
+    revision "2013-12-16" {
+        description "Initial revision of queue statistics model";
+    }
+    
+    //Augment queue statistics data to the flow-capable-node-connector
+       augment "/inv:nodes/inv:node/inv:node-connector/flow-node:queue" {
+        ext:augment-identifier "flow-capable-node-connector-queue-statistics-data";
+        uses flow-capable-node-connector-queue-statistics;
+    }
+       
+       grouping flow-capable-node-connector-queue-statistics {
+        container flow-capable-node-connector-queue-statistics {
+            //config "false";
+            uses stat-types:generic-queue-statistics;
+        }
+       }    
+       
+       //RPC calls to fetch queue statistics
+    grouping queue-id-and-statistics-map {
+       list queue-id-and-statistics-map {
+               key "queue-id node-connector-id";
+               leaf queue-id {
+                       type queue-types:queue-id;
+               }
+               leaf node-connector-id {
+                       type inv:node-connector-id;
+               }
+               
+            uses stat-types:generic-queue-statistics;
+       }
+    }
+    
+    rpc get-all-queues-statistics-from-all-ports {
+       description "Get statistics for all the queues attached to all the ports from the node";
+        input {
+            uses inv:node-context-ref;
+        }
+        output {
+            uses queue-id-and-statistics-map;
+            uses tr:transaction-aware;
+        }
+    }
+    
+    rpc get-all-queues-statistics-from-given-port {
+       description "Get statistics for all queues for given port of the node";
+       input {
+               uses inv:node-context-ref;
+               leaf node-connector-id {
+                       type inv:node-connector-id;
+               }
+       }
+       output {
+            uses queue-id-and-statistics-map;
+            uses tr:transaction-aware;
+       }
+    }
+    
+    rpc get-queue-statistics-from-given-port {
+       description "Get statistics for given queues from given port of the node";
+       input {
+               uses inv:node-context-ref;
+               leaf node-connector-id {
+                       type inv:node-connector-id;
+               }
+               leaf queue-id {
+                       type queue-types:queue-id;
+               }
+       }
+       output {
+            uses queue-id-and-statistics-map;
+            uses tr:transaction-aware;
+       }
+    }
+
+    //Notification for port statistics update
+
+       notification queue-statistics-update {
+        leaf moreReplies {
+            type boolean;
+        }
+        uses inv:node;
+               uses queue-id-and-statistics-map;
+        uses tr:transaction-aware;
+    }
+}
index 6d5bec1280ffde4cee89690032ec3b40b6fc318b..7bde486e91da8c4228086a9a6e1e08f8637b8707 100644 (file)
@@ -7,7 +7,18 @@ module opendaylight-statistics-types {
     
     revision "2013-09-25" {
         description "Initial revision of flow service";
-    }    
+    }
+    
+    grouping duration {
+        container duration {
+            leaf second {
+                type yang:counter32;
+            }
+            leaf nanosecond {
+                type yang:counter32;
+            }
+        }
+    }
 
     grouping node-connector-statistics {
        container packets {
@@ -50,15 +61,7 @@ module opendaylight-statistics-types {
         leaf collision-count {
             type uint64;
         }
-        
-        container duration {
-            leaf second {
-                type yang:counter32;
-            }
-            leaf nanosecond {
-                type yang:counter32;
-            }
-        }
+        uses duration;
     }
     
     grouping generic-statistics {
@@ -70,16 +73,8 @@ module opendaylight-statistics-types {
         leaf byte-count {
             type yang:counter64;
         }
-
-        container duration {
-            leaf second {
-                type yang:counter64;
-            }
-            leaf nanosecond {
-                type yang:counter64;
-            }
-        }
-    }
+       uses duration;
+       }
     
     grouping generic-table-statistics {
        description "Generic grouping holding generic statistics related to switch table";
@@ -108,4 +103,20 @@ module opendaylight-statistics-types {
         }
     }
     
+    grouping generic-queue-statistics {
+       description "Generic statistics of switch port attached queues.";
+       leaf transmitted-bytes {
+                       type yang:counter64;
+       }
+       
+       leaf transmitted-packets {
+                       type yang:counter64;
+       }
+       
+       leaf transmission-errors {
+                       type yang:counter64;
+       }
+               uses duration;          
+    }
+    
 }
\ No newline at end of file
index 6f1b2c0c10629053d96589e581d221be53a184a5..0d6523bc0bbb38dd059e9c978be147cab7a4b7e8 100644 (file)
@@ -43,7 +43,7 @@
         <module>sal-rest-connector</module>
         <module>sal-netconf-connector</module>
 
-        <module>zeromq-routingtable/implementation</module>
+        <module>remoterpc-routingtable/implementation</module>
         <module>sal-remoterpc-connector/implementation</module>
         <!-- Clustered Data Store -->
         <module>clustered-data-store/implementation</module>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
             </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>1.8</version>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>${project.build.directory}/generated-sources/config</source>
+                                <source>${project.build.directory}/generated-sources/sal</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
similarity index 98%
rename from opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml
rename to opendaylight/md-sal/remoterpc-routingtable/implementation/pom.xml
index 2926786849f82999903565f3388e49481b4ab637..a788baf4c0642a1ebb26b390ba415a338a45a033 100644 (file)
@@ -15,7 +15,7 @@
         <tag>HEAD</tag>
     </scm>
 
-    <artifactId>zeromq-routingtable.implementation</artifactId>
+    <artifactId>remoterpc-routingtable.implementation</artifactId>
     <version>0.4.1-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
@@ -30,6 +30,7 @@ import javax.transaction.RollbackException;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 
@@ -254,6 +255,23 @@ public class RoutingTableImpl<I, R> implements RoutingTable<I, R>, ICacheUpdateA
         return this.routingTableCache;
     }
 
+    /**
+     * This is used from integration test NP rest API to check out the result of the
+     * cache population
+     * <Note> For testing purpose only-- use it wisely</Note>
+     * @return
+     */
+    public String dumpRoutingTableCache(){
+       Set<Map.Entry<I, R>> cacheEntrySet = this.routingTableCache.entrySet();
+       StringBuilder sb = new StringBuilder();
+       for(Map.Entry<I,R> entry:cacheEntrySet){
+           sb.append("Key:").append(entry.getKey()).append("---->Value:")
+                   .append((entry.getValue() != null)?entry.getValue():"null")
+                   .append("\n");
+       }
+       return sb.toString();
+    }
+
     /**
      * Invoked when a new entry is available in the cache, the key is only
      * provided, the value will come as an entryUpdate invocation
similarity index 98%
rename from opendaylight/md-sal/zeromq-routingtable/integrationtest/pom.xml
rename to opendaylight/md-sal/remoterpc-routingtable/integrationtest/pom.xml
index 308d5a9316d621e2b235cd1b356b121475fe311d..bdc4569f31ac6869276e1cc7075ba7ded3844fc6 100644 (file)
     <tag>HEAD</tag>
   </scm>
 
-  <artifactId>zeromq-routingtable.integrationtest</artifactId>
+  <artifactId>remoterpc-routingtable.integrationtest</artifactId>
   <version>0.4.1-SNAPSHOT</version>
 
   <dependencies>
     <dependency>
         <groupId>org.opendaylight.controller</groupId>
-        <artifactId>zeromq-routingtable.implementation</artifactId>
+        <artifactId>remoterpc-routingtable.implementation</artifactId>
         <version>0.4.1-SNAPSHOT</version>
     </dependency>
     <dependency>
@@ -120,7 +120,7 @@ public class
                         .versionAsInProject(),
                 mavenBundle(ODL, "sal-connector-api")
                         .versionAsInProject(),
-                mavenBundle(ODL, "zeromq-routingtable.implementation")
+                mavenBundle(ODL, "remoterpc-routingtable.implementation")
                         .versionAsInProject(),
 
                 mavenBundle("org.jboss.spec.javax.transaction",
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/pom.xml b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/pom.xml
new file mode 100644 (file)
index 0000000..35b2a4b
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>sal-remoterpc-connector-test-parent</artifactId>
+    <groupId>org.opendaylight.controller.tests</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>remoterpc-routingtable-nb-it</artifactId>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package>
+             org.opendaylight.controller.tests.zmqroutingtable.rest
+            </Export-Package>
+            <Import-Package>
+              com.sun.jersey.spi.container.servlet,
+              org.codehaus.jackson.annotate,
+              javax.ws.rs,
+              javax.ws.rs.core,
+              javax.xml.bind,
+              javax.xml.bind.annotation,
+              org.slf4j,
+              org.apache.catalina.filters,
+              org.codehaus.jackson.jaxrs,
+              org.opendaylight.controller.sal.utils,
+              org.opendaylight.yangtools.yang.common,
+              org.opendaylight.controller.sal.connector.api,
+              org.opendaylight.controller.sal.connector.remoterpc.api,
+              org.opendaylight.controller.sal.connector.remoterpc.impl,
+              org.osgi.framework,
+              com.google.common.base,
+              org.opendaylight.yangtools.yang.data.api,
+              !org.codehaus.enunciate.jaxrs
+
+            </Import-Package>
+            <Web-ContextPath>/controller/nb/v2/zmqnbrt</Web-ContextPath>
+            <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
+          </instructions>
+          <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>5.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>remoterpc-routingtable.implementation</artifactId>
+          <version>0.4.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>com.google.guava</groupId>
+          <artifactId>guava</artifactId>
+      </dependency>
+  </dependencies>
+
+ </project>
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/RouteIdentifierImpl.java b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/RouteIdentifierImpl.java
new file mode 100644 (file)
index 0000000..6b7ee26
--- /dev/null
@@ -0,0 +1,69 @@
+package org.opendaylight.controller.tests.zmqroutingtable.rest;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.io.Serializable;
+import java.net.URI;
+
+/**
+ * @author: syedbahm
+ * Date: 12/10/13
+ */
+public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier, Serializable {
+
+    private final URI namespace;
+    private final QName QNAME;
+    private final QName instance;
+
+    public RouteIdentifierImpl() {
+        namespace = URI.create("http://cisco.com/example");
+        QNAME = new QName(namespace, "global");
+        instance = new QName(URI.create("127.0.0.1"), "local");
+    }
+
+    public RouteIdentifierImpl(String url,String instanceIP){
+        namespace = URI.create(url);
+        QNAME = new QName(namespace,"global");
+        instance =  new QName(URI.create(instanceIP), "local");
+    }
+
+
+    @Override
+    public QName getContext() {
+        return QNAME;
+    }
+
+    @Override
+    public QName getType() {
+        return QNAME;
+    }
+
+    @Override
+    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
+        return InstanceIdentifier.of(instance);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        RouteIdentifierImpl that = (RouteIdentifierImpl) o;
+
+        if (!QNAME.equals(that.QNAME)) return false;
+        if (!instance.equals(that.instance)) return false;
+        if (!namespace.equals(that.namespace)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = namespace.hashCode();
+        result = 31 * result + QNAME.hashCode();
+        result = 31 * result + instance.hashCode();
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/Router.java b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqroutingtable/rest/Router.java
new file mode 100644 (file)
index 0000000..c426927
--- /dev/null
@@ -0,0 +1,157 @@
+package org.opendaylight.controller.tests.zmqroutingtable.rest;
+
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
+import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
+import org.opendaylight.controller.sal.connector.remoterpc.impl.RoutingTableImpl;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleReference;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.io.Serializable;
+import java.net.URI;
+
+@Path("router")
+public class Router implements Serializable {
+  private Logger _logger = LoggerFactory.getLogger(Router.class);
+  private final URI namespace = URI.create("http://cisco.com/example");
+  private final QName QNAME = new QName(namespace, "heartbeat");
+
+
+  @GET
+  @Path("/hello")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String hello() {
+    return "Hello";
+  }
+
+
+
+
+    @GET
+    @Path("/rtadd")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String addToRoutingTable(@QueryParam("nsp") String namespace,@QueryParam("inst") String instance,@QueryParam("port") String port) {
+        _logger.info("Invoking adding an entry in routing table");
+
+        BundleContext ctx = getBundleContext();
+        ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
+        if (routingTableServiceReference == null) {
+            _logger.debug("Could not get routing table impl reference");
+            return "Could not get routingtable referen ";
+        }
+        RoutingTableImpl routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
+        if (routingTable == null) {
+            _logger.info("Could not get routing table service");
+            return "Could not get routing table service";
+        }
+
+
+        RouteIdentifierImpl rii = new RouteIdentifierImpl(namespace,instance);
+        try {
+            routingTable.addGlobalRoute(rii, instance+":"+ port);
+        } catch (RoutingTableException e) {
+            _logger.error("error in adding routing identifier" + e.getMessage());
+
+        } catch (SystemException e) {
+            _logger.error("error in adding routing identifier" + e.getMessage());
+        }
+
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("Result of adding route:").append("\n")
+                     .append(routingTable.dumpRoutingTableCache());
+        return stringBuilder.toString();
+    }
+
+  @GET
+  @Path("/rtdelete")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String invokeDeleteRoutingTable(@QueryParam("nsp") String namespace,@QueryParam("inst") String instance) {
+    _logger.info("Invoking delete an entry in routing table");
+
+    BundleContext ctx = getBundleContext();
+    ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
+    if (routingTableServiceReference == null) {
+      _logger.debug("Could not get routing table impl reference");
+      return "Could not get routingtable referen ";
+    }
+    RoutingTableImpl routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
+    if (routingTable == null) {
+      _logger.info("Could not get routing table service");
+      return "Could not get routing table service";
+    }
+
+
+    RouteIdentifierImpl rii = new RouteIdentifierImpl(namespace,instance);
+    try {
+      routingTable.removeGlobalRoute(rii);
+    } catch (RoutingTableException e) {
+      _logger.error("error in adding routing identifier" + e.getMessage());
+
+    } catch (SystemException e) {
+      _logger.error("error in adding routing identifier" + e.getMessage());
+    }
+
+
+    StringBuilder stringBuilder = new StringBuilder();
+    stringBuilder.append("Result of deleting route:").append("\n")
+              .append(routingTable.dumpRoutingTableCache());
+
+    return stringBuilder.toString();
+  }
+
+    @GET
+    @Path("/routingtable")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String invokeGetRoutingTable() {
+        _logger.info("Invoking getting of routing table");
+
+        BundleContext ctx = getBundleContext();
+        ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
+        if (routingTableServiceReference == null) {
+            _logger.debug("Could not get routing table impl reference");
+            return "Could not get routingtable referen ";
+        }
+        RoutingTableImpl routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
+        if (routingTable == null) {
+            _logger.info("Could not get routing table service");
+            return "Could not get routing table service";
+        }
+
+
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("Result of getting routetable:").append("\n")
+                .append(routingTable.dumpRoutingTableCache());
+
+        return stringBuilder.toString();
+    }
+
+
+
+  private BundleContext getBundleContext() {
+    ClassLoader tlcl = Thread.currentThread().getContextClassLoader();
+    Bundle bundle = null;
+
+    if (tlcl instanceof BundleReference) {
+      bundle = ((BundleReference) tlcl).getBundle();
+    } else {
+      _logger.info("Unable to determine the bundle context based on " +
+          "thread context classloader.");
+      bundle = FrameworkUtil.getBundle(this.getClass());
+    }
+    return (bundle == null ? null : bundle.getBundleContext());
+  }
+
+
+
+}
diff --git a/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml b/opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..2a0f3f3
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+        version="3.0">
+  <servlet>
+    <servlet-name>JAXRSZmqRT</servlet-name>
+    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+    <init-param>
+      <param-name>javax.ws.rs.Application</param-name>
+      <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>JAXRSZmqRT</servlet-name>
+    <url-pattern>/*</url-pattern>
+  </servlet-mapping>
+
+
+
+        <security-constraint>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</url-pattern>
+            <http-method>POST</http-method>
+            <http-method>GET</http-method>
+            <http-method>PUT</http-method>
+            <http-method>PATCH</http-method>
+            <http-method>DELETE</http-method>
+            <http-method>HEAD</http-method>
+          </web-resource-collection>
+          <auth-constraint>
+            <role-name>System-Admin</role-name>
+            <role-name>Network-Admin</role-name>
+            <role-name>Network-Operator</role-name>
+            <role-name>Container-User</role-name>
+          </auth-constraint>
+        </security-constraint>
+
+        <security-role>
+                <role-name>System-Admin</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Network-Admin</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Network-Operator</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Container-User</role-name>
+        </security-role>
+
+        <login-config>
+                <auth-method>BASIC</auth-method>
+                <realm-name>opendaylight</realm-name>
+        </login-config>
+</web-app>
diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcAvailabilityListener.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcAvailabilityListener.java
new file mode 100644 (file)
index 0000000..e25b939
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.api;
+
+public interface RpcAvailabilityListener {
+
+}
index 48c33ad0fc704e162c8dcae4f56be23ffb87ee1d..c46b0dd6b4c529d00e0fae55f862f6a0229e701b 100644 (file)
@@ -36,7 +36,7 @@ public final class BindingBrokerImplModule extends org.opendaylight.controller.c
 \r
     @Override\r
     public java.lang.AutoCloseable createInstance() {\r
-        BindingAwareBrokerImpl broker = new BindingAwareBrokerImpl(getBundleContext());\r
+        BindingAwareBrokerImpl broker = new BindingAwareBrokerImpl(getIdentifier().getInstanceName(),getBundleContext());\r
         broker.setDataBroker(getDataBrokerDependency());\r
         broker.setNotifyBroker(getNotificationServiceDependency());\r
         broker.start();\r
index 74b6ad8a235fabbbee093063b25dc40cefb37081..01dc6b8c0cd6162be049fe44d6806524da820f7a 100644 (file)
@@ -16,7 +16,7 @@ import java.util.concurrent.ScheduledExecutorService;
 import org.opendaylight.controller.config.yang.md.sal.binding.statistics.DataBrokerRuntimeMXBeanImpl;\r
 import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter;\r
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;\r
-import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;\r
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;\r
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;\r
 import org.opendaylight.controller.sal.core.api.Broker;\r
 import org.opendaylight.controller.sal.core.api.data.DataProviderService;\r
@@ -63,7 +63,7 @@ public final class DataBrokerImplModule extends
         BindingIndependentMappingService mappingService = getMappingServiceDependency();\r
         \r
         if (domBroker != null && mappingService != null) {\r
-            BindingIndependentDataServiceConnector runtimeMapping = new BindingIndependentDataServiceConnector();\r
+            BindingIndependentConnector runtimeMapping = new BindingIndependentConnector();\r
             runtimeMapping.setMappingService(mappingService);\r
             runtimeMapping.setBaDataService(dataBindingBroker);\r
             domBroker.registerProvider(runtimeMapping, getBundleContext());\r
index 1bf15c182f5f93196fe0c3d27fc0438295df2812..99b7ed8acf777a61d4a73c37cbf80500241274ba 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
 import javassist.ClassPool;
 
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
 import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
 import org.osgi.framework.BundleContext;
 
@@ -50,8 +51,7 @@ public final class RuntimeMappingModule extends
     @Override
     public java.lang.AutoCloseable createInstance() {
         RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl();
-        ClassPool pool = new ClassPool(); // Should be default singleton
-        service.setPool(pool);
+        service.setPool(SingletonHolder.CLASS_POOL);
         service.start(getBundleContext());
         return service;
     }
index 6672d953a2c29243d525de87f07c4c014c6bdf97..7789a06fe8c734f61215805d3e5b18bd558c4916 100644 (file)
@@ -86,7 +86,7 @@ public interface RuntimeCodeGenerator {
      * @return Instance of RpcService of provided serviceType which implements
      *         also {@link RpcRouter}<T> and {@link DelegateProxy}
      */
-    <T extends RpcService> RpcRouter<T> getRouterFor(Class<T> serviceType) throws IllegalArgumentException;
+    <T extends RpcService> RpcRouter<T> getRouterFor(Class<T> serviceType,String name) throws IllegalArgumentException;
 
     NotificationInvokerFactory getInvokerFactory();
 }
index f0f92da18e5c3b2235eb77a9cf3d0e32b8df371c..dff0d215b2ac14dece9c9139d677db4de3d74f65 100644 (file)
@@ -76,7 +76,6 @@ class RuntimeCodeHelper {
         if (field == null) throw new UnsupportedOperationException(
             "Unable to set routing table. Table field does not exists");
         field.set(target,routingTable);
-        
     }
 
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java
new file mode 100644 (file)
index 0000000..8b2db8b
--- /dev/null
@@ -0,0 +1,168 @@
+package org.opendaylight.controller.sal.binding.codegen.impl;
+
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.spi.RpcRouter;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.HashMap;
+
+import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.RpcImplementation;
+import org.opendaylight.controller.md.sal.common.api.routing.MutableRoutingTable;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public class RpcRouterCodegenInstance<T extends RpcService> implements //
+        RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RpcRouterCodegenInstance.class);
+
+    private T defaultService;
+
+    private final Class<T> serviceType;
+
+    private final T invocationProxy;
+
+    private final Set<Class<? extends BaseIdentity>> contexts;
+
+    private final ListenerRegistry<RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> listeners;
+
+    private final Map<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, T>> routingTables;
+
+    private final String name;
+
+    @SuppressWarnings("unchecked")
+    public RpcRouterCodegenInstance(String name,Class<T> type, T routerImpl, Set<Class<? extends BaseIdentity>> contexts,
+            Set<Class<? extends DataContainer>> inputs) {
+        this.name = name;
+        this.listeners = ListenerRegistry.create();
+        this.serviceType = type;
+        this.invocationProxy = routerImpl;
+        this.contexts = ImmutableSet.copyOf(contexts);
+        Map<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, T>> mutableRoutingTables = new HashMap<>();
+        for (Class<? extends BaseIdentity> ctx : contexts) {
+            RpcRoutingTableImpl<? extends BaseIdentity, T> table = new RpcRoutingTableImpl<>(name,ctx,type);
+            
+            @SuppressWarnings("rawtypes")
+            Map invokerView = table.getRoutes();
+            
+            setRoutingTable((RpcService) invocationProxy, ctx, invokerView);
+            mutableRoutingTables.put(ctx, table);
+            table.registerRouteChangeListener(this);
+        }
+        this.routingTables = ImmutableMap.copyOf(mutableRoutingTables);
+    }
+
+    @Override
+    public Class<T> getServiceType() {
+        return serviceType;
+    }
+
+    @Override
+    public T getInvocationProxy() {
+        return invocationProxy;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <C extends BaseIdentity> RpcRoutingTable<C, T> getRoutingTable(Class<C> routeContext) {
+        return (RpcRoutingTable<C, T>) routingTables.get(routeContext);
+    }
+
+    @Override
+    public T getDefaultService() {
+        return defaultService;
+    }
+
+    @Override
+    public Set<Class<? extends BaseIdentity>> getContexts() {
+        return contexts;
+    }
+
+    @Override
+    public <L extends RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
+            L listener) {
+        return listeners.registerWithType(listener);
+    }
+
+    @Override
+    public void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
+        for (ListenerRegistration<RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> listener : listeners) {
+            try {
+                listener.getInstance().onRouteChange(change);
+            } catch (Exception e) {
+                LOG.error("Error occured during invoker listener {}", listener.getInstance(), e);
+            }
+        }
+    }
+
+    @Override
+    public T getService(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+        return routingTables.get(context).getRoute(path);
+    }
+
+    @Override
+    public RoutedRpcRegistration<T> addRoutedRpcImplementation(T service) {
+        return new RoutedRpcRegistrationImpl(service);
+    }
+
+    @Override
+    public RpcRegistration<T> registerDefaultService(T service) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    private class RoutedRpcRegistrationImpl extends AbstractObjectRegistration<T> implements RoutedRpcRegistration<T> {
+
+        public RoutedRpcRegistrationImpl(T instance) {
+            super(instance);
+        }
+
+        @Override
+        public Class<T> getServiceType() {
+            return serviceType;
+        }
+
+        @Override
+        public void registerPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+            routingTables.get(context).updateRoute(path, getInstance());
+        }
+
+        @Override
+        public void unregisterPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+            routingTables.get(context).removeRoute(path, getInstance());
+
+        }
+
+        @Override
+        public void registerInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance) {
+            registerPath(context, instance);
+        }
+
+        @Override
+        public void unregisterInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance) {
+            unregisterPath(context, instance);
+        }
+
+        @Override
+        protected void removeRegistration() {
+
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.xtend
deleted file mode 100644 (file)
index b6dcde1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.opendaylight.controller.sal.binding.codegen.impl
-
-import org.opendaylight.yangtools.yang.binding.RpcService
-import org.opendaylight.controller.sal.binding.spi.RpcRouter
-import org.opendaylight.yangtools.yang.binding.BaseIdentity
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*
-import java.util.Set
-import java.util.HashMap
-import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable
-import org.opendaylight.yangtools.yang.binding.DataContainer
-import org.opendaylight.yangtools.yang.binding.RpcImplementation
-
-class RpcRouterCodegenInstance<T extends RpcService> implements RpcRouter<T> {
-
-    @Property
-    val T invocationProxy
-
-    @Property
-    val RpcImplementation invokerDelegate;
-
-    @Property
-    val Class<T> serviceType
-
-    @Property
-    val Set<Class<? extends BaseIdentity>> contexts
-
-    @Property
-    val Set<Class<? extends DataContainer>> supportedInputs;
-
-    val routingTables = new HashMap<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, ? extends RpcService>>;
-
-    @Property
-    var T defaultService
-
-    new(Class<T> type, T routerImpl, Set<Class<? extends BaseIdentity>> contexts,
-        Set<Class<? extends DataContainer>> inputs) {
-        _serviceType = type
-        _invocationProxy = routerImpl
-        _invokerDelegate = routerImpl as RpcImplementation
-        _contexts = contexts
-        _supportedInputs = inputs;
-
-        for (ctx : contexts) {
-            val table = XtendHelper.createRoutingTable(ctx)
-            invocationProxy.setRoutingTable(ctx, table.routes);
-            routingTables.put(ctx, table);
-        }
-    }
-
-    override <C extends BaseIdentity> getRoutingTable(Class<C> table) {
-        routingTables.get(table) as RpcRoutingTable<C,T>
-    }
-
-    override getService(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
-        val table = getRoutingTable(context);
-        return table.getRoute(path);
-    }
-
-    override <T extends DataContainer> invoke(Class<T> type, T input) {
-        return invokerDelegate.invoke(type, input);
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRoutingTableImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRoutingTableImpl.java
new file mode 100644 (file)
index 0000000..808358f
--- /dev/null
@@ -0,0 +1,148 @@
+package org.opendaylight.controller.sal.binding.codegen.impl;
+
+import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Mutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class RpcRoutingTableImpl<C extends BaseIdentity, S extends RpcService> //
+implements //
+        Mutable, //
+        RpcRoutingTable<C, S>, //
+        RouteChangePublisher<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(RpcRoutingTableImpl.class);
+    private final String routerName;
+    private final Class<S> serviceType;
+
+    private final Class<C> contextType;
+    private final ConcurrentMap<InstanceIdentifier<?>, S> routes;
+    private final Map<InstanceIdentifier<?>, S> unmodifiableRoutes;
+
+    private RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> listener;
+    private S defaultRoute;
+    
+    public RpcRoutingTableImpl(String routerName,Class<C> contextType, Class<S> serviceType) {
+        super();
+        this.routerName = routerName;
+        this.serviceType = serviceType;
+        this.contextType = contextType;
+        this.routes = new ConcurrentHashMap<>();
+        this.unmodifiableRoutes = Collections.unmodifiableMap(routes);
+    }
+
+    @Override
+    public void setDefaultRoute(S target) {
+        defaultRoute = target;
+    }
+
+    @Override
+    public S getDefaultRoute() {
+        return defaultRoute;
+    }
+
+    @Override
+    public <L extends RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
+            L listener) {
+        return (ListenerRegistration<L>) new SingletonListenerRegistration<L>(listener);
+    }
+        
+    @Override
+    public Class<C> getIdentifier() {
+        return contextType;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void updateRoute(InstanceIdentifier<?> path, S service) {
+        S previous = this.routes.put(path, service);
+        
+        LOGGER.debug("Route {} updated to {} in routing table {}",path,service,this);
+        @SuppressWarnings("rawtypes")
+        RouteChangeListener listenerCapture = listener;
+        if (previous == null && listenerCapture != null) {
+            listenerCapture.onRouteChange(RoutingUtils.announcementChange(contextType, path));
+        }
+    }
+
+    
+    @Override
+    @SuppressWarnings("unchecked")
+    public void removeRoute(InstanceIdentifier<?> path) {
+        S previous = this.routes.remove(path);
+        LOGGER.debug("Route {} to {} removed in routing table {}",path,previous,this);
+        @SuppressWarnings("rawtypes")
+        RouteChangeListener listenerCapture = listener;
+        if (previous != null && listenerCapture != null) {
+            listenerCapture.onRouteChange(RoutingUtils.removalChange(contextType, path));
+        }
+    }
+    
+    public void removeRoute(InstanceIdentifier<?> path, S service) {
+        @SuppressWarnings("rawtypes")
+        RouteChangeListener listenerCapture = listener;
+        if (routes.remove(path, service) && listenerCapture != null) {
+            LOGGER.debug("Route {} to {} removed in routing table {}",path,service,this);
+            listenerCapture.onRouteChange(RoutingUtils.removalChange(contextType, path));
+        }
+    }
+
+    @Override
+    public S getRoute(InstanceIdentifier<?> nodeInstance) {
+        S route = routes.get(nodeInstance);
+        if (route != null) {
+            return route;
+        }
+        return getDefaultRoute();
+    }
+
+    @Override
+    public Map<InstanceIdentifier<?>, S> getRoutes() {
+        return unmodifiableRoutes;
+    }
+    
+    protected void removeAllReferences(S service) {
+        
+    }
+    
+    
+
+    @Override
+    public String toString() {
+        return "RpcRoutingTableImpl [router=" + routerName + ", service=" + serviceType.getSimpleName() + ", context="
+                + contextType.getSimpleName() + "]";
+    }
+
+
+
+    private class SingletonListenerRegistration<L extends RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> extends
+            AbstractObjectRegistration<L>
+            implements ListenerRegistration<L> {
+
+        public SingletonListenerRegistration(L instance) {
+            super(instance);
+            listener = instance;
+        }
+
+        @Override
+        protected void removeRegistration() {
+            listener = null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRoutingTableImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRoutingTableImpl.xtend
deleted file mode 100644 (file)
index 116a817..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.opendaylight.controller.sal.binding.codegen.impl
-
-import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable
-import org.opendaylight.yangtools.yang.binding.BaseIdentity
-import org.opendaylight.yangtools.yang.binding.RpcService
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import java.util.Map
-import org.opendaylight.yangtools.yang.binding.DataObject
-import java.util.HashMap
-
-class RpcRoutingTableImpl<C extends BaseIdentity,S extends RpcService> implements RpcRoutingTable<C,S>{
-    
-    @Property
-    val Class<C> identifier;
-    
-    @Property
-    var S defaultRoute;
-    
-    @Property
-    val Map<InstanceIdentifier<? extends DataObject>,S> routes;
-    
-    new(Class<C> ident, Map<InstanceIdentifier<? extends DataObject>,S> route) {
-        _identifier = ident
-        _routes = route
-    }
-    
-    new(Class<C> ident) {
-        _identifier = ident
-        _routes = new HashMap
-    }
-    
-    
-    override getRoute(InstanceIdentifier<? extends Object> nodeInstance) {
-        val ret = routes.get(nodeInstance);
-        if(ret !== null) {
-            return ret;
-        }
-        return defaultRoute;
-    }
-    
-    override removeRoute(InstanceIdentifier<? extends Object> path) {
-        routes.remove(path);
-    }
-    
-    @SuppressWarnings("rawtypes")
-    override updateRoute(InstanceIdentifier<? extends Object> path, S service) {
-        routes.put(path as InstanceIdentifier<? extends DataObject>,service);
-    }
-}
\ No newline at end of file
index 90fcbd99aaaad0a6f6448faf0428cbc46cc52b4d..d9e0983cfa516f07e0285dab813b5b0c1b3aec17 100644 (file)
@@ -27,7 +27,7 @@ import org.opendaylight.yangtools.yang.binding.Notification
 import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
 import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
 import java.util.HashSet
-import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
+import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.*
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker
 import java.util.Set
@@ -37,6 +37,8 @@ import org.opendaylight.yangtools.yang.binding.annotations.QName
 import org.opendaylight.yangtools.yang.binding.DataContainer
 import org.opendaylight.yangtools.yang.binding.RpcImplementation
 import org.opendaylight.controller.sal.binding.codegen.util.JavassistUtils
+import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils
+import javassist.LoaderClassPath
 
 class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory {
 
@@ -45,40 +47,70 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
     val extension JavassistUtils utils;
     val Map<Class<? extends NotificationListener>, RuntimeGeneratedInvokerPrototype> invokerClasses;
 
-    public new(ClassPool pool) {
+
+    new(ClassPool pool) {
         classPool = pool;
         utils = new JavassistUtils(pool);
         invokerClasses = new WeakHashMap();
         BROKER_NOTIFICATION_LISTENER = org.opendaylight.controller.sal.binding.api.NotificationListener.asCtClass;
+        pool.appendClassPath(new LoaderClassPath(RpcService.classLoader));
     }
 
     override <T extends RpcService> getDirectProxyFor(Class<T> iface) {
-        val supertype = iface.asCtClass
-        val targetCls = createClass(iface.directProxyName, supertype) [
-            field(DELEGATE_FIELD, iface);
-            implementMethodsFrom(supertype) [
-                body = '''
-                {
-                    if(«DELEGATE_FIELD» == null) {
+        val T instance =  withClassLoaderAndLock(iface.classLoader,lock) [|
+            val proxyName = iface.directProxyName;
+            val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName)
+            if(potentialClass != null) {
+                return potentialClass.newInstance as T;
+            }
+            val supertype = iface.asCtClass
+            val createdCls = createClass(iface.directProxyName, supertype) [
+                field(DELEGATE_FIELD, iface);
+                implementsType(RpcImplementation.asCtClass)
+                implementMethodsFrom(supertype) [
+                    body = '''
+                    {
+                        if(«DELEGATE_FIELD» == null) {
+                            throw new java.lang.IllegalStateException("No default provider is available");
+                        }
+                        return ($r) Â«DELEGATE_FIELD».«it.name»($$);
+                    }
+                    '''
+                ]
+                implementMethodsFrom(RpcImplementation.asCtClass) [
+                    body = '''
+                    {
                         throw new java.lang.IllegalStateException("No provider is processing supplied message");
+                        return ($r) null;
                     }
-                    return ($r) Â«DELEGATE_FIELD».«it.name»($$);
-                }
-                '''
+                    '''
+                ]
             ]
+            return createdCls.toClass(iface.classLoader).newInstance as T
         ]
-        return targetCls.toClass(iface.classLoader).newInstance as T
+        return instance;
     }
 
-    override <T extends RpcService> getRouterFor(Class<T> iface) {
-        val instance = <RpcRouterCodegenInstance<T>>withClassLoaderAndLock(iface.classLoader,lock) [ |
+    override <T extends RpcService> getRouterFor(Class<T> iface,String routerInstanceName) {
+        val metadata = withClassLoader(iface.classLoader) [|
+            val supertype = iface.asCtClass
+            return supertype.rpcMetadata;
+        ]
+        
+        val instance = <T>withClassLoaderAndLock(iface.classLoader,lock) [ |
             val supertype = iface.asCtClass
-            val metadata = supertype.rpcMetadata;
+            val routerName = iface.routerName;
+            val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName)
+            if(potentialClass != null) {
+                return potentialClass.newInstance as T;
+            }
+            
             val targetCls = createClass(iface.routerName, supertype) [
-                addInterface(RpcImplementation.asCtClass)
+                
                 
                 field(DELEGATE_FIELD, iface)
                 //field(REMOTE_INVOKER_FIELD,iface);
+                implementsType(RpcImplementation.asCtClass)
                 
                 for (ctx : metadata.contexts) {
                     field(ctx.routingTableField, Map)
@@ -95,7 +127,7 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
                                instance = Â«DELEGATE_FIELD»;
                             }
                             if(instance == null) {
-                                throw new java.lang.IllegalStateException("No provider is processing supplied message");
+                                throw new java.lang.IllegalStateException("No routable provider is processing routed message for " + String.valueOf(identifier));
                             }
                             return ($r) instance.«it.name»($$);
                         }'''
@@ -105,35 +137,18 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
                     }
                 ]
                 implementMethodsFrom(RpcImplementation.asCtClass) [
-                    switch (name) {
-                        case "getSupportedInputs":
-                            body = '''
-                            {
-                                throw new java.lang.UnsupportedOperationException("Not implemented yet");
-                                return ($r) null;
-                            }'''
-                        case "invoke": {
-                            val tmpBody = '''
-                            {
-                                Â«FOR input : metadata.supportedInputs SEPARATOR " else "»
-                                Â«val rpcMetadata = metadata.rpcInputs.get(input)»
-                                if(«input.name».class.equals($1)) {
-                                    return ($r) this.«rpcMetadata.methodName»((«input.name») $2);
-                                }
-                                Â«ENDFOR»
-                                throw new java.lang.IllegalArgumentException("Not supported message type");
-                                return ($r) null;
-                            }
-                            '''
-                            body = tmpBody
-                        }
+                    body = '''
+                    {
+                        throw new java.lang.IllegalStateException("No provider is processing supplied message");
+                        return ($r) null;
                     }
+                    '''
                 ]
             ]
-            val instance = targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as T
-            return new RpcRouterCodegenInstance(iface, instance, metadata.contexts,metadata.supportedInputs);
+            return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as T
+            
         ];
-        return instance;
+        return new RpcRouterCodegenInstance(routerInstanceName,iface, instance, metadata.contexts,metadata.supportedInputs);
     }
 
     private def RpcServiceMetadata getRpcMetadata(CtClass iface) {
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java
new file mode 100644 (file)
index 0000000..266293f
--- /dev/null
@@ -0,0 +1,14 @@
+package org.opendaylight.controller.sal.binding.codegen.impl;
+
+import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
+import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
+
+import javassist.ClassPool;
+
+public class SingletonHolder {
+
+    public static final ClassPool CLASS_POOL = new ClassPool(); 
+    public static final org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator RPC_GENERATOR_IMPL = new org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator(CLASS_POOL);
+    public static final RuntimeCodeGenerator RPC_GENERATOR = RPC_GENERATOR_IMPL;
+    public static final NotificationInvokerFactory INVOKER_FACTORY = RPC_GENERATOR_IMPL.getInvokerFactory();
+}
index 83096514465a4814c86ad751493dec1d6e1fc156..ca1b6344e6cd2fd178cf598b91cbced94397205e 100644 (file)
@@ -1,12 +1,16 @@
 package org.opendaylight.controller.sal.binding.codegen.impl;
 
+import java.util.List;
+
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 
 public class XtendHelper {
 
-    public static <C extends BaseIdentity> RpcRoutingTableImpl createRoutingTable(
-            Class<C> cls) {
-        return new RpcRoutingTableImpl<>(cls);
+    @SuppressWarnings({"rawtypes","unchecked"})
+    public static Iterable<TypeDefinition> getTypes(UnionTypeDefinition definition) {
+        return (Iterable<TypeDefinition>) (List) definition.getTypes();
     }
 }
index 4b672f1140ff915d957ee33a8d0efc69a724636e..cabb1bc4e2c5359582bc95e1e30514f557801b64 100644 (file)
@@ -175,7 +175,7 @@ public class LazyGeneratedCodecRegistry implements //
                     });
             return ret;
         } catch (Exception e) {
-            LOG.error("Could not find augmentable for {}", augmentation, e);
+            LOG.debug("Could not find augmentable for {} using {}", augmentation, augmentation.getClassLoader(), e);
             return null;
         }
     }
@@ -233,7 +233,7 @@ public class LazyGeneratedCodecRegistry implements //
         if (typeToClass.containsKey(typeRef)) {
             return;
         }
-        LOG.info("Binding Class {} encountered.", cls);
+        LOG.trace("Binding Class {} encountered.", cls);
         WeakReference<Class> weakRef = new WeakReference<>(cls);
         typeToClass.put(typeRef, weakRef);
         if (Augmentation.class.isAssignableFrom(cls)) {
@@ -250,7 +250,7 @@ public class LazyGeneratedCodecRegistry implements //
         if (typeToClass.containsKey(typeRef)) {
             return;
         }
-        LOG.info("Binding Class {} encountered.", cls);
+        LOG.trace("Binding Class {} encountered.", cls);
         WeakReference<Class> weakRef = new WeakReference<>((Class) cls);
         typeToClass.put(typeRef, weakRef);
     }
index 853e62aa38799302fb46319ac2f09577ad4d4ec5..1b3acf7674eda63e4430ec8d61b7ef186a2b6c80 100644 (file)
@@ -43,6 +43,11 @@ import java.util.ArrayList
 import org.opendaylight.yangtools.yang.data.api.Node
 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.binding.RpcService
+import java.util.Set
+import org.opendaylight.yangtools.yang.common.QName
+import com.google.common.collect.FluentIterable
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
 
 class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, AutoCloseable {
 
@@ -65,6 +70,9 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
 
     @Property
     val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
+    
+    @Property
+    val ConcurrentMap<Type,Set<QName>> serviceTypeToRpc = new ConcurrentHashMap(); 
 
     val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
 
@@ -85,10 +93,17 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
 
             registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
             binding.pathToType.putAll(entry.value.childNodes)
-            //val module = entry.key;
+            val module = entry.key;
             val context = entry.value;
             updateBindingFor(context.childNodes, schemaContext);
             updateBindingFor(context.cases, schemaContext);
+            val namespace = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
+            
+            if(!module.rpcs.empty) {
+            val rpcs = FluentIterable.from(module.rpcs).transform[QName].toSet
+            val serviceClass = new ReferencedTypeImpl(namespace,BindingGeneratorUtil.parseToClassName(module.name)+"Service");
+                serviceTypeToRpc.put(serviceClass,rpcs);
+            }
 
             val typedefs = context.typedefs;
             for (typedef : typedefs.entrySet) {
@@ -186,15 +201,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
     }
 
     override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
-        return tryDeserialization[ |
-            if (node == null) {
-                return null;
-            }
-            val targetType = path.targetType
-            val transformer = registry.getCodecForDataObject(targetType);
-            val ret = transformer.deserialize(node)?.value as DataObject;
-            return ret;
-        ]
+         dataObjectFromDataDom(path.targetType,node) as DataObject;
     }
 
     override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) {
@@ -243,6 +250,10 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
             listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable<String, String>());
         }
     }
+    
+    override getRpcQNamesFor(Class<? extends RpcService> service) {
+        return serviceTypeToRpc.get(new ReferencedTypeImpl(service.package.name,service.simpleName));
+    }
 
     private def getSchemaWithRetry(Type type) {
         val typeDef = typeToSchemaNode.get(type);
@@ -274,5 +285,16 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
     override close() throws Exception {
         listenerRegistration?.unregister();
     }
+    
+    override dataObjectFromDataDom(Class<? extends DataContainer> container, CompositeNode domData) {
+        return tryDeserialization[ |
+            if (domData == null) {
+                return null;
+            }
+            val transformer = registry.getCodecForDataObject(container);
+            val ret = transformer.deserialize(domData)?.value as DataObject;
+            return ret;
+        ]
+    }
 
 }
index 4271ef9c1a9bb5824f04673cbcf1e86f466c7c52..5bc2d70c6a97a6cfba93ff15ee065ecbae352ae8 100644 (file)
@@ -56,6 +56,14 @@ import javassist.CannotCompileException
 import java.util.concurrent.locks.Lock
 import java.util.concurrent.Callable
 import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
+import java.util.HashSet
+import java.util.Collections
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit
+import java.util.Set
+import org.opendaylight.controller.sal.binding.codegen.impl.XtendHelper
 
 class TransformerGenerator {
 
@@ -137,9 +145,13 @@ class TransformerGenerator {
             if (typeSpecBuilder == null) {
                 typeSpecBuilder = pathToType.get(node.path);
             }
+            var schemaNode = typeToSchemaNode.get(ref);
+            if(schemaNode === null) {
+                schemaNode = node;
+            }
             checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
             val typeSpec = typeSpecBuilder.toInstance();
-            val newret = generateTransformerFor(inputType, typeSpec, node);
+            val newret = generateTransformerFor(inputType, typeSpec, schemaNode);
             listener.onClassProcessed(inputType);
             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         ]
@@ -243,19 +255,24 @@ class TransformerGenerator {
         transformerFor(cls, node);
     }
 
-    private def Class<?> getValueSerializer(GeneratedTransferObject type) {
+    private def Class<?> valueSerializer(GeneratedTransferObject type, TypeDefinition<?> typeDefinition) {
         val cls = loadClassWithTCCL(type.resolvedName);
         val transformer = cls.generatedClass;
         if (transformer !== null) {
             return transformer;
         }
+        var baseType = typeDefinition;
+        while (baseType.baseType != null) {
+            baseType = baseType.baseType;
+        }
+        val finalType = baseType;
         return withClassLoaderAndLock(cls.classLoader, lock) [ |
-            val valueTransformer = generateValueTransformer(cls, type);
+            val valueTransformer = generateValueTransformer(cls, type, finalType);
             return valueTransformer;
         ]
     }
 
-    private def Class<?> getValueSerializer(Enumeration type) {
+    private def Class<?> valueSerializer(Enumeration type, TypeDefinition<?> typeDefinition) {
         val cls = loadClassWithTCCL(type.resolvedName);
         val transformer = cls.generatedClass;
         if (transformer !== null) {
@@ -340,7 +357,7 @@ class TransformerGenerator {
                 ]
             ]
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
         } catch (Exception e) {
             processException(inputType, e);
@@ -391,7 +408,7 @@ class TransformerGenerator {
                 method(Object, "deserialize", Object) [
                     bodyChecked = '''
                         {
-                            //System.out.println("«type.name»#deserialize: " +$1);
+                            ////System.out.println("«type.name»#deserialize: " +$1);
                             java.util.Map.Entry _input = (java.util.Map.Entry) $1;
                             return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue());
                         }
@@ -401,7 +418,7 @@ class TransformerGenerator {
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)  as Class<? extends BindingCodec<Object, Object>>
             listener?.onDataContainerCodecCreated(inputType, ret);
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -450,7 +467,7 @@ class TransformerGenerator {
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
             listener?.onDataContainerCodecCreated(inputType, ret);
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -475,14 +492,14 @@ class TransformerGenerator {
                     modifiers = PUBLIC + FINAL + STATIC
                     bodyChecked = '''
                         {
-                            //System.out.println("Qname " + $1);
-                            //System.out.println("Value " + $2);
+                            ////System.out.println("Qname " + $1);
+                            ////System.out.println("Value " + $2);
                             Â«QName.name» _resultName = Â«QName.name».create(QNAME,QNAME.getLocalName());
                             java.util.List _childNodes = new java.util.ArrayList();
                             Â«type.resolvedName» value = («type.resolvedName») $2;
                             Â«FOR child : node.childNodes»
                                 Â«var signature = properties.getFor(child)»
-                                //System.out.println("«signature.key»" + value.«signature.key»());
+                                ////System.out.println("«signature.key»" + value.«signature.key»());
                                 Â«serializeProperty(child, signature.value, signature.key)»
                             Â«ENDFOR»
                             return ($r) _childNodes;
@@ -511,7 +528,7 @@ class TransformerGenerator {
                             return null;
                             }
                             java.util.Map _compositeNode = (java.util.Map) $2;
-                            //System.out.println(_localQName + " " + _compositeNode);
+                            System.out.println(_localQName + " " + _compositeNode);
                             Â«type.builderName» _builder = new Â«type.builderName»();
                             boolean _is_empty = true;
                             Â«FOR child : node.childNodes»
@@ -571,7 +588,7 @@ class TransformerGenerator {
                             }
                             java.util.Map.Entry _input = new Â«SimpleEntry.name»($1,_baValue);
                             Object _ret =  _codec.serialize(_input);
-                            //System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
+                            ////System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
                             return («List.name») _ret;
                         }
                     '''
@@ -603,7 +620,7 @@ class TransformerGenerator {
             val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
             val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             listener?.onChoiceCodecCreated(inputType, ret, node);
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (Exception e) {
             processException(inputType, e);
@@ -659,6 +676,7 @@ class TransformerGenerator {
                 return null;
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
+            System.out.println(_localQName + " " + _compositeNode);
             Â«type.builderName» _builder = new Â«type.builderName»();
             Â«deserializeKey(type, node)»
             Â«deserializeDataNodeContainerBody(type, node)»
@@ -674,6 +692,7 @@ class TransformerGenerator {
                 return null;
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
+            System.out.println(_localQName + " " + _compositeNode);
             Â«type.builderName» _builder = new Â«type.builderName»();
             Â«deserializeDataNodeContainerBody(type, node)»
             Â«deserializeAugmentations»
@@ -689,7 +708,7 @@ class TransformerGenerator {
                 return null;
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
-            //System.out.println(_localQName + " " + _compositeNode);
+            System.out.println(_localQName + " " + _compositeNode);
             Â«type.builderName» _builder = new Â«type.builderName»();
             Â«deserializeDataNodeContainerBody(type, node)»
             Â«deserializeAugmentations»
@@ -722,7 +741,7 @@ class TransformerGenerator {
             Â«Iterator.name» _entries = _augmentation.entrySet().iterator();
             while(_entries.hasNext()) {
                 java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
-                //System.out.println("Aug. key:" + _entry.getKey());
+                ////System.out.println("Aug. key:" + _entry.getKey());
                 Class _type = (Class) _entry.getKey();
                 Â«Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
                 if(_value != null) {
@@ -736,7 +755,7 @@ class TransformerGenerator {
         String propertyName) '''
         java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
             localName»"));
-        //System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
+        ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
         java.util.List Â«propertyName» = new java.util.ArrayList();
         if(_dom_«propertyName» != null) {
             java.util.List _serialized = new java.util.ArrayList();
@@ -745,15 +764,15 @@ class TransformerGenerator {
             while(_hasNext) {
                 Object _listItem = _iterator.next();
                 _is_empty = false;
-                //System.out.println("  item" + _listItem);
+                ////System.out.println("  item" + _listItem);
                 Object _value = Â«type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
-                //System.out.println("  value" + _value);
+                ////System.out.println("  value" + _value);
                 Â«propertyName».add(_value);
                 _hasNext = _iterator.hasNext();
             }
         }
         
-        //System.out.println(" list" + Â«propertyName»);
+        ////System.out.println(" list" + Â«propertyName»);
     '''
 
     private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
@@ -770,7 +789,7 @@ class TransformerGenerator {
                 Object _listItem = _iterator.next();
                 if(_listItem instanceof java.util.Map.Entry) {
                     Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
-                    Object _value = Â«deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
+                    Object _value = Â«deserializeValue(type.actualTypeArguments.get(0), "_innerValue", schema.type)»;
                     Â«propertyName».add(_value);
                 }
                 _hasNext = _iterator.hasNext();
@@ -786,7 +805,7 @@ class TransformerGenerator {
             _is_empty = false;
             java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
             Object _inner_value = _dom_«propertyName».getValue();
-            Â«propertyName» = Â«deserializeValue(type, "_inner_value")»;
+            Â«propertyName» = Â«deserializeValue(type, "_inner_value", schema.type)»;
         }
     '''
 
@@ -809,16 +828,17 @@ class TransformerGenerator {
         }
     '''
 
-    private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
-        («type.resolvedName») Â«type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
+    private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter,
+        TypeDefinition<?> typeDefinition) '''
+        («type.resolvedName») Â«type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
     '''
 
-    private def dispatch String deserializeValue(Enumeration type, String domParameter) '''
-        («type.resolvedName») Â«type.valueSerializer.resolvedName».fromDomValue(«domParameter»)
+    private def dispatch String deserializeValue(Enumeration type, String domParameter, TypeDefinition<?> typeDefinition) '''
+        («type.resolvedName») Â«type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
     '''
 
     private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
-        Class<?> inputType, GeneratedTransferObject typeSpec) {
+        Class<?> inputType, GeneratedTransferObject typeSpec, TypeDefinition<?> typeDef) {
         try {
 
             val returnType = typeSpec.valueReturnType;
@@ -827,11 +847,6 @@ class TransformerGenerator {
                 val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
-            if (returnType.name == 'char[]') {
-                val ctCls = createUnionImplementation(inputType, typeSpec);
-                val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-                return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
-            }
 
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
@@ -846,16 +861,16 @@ class TransformerGenerator {
                     val ctSpec = typeSpec.asCtClass;
                     bodyChecked = '''
                         {
-                            //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+                            ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
                             
                             if($1 == null) {
                                 return null;
                             }
                             Â«typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
-                            //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+                            ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
                             Â«returnType.resolvedName» _value =  _encapsulatedValue.getValue();
-                            //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
-                            Object _domValue = Â«serializeValue(returnType, "_value")»;
+                            ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
+                            Object _domValue = Â«serializeValue(returnType, "_value", null)»;
                             return _domValue;
                         }
                     '''
@@ -871,12 +886,12 @@ class TransformerGenerator {
                     modifiers = PUBLIC + FINAL + STATIC
                     bodyChecked = '''
                         {
-                            //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
                             
                             if($1 == null) {
                                 return null;
                             }
-                            Â«returnType.resolvedName» _simpleValue = Â«deserializeValue(returnType, "$1")»;
+                            Â«returnType.resolvedName» _simpleValue = Â«deserializeValue(returnType, "$1", null)»;
                             Â«typeSpec.resolvedName» _value = new Â«typeSpec.resolvedName»(_simpleValue);
                             return _value;
                         }
@@ -891,7 +906,7 @@ class TransformerGenerator {
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         } catch (Exception e) {
             log.error("Cannot compile DOM Codec for {}", inputType, e);
@@ -899,74 +914,182 @@ class TransformerGenerator {
             exception.addSuppressed(e);
             throw exception;
         }
-
     }
 
-    def createUnionImplementation(Class<?> inputType, GeneratedTransferObject typeSpec) {
-        return createClass(typeSpec.codecClassName) [
-            val properties = typeSpec.allProperties;
-            //staticField(Map,"AUGMENTATION_SERIALIZERS");
-            if (inputType.isYangBindingAvailable) {
-                implementsType(BINDING_CODEC)
-                staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
-                staticField(it, IDENTITYREF_CODEC, BindingCodec)
-                implementsType(BindingDeserializer.asCtClass)
-            }
-            method(Object, "toDomValue", Object) [
-                modifiers = PUBLIC + FINAL + STATIC
-                val ctSpec = inputType.asCtClass;
-                bodyChecked = '''
-                    {
-                        //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
-                        
-                        if($1 == null) {
+    private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+        Class<?> inputType, GeneratedTransferObject typeSpec, UnionTypeDefinition typeDef) {
+        try {
+            val ctCls = createClass(typeSpec.codecClassName) [
+                val properties = typeSpec.allProperties;
+                val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type | type.QName.getterName];
+                //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                if (inputType.isYangBindingAvailable) {
+                    implementsType(BINDING_CODEC)
+                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                    staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                    implementsType(BindingDeserializer.asCtClass)
+                }
+                method(Object, "toDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    val ctSpec = inputType.asCtClass;
+                    
+                    bodyChecked = '''
+                        {
+                            ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            Â«typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
+                            Â«FOR property : properties.entrySet»
+                                Â«IF property.key != "getValue"»
+                                    Â«property.value.resolvedName» Â«property.key» = («property.value.resolvedName») _value.«property.
+                            key»();
+                                    if(«property.key» != null) { 
+                                        return Â«serializeValue(property.value, property.key, getterToTypeDefinition.get(property.key))»;
+                                    }
+                                Â«ENDIF»
+                            Â«ENDFOR»
+                            
                             return null;
                         }
-                        Â«typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
-                        Â«FOR property : properties.entrySet»
-                            Â«IF property.key != "getValue"»
-                                Â«property.value.resolvedName» Â«property.key» = («property.value.resolvedName») _value.«property.key»();
-                                if(«property.key» != null) { 
-                                    return Â«serializeValue(property.value, property.key)»;
-                                }
-                            Â«ENDIF»
-                        Â«ENDFOR»
-                        
-                        return null;
-                    }
-                '''
-            ]
-            method(Object, "serialize", Object) [
-                bodyChecked = '''
-                    {
-                        return toDomValue($1);
-                    }
-                '''
-            ]
-            method(Object, "fromDomValue", Object) [
-                modifiers = PUBLIC + FINAL + STATIC
-                bodyChecked = '''
-                    {
-                        //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
-                        
-                        if($1 == null) {
-                            return null;
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    bodyChecked = '''
+                        {
+                            return toDomValue($1);
                         }
-                        if($1 instanceof String) {
-                            String _simpleValue = (String) $1;
-                            return new Â«typeSpec.resolvedName»(_simpleValue.toCharArray());
+                    '''
+                ]
+                method(Object, "fromDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    bodyChecked = '''
+                        {
+                            ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            if($1 instanceof String) {
+                                String _simpleValue = (String) $1;
+                                return new Â«typeSpec.resolvedName»(_simpleValue.toCharArray());
+                            }
+                            return null;
                         }
-                        return null;
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    bodyChecked = '''{
+                            return fromDomValue($1);
                     }
-                '''
+                    '''
+                ]
             ]
-            method(Object, "deserialize", Object) [
-                bodyChecked = '''{
+
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        } catch (Exception e) {
+            log.error("Cannot compile DOM Codec for {}", inputType, e);
+            val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+    }
+
+
+    private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+        Class<?> inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) {
+        try {
+            val ctCls = createClass(typeSpec.codecClassName) [
+                //staticField(Map,"AUGMENTATION_SERIALIZERS");
+                if (inputType.isYangBindingAvailable) {
+                    implementsType(BINDING_CODEC)
+                    staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+                    staticField(it, IDENTITYREF_CODEC, BindingCodec)
+                    implementsType(BindingDeserializer.asCtClass)
+                }
+                method(Object, "toDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    val ctSpec = typeSpec.asCtClass;
+                    bodyChecked = '''
+                        {
+                            ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            Â«typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
+                            Â«HashSet.resolvedName» _value = new Â«HashSet.resolvedName»();
+                            //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+                            
+                            Â«FOR bit : typeDef.bits»
+                                Â«val getter = bit.getterName()»
+                                if(Boolean.TRUE.equals(_encapsulatedValue.«getter»())) {
+                                    _value.add("«bit.name»");
+                                }
+                            Â«ENDFOR»
+                            Â«Set.resolvedName» _domValue =  Â«Collections.resolvedName».unmodifiableSet(_value);
+                            //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_domValue);
+                            
+                            return _domValue;
+                        }
+                    '''
+                ]
+                method(Object, "serialize", Object) [
+                    bodyChecked = '''
+                        {
+                            return toDomValue($1);
+                        }
+                    '''
+                ]
+                method(Object, "fromDomValue", Object) [
+                    modifiers = PUBLIC + FINAL + STATIC
+                    val sortedBits = typeDef.bits.sort[o1, o2|o1.propertyName.compareTo(o2.propertyName)]
+                    bodyChecked = '''
+                        {
+                            //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            
+                            if($1 == null) {
+                                return null;
+                            }
+                            Â«Set.resolvedName» _domValue = («Set.resolvedName») $1;
+                            Â«FOR bit : sortedBits»
+                                Boolean Â«bit.propertyName» = Boolean.valueOf(_domValue.contains("«bit.name»"));
+                            Â«ENDFOR»
+                            
+                            return new Â«inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»);
+                        }
+                    '''
+                ]
+                method(Object, "deserialize", Object) [
+                    bodyChecked = '''{
                             return fromDomValue($1);
                     }
                     '''
+                ]
             ]
-        ]
+
+            val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
+            return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+        } catch (Exception e) {
+            log.error("Cannot compile DOM Codec for {}", inputType, e);
+            val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
+            exception.addSuppressed(e);
+            throw exception;
+        }
+    }
+
+    def String getPropertyName(Bit bit) {
+        '''_«BindingGeneratorUtil.parseToValidParamName(bit.name)»'''
+    }
+
+    def String getterName(Bit bit) {
+
+        val paramName = BindingGeneratorUtil.parseToValidParamName(bit.name);
+        return '''is«paramName.toFirstUpper»''';
     }
 
     def boolean isYangBindingAvailable(Class<?> class1) {
@@ -1030,7 +1153,7 @@ class TransformerGenerator {
         return null;
     }
 
-    private def dispatch Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
+    private def Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
         try {
             val typeRef = new ReferencedTypeImpl(typeSpec.packageName, typeSpec.name);
             val schema = typeToSchemaNode.get(typeRef) as ExtendedType;
@@ -1086,7 +1209,7 @@ class TransformerGenerator {
             ]
 
             val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
-            log.info("DOM Codec for {} was generated {}", inputType, ret)
+            log.debug("DOM Codec for {} was generated {}", inputType, ret)
             return ret;
         } catch (CodeGenerationException e) {
             throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
@@ -1116,7 +1239,7 @@ class TransformerGenerator {
 
     }
 
-    private def dispatch String deserializeValue(Type type, String domParameter) {
+    private def dispatch String deserializeValue(Type type, String domParameter, TypeDefinition<?> typeDef) {
         if (INSTANCE_IDENTIFIER.equals(type)) {
             return '''(«InstanceIdentifier.name») Â«INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
         } else if (CLASS_TYPE.equals(type)) {
@@ -1214,7 +1337,7 @@ class TransformerGenerator {
             Â«FOR child : node.childNodes»
                 Â«val signature = properties.getFor(child)»
                 Â«IF signature !== null»
-                    //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
+                    ////System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
                     Â«serializeProperty(child, signature.value, signature.key)»
                 Â«ENDIF»
             Â«ENDFOR»
@@ -1256,7 +1379,7 @@ class TransformerGenerator {
     private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
         String propertyName) '''
         Â«type.resolvedName» Â«propertyName» = value.«propertyName»();
-        //System.out.println("«propertyName»:" + Â«propertyName»);
+        ////System.out.println("«propertyName»:" + Â«propertyName»);
         if(«propertyName» != null) {
             java.util.Iterator _iterator = Â«propertyName».iterator();
             boolean _hasNext = _iterator.hasNext();
@@ -1274,7 +1397,7 @@ class TransformerGenerator {
         
         if(«propertyName» != null) {
             Â«QName.name» _qname = Â«QName.name».create(_resultName,"«schema.QName.localName»");
-            Object _propValue = Â«serializeValue(type, propertyName)»;
+            Object _propValue = Â«serializeValue(type, propertyName, schema.type)»;
             if(_propValue != null) {
                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
                 _childNodes.add(_domValue);
@@ -1282,12 +1405,15 @@ class TransformerGenerator {
         }
     '''
 
-    private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
-        resolvedName».toDomValue(«parameter»)'''
+    private def dispatch serializeValue(GeneratedTransferObject type, String parameter, TypeDefinition<?> typeDefinition) {
+        '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
+    }
 
-    private def dispatch serializeValue(Enumeration type, String parameter) '''«type.valueSerializer.resolvedName».toDomValue(«parameter»)'''
+    private def dispatch serializeValue(Enumeration type, String parameter, TypeDefinition<?> typeDefinition) {
+        '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
+    }
 
-    private def dispatch serializeValue(Type signature, String property) {
+    private def dispatch serializeValue(Type signature, String property, TypeDefinition<?> typeDefinition) {
         if (INSTANCE_IDENTIFIER == signature) {
             return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
         } else if (CLASS_TYPE.equals(signature)) {
@@ -1308,7 +1434,7 @@ class TransformerGenerator {
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
-                Object _propValue = Â«serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
+                Object _propValue = Â«serializeValue(type.actualTypeArguments.get(0), "_listItem", schema.type)»;
                 Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
                 _childNodes.add(_domValue);
                 _hasNext = _iterator.hasNext();
index 9381a5a070e67e7c82226c5b920b06f9a952cc67..b4bf3f5a83cbcaff144af392ee2f1141235aa753 100644 (file)
@@ -9,69 +9,22 @@ package org.opendaylight.controller.sal.binding.impl
 
 import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider
-import org.opendaylight.yangtools.yang.binding.RpcService
-import javassist.ClassPool
 import org.osgi.framework.BundleContext
-import java.util.Map
-import java.util.HashMap
-import javassist.LoaderClassPath
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker
-import java.util.Hashtable
-import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*
-
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService
-import org.osgi.framework.ServiceRegistration
-import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.*
-import static extension org.opendaylight.controller.sal.binding.impl.osgi.PropertiesUtils.*
-import org.opendaylight.controller.sal.binding.api.NotificationService
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-
-import org.slf4j.LoggerFactory
-import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
-import org.opendaylight.controller.sal.binding.spi.RpcRouter
-import java.util.concurrent.ConcurrentHashMap
-import static com.google.common.base.Preconditions.*
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
-import org.opendaylight.yangtools.yang.binding.BaseIdentity
-import com.google.common.collect.Multimap
-import com.google.common.collect.HashMultimap
-import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
-import java.util.concurrent.Executors
-import java.util.Collections
 import org.opendaylight.yangtools.yang.binding.DataObject
-import java.util.concurrent.locks.ReentrantLock
-import java.util.concurrent.Callable
-import java.util.WeakHashMap
-import javax.annotation.concurrent.GuardedBy
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener
+import org.opendaylight.controller.sal.binding.spi.RpcContextIdentifier
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.slf4j.LoggerFactory
 
-class BindingAwareBrokerImpl implements BindingAwareBroker, RpcProviderRegistry, AutoCloseable {
+class BindingAwareBrokerImpl extends RpcProviderRegistryImpl implements BindingAwareBroker, AutoCloseable {
     private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl)
 
     private InstanceIdentifier<? extends DataObject> root = InstanceIdentifier.builder().toInstance();
 
-    private static val clsPool = ClassPool.getDefault()
-    public static var RuntimeCodeGenerator generator;
-
-    /**
-     * Map of all Managed Direct Proxies
-     * 
-     */
-    private val Map<Class<? extends RpcService>, RpcProxyContext> managedProxies = new ConcurrentHashMap();
-
-    /**
-     * 
-     * Map of all available Rpc Routers
-     * 
-     * 
-     */
-    private val Map<Class<? extends RpcService>, RpcRouter<? extends RpcService>> rpcRouters = new WeakHashMap();
-
     @Property
     private var NotificationProviderService notifyBroker
 
@@ -81,43 +34,16 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, RpcProviderRegistry,
     @Property
     var BundleContext brokerBundleContext
 
-    ServiceRegistration<NotificationProviderService> notifyProviderRegistration
-
-    ServiceRegistration<NotificationService> notifyConsumerRegistration
-
-    ServiceRegistration<DataProviderService> dataProviderRegistration
-
-    ServiceRegistration<DataBrokerService> dataConsumerRegistration
-
-    private val proxyGenerationLock = new ReentrantLock;
-
-    private val routerGenerationLock = new ReentrantLock;
-
-    public new(BundleContext bundleContext) {
+    public new(String name,BundleContext bundleContext) {
+        super(name);
         _brokerBundleContext = bundleContext;
     }
 
     def start() {
         log.info("Starting MD-SAL: Binding Aware Broker");
-        initGenerator();
-
-        val executor = Executors.newCachedThreadPool;
-
-        // Initialization of notificationBroker
-        log.info("Starting MD-SAL: Binding Aware Notification Broker");
-
-        log.info("Starting MD-SAL: Binding Aware Data Broker");
-
-        log.info("Starting MD-SAL: Binding Aware Data Broker");
-        log.info("MD-SAL: Binding Aware Broker Started");
     }
 
-    def initGenerator() {
 
-        // YANG Binding Class Loader
-        clsPool.appendClassPath(new LoaderClassPath(RpcService.classLoader));
-        generator = new RuntimeCodeGenerator(clsPool);
-    }
 
     override registerConsumer(BindingAwareConsumer consumer, BundleContext bundleCtx) {
         val ctx = consumer.createContext(bundleCtx)
@@ -140,246 +66,11 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, RpcProviderRegistry,
         new OsgiProviderContext(providerCtx, this)
     }
 
-    /**
-     * Returns a Managed Direct Proxy for supplied class
-     * 
-     * Managed direct proxy is a generated proxy class conforming to the supplied interface
-     * which delegates all calls to the backing delegate.
-     * 
-     * Proxy does not do any validation, null pointer checks or modifies data in any way, it
-     * is only use to avoid exposing direct references to backing implementation of service.
-     * 
-     * If proxy class does not exist for supplied service class it will be generated automatically.
-     */
-    private def <T extends RpcService> getManagedDirectProxy(Class<T> service) {
-        var RpcProxyContext existing = null
-
-        if ((existing = managedProxies.get(service)) != null) {
-            return existing.proxy
-        }
-        return withLock(proxyGenerationLock) [ |
-            val maybeProxy = managedProxies.get(service);
-            if (maybeProxy !== null) {
-                return maybeProxy.proxy;
-            }
-            
-            
-            val proxyInstance = generator.getDirectProxyFor(service)
-            val rpcProxyCtx = new RpcProxyContext(proxyInstance.class)
-            val properties = new Hashtable<String, String>()
-            rpcProxyCtx.proxy = proxyInstance as RpcService
-            properties.salServiceType = SAL_SERVICE_TYPE_CONSUMER_PROXY
-            rpcProxyCtx.registration = brokerBundleContext.registerService(service, rpcProxyCtx.proxy as T, properties)
-            managedProxies.put(service, rpcProxyCtx)
-            return rpcProxyCtx.proxy
-        ]
-    }
-
-    private static def <T> T withLock(ReentrantLock lock, Callable<T> method) {
-        try {
-            lock.lock();
-            val ret = method.call;
-            return ret;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Registers RPC Implementation
-     * 
-     */
-    override <T extends RpcService> addRpcImplementation(Class<T> type, T service) {
-        checkNotNull(type, "Service type should not be null")
-        checkNotNull(service, "Service type should not be null")
-        
-        val proxy = getManagedDirectProxy(type)
-        checkState(proxy.delegate === null, "The Service for type %s is already registered", type)
-
-        proxy.delegate = service;
-        return new RpcServiceRegistrationImpl<T>(type, service, this);
-    }
-
-    override <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type, T service) {
-        checkNotNull(type, "Service type should not be null")
-        checkNotNull(service, "Service type should not be null")
-        
-        val router = resolveRpcRouter(type);
-        checkState(router !== null)
-        return new RoutedRpcRegistrationImpl<T>(service, router, this)
+    override <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> registerRouteChangeListener(L listener) {
+        super.<L>registerRouteChangeListener(listener)
     }
     
-    override <T extends RpcService> getRpcService(Class<T> service) {
-        checkNotNull(service, "Service should not be null");
-        return getManagedDirectProxy(service) as T;
-    }
-
-    private def <T extends RpcService> RpcRouter<T> resolveRpcRouter(Class<T> type) {
-
-        val router = rpcRouters.get(type);
-        if (router !== null) {
-            return router as RpcRouter<T>;
-        }
-
-        // We created Router
-        return withLock(routerGenerationLock) [ |
-            val maybeRouter = rpcRouters.get(type);
-            if (maybeRouter !== null) {
-                return maybeRouter as RpcRouter<T>;
-            }
-            
-            val newRouter = generator.getRouterFor(type);
-            checkState(newRouter !== null);
-            rpcRouters.put(type, newRouter);
-            // We create / update Direct Proxy for router
-            val proxy = getManagedDirectProxy(type);
-            proxy.delegate = newRouter.invocationProxy
-            return newRouter;
-        ]
-
-    }
-
-    protected def <T extends RpcService> void registerPath(RoutedRpcRegistrationImpl<T> registration,
-        Class<? extends BaseIdentity> context, InstanceIdentifier<? extends Object> path) {
-
-        val router = registration.router;
-        val paths = registration.registeredPaths;
-
-        val routingTable = router.getRoutingTable(context)
-        checkState(routingTable != null);
-
-        // Updating internal structure of registration
-        routingTable.updateRoute(path, registration.instance)
-
-        // Update routing table / send announce to message bus
-        val success = paths.put(context, path);
-    }
-
-    protected def <T extends RpcService> void unregisterPath(RoutedRpcRegistrationImpl<T> registration,
-        Class<? extends BaseIdentity> context, InstanceIdentifier<? extends Object> path) {
-
-        val router = registration.router;
-        val paths = registration.registeredPaths;
-
-        val routingTable = router.getRoutingTable(context)
-        checkState(routingTable != null);
-
-        // Updating internal structure of registration
-        val target = routingTable.getRoute(path)
-        checkState(target === registration.instance)
-        routingTable.removeRoute(path)
-        checkState(paths.remove(context, path));
-    }
-
-    protected def <T extends RpcService> void unregisterRoutedRpcService(RoutedRpcRegistrationImpl<T> registration) {
-
-        val router = registration.router;
-        val paths = registration.registeredPaths;
-
-        for (ctxMap : registration.registeredPaths.entries) {
-            val context = ctxMap.key
-            val routingTable = router.getRoutingTable(context)
-            val path = ctxMap.value
-            routingTable.removeRoute(path)
-        }
-    }
-
-    protected def <T extends RpcService> void unregisterRpcService(RpcServiceRegistrationImpl<T> registration) {
-
-        val type = registration.serviceType;
-
-        val proxy = managedProxies.get(type);
-        if (proxy.proxy.delegate === registration.instance) {
-            proxy.proxy.delegate = null;
-        }
-    }
-
-    def createDelegate(Class<? extends RpcService> type) {
-        getManagedDirectProxy(type);
-    }
-
-    def getRpcRouters() {
-        return Collections.unmodifiableMap(rpcRouters);
-    }
-
-    override close() {
-        dataConsumerRegistration.unregister()
-        dataProviderRegistration.unregister()
-        notifyConsumerRegistration.unregister()
-        notifyProviderRegistration.unregister()
-    }
-
-}
-
-class RoutedRpcRegistrationImpl<T extends RpcService> extends AbstractObjectRegistration<T> implements RoutedRpcRegistration<T> {
-
-    @Property
-    private val BindingAwareBrokerImpl broker;
-
-    @Property
-    private val RpcRouter<T> router;
-
-    @Property
-    private val Multimap<Class<? extends BaseIdentity>, InstanceIdentifier<?>> registeredPaths = HashMultimap.create();
-
-    private var closed = false;
-
-    new(T instance, RpcRouter<T> backingRouter, BindingAwareBrokerImpl broker) {
-        super(instance)
-        _router = backingRouter;
-        _broker = broker;
-    }
-
-    override protected removeRegistration() {
-        closed = true
-        broker.unregisterRoutedRpcService(this)
-    }
-
-    override registerInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<? extends Object> instance) {
-        registerPath(context, instance);
-    }
-
-    override unregisterInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<? extends Object> instance) {
-        unregisterPath(context, instance);
-    }
-
-    override registerPath(Class<? extends BaseIdentity> context, InstanceIdentifier<? extends Object> path) {
-        checkClosed()
-        broker.registerPath(this, context, path);
-    }
-
-    override unregisterPath(Class<? extends BaseIdentity> context, InstanceIdentifier<? extends Object> path) {
-        checkClosed()
-        broker.unregisterPath(this, context, path);
-    }
-
-    override getServiceType() {
-        return router.serviceType;
-    }
-
-    private def checkClosed() {
-        if (closed)
-            throw new IllegalStateException("Registration was closed.");
-    }
-
-}
-
-class RpcServiceRegistrationImpl<T extends RpcService> extends AbstractObjectRegistration<T> implements RpcRegistration<T> {
-
-    private var BindingAwareBrokerImpl broker;
-
-    @Property
-    val Class<T> serviceType;
-
-    public new(Class<T> type, T service, BindingAwareBrokerImpl broker) {
-        super(service);
-        this._serviceType = type;
-        this.broker = broker;
-    }
-
-    override protected removeRegistration() {
-        broker.unregisterRpcService(this);
-        broker = null;
+    override close() throws Exception {
+        
     }
-
-}
+}
\ No newline at end of file
index e8b3850b77b665113b3bac0d9e33c8029cc592fc..b10c06f0c53e359ec2cabe3028b7243339c6f53b 100644 (file)
@@ -20,8 +20,8 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
 import org.opendaylight.yangtools.concepts.ListenerRegistration\r
 import org.opendaylight.yangtools.concepts.Registration\r
 import org.opendaylight.yangtools.yang.binding.Notification\r
-import org.slf4j.LoggerFactory\r
-\r
+import org.slf4j.LoggerFactory\rimport org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder
+
 class NotificationBrokerImpl implements NotificationProviderService, AutoCloseable {\r
 \r
     val Multimap<Class<? extends Notification>, NotificationListener<?>> listeners;\r
@@ -29,6 +29,11 @@ class NotificationBrokerImpl implements NotificationProviderService, AutoCloseab
     @Property\r
     var ExecutorService executor;\r
 \r
+    new() {\r
+        listeners = HashMultimap.create()\r
+    }\r
+\r
+    @Deprecated\r
     new(ExecutorService executor) {\r
         listeners = HashMultimap.create()\r
         this.executor = executor;\r
@@ -100,7 +105,7 @@ class NotificationBrokerImpl implements NotificationProviderService, AutoCloseab
 \r
     override registerNotificationListener(\r
         org.opendaylight.yangtools.yang.binding.NotificationListener listener) {\r
-        val invoker = BindingAwareBrokerImpl.generator.invokerFactory.invokerFor(listener);\r
+        val invoker = SingletonHolder.INVOKER_FACTORY.invokerFor(listener);\r
         for (notifyType : invoker.supportedNotifications) {\r
             listeners.put(notifyType, invoker.invocationProxy)\r
         }\r
index bc53108675798173dd271b9bf18bf6db6fd3bb65..644c50b86ad1699989720403c67f041c296a1b42 100644 (file)
@@ -45,8 +45,7 @@ class OsgiConsumerContext implements ConsumerContext {
                 val ref = services.iterator().next() as ServiceReference<T>;
                 return bundleContext.getService(ref) as T;
             } else {
-                broker.createDelegate(module);
-                return getRpcService(module);
+                return broker.getRpcService(module);
             }
         } catch (InvalidSyntaxException e) {
             log.error("Created filter was invalid:", e.message, e)
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java
new file mode 100644 (file)
index 0000000..6a17007
--- /dev/null
@@ -0,0 +1,209 @@
+package org.opendaylight.controller.sal.binding.impl;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import javax.swing.tree.ExpandVetoException;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
+import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
+import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper;
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
+import org.opendaylight.controller.sal.binding.spi.RpcContextIdentifier;
+import org.opendaylight.controller.sal.binding.spi.RpcRouter;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.*;
+
+public class RpcProviderRegistryImpl implements //
+        RpcProviderRegistry, //
+        RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
+
+    private RuntimeCodeGenerator rpcFactory = SingletonHolder.RPC_GENERATOR_IMPL;
+
+    private final Map<Class<? extends RpcService>, RpcService> publicProxies = new WeakHashMap<>();
+    private final Map<Class<? extends RpcService>, RpcRouter<?>> rpcRouters = new WeakHashMap<>();
+    private final ListenerRegistry<RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> routeChangeListeners = ListenerRegistry
+            .create();
+
+    private final static Logger LOG = LoggerFactory.getLogger(RpcProviderRegistryImpl.class);
+    
+    private final String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public RpcProviderRegistryImpl(String name) {
+        super();
+        this.name = name;
+    }
+
+    @Override
+    public final <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type,
+            T implementation) throws IllegalStateException {
+        return getRpcRouter(type).addRoutedRpcImplementation(implementation);
+    }
+
+    @Override
+    public final <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
+            throws IllegalStateException {
+        @SuppressWarnings("unchecked")
+        RpcRouter<T> potentialRouter = (RpcRouter<T>) rpcRouters.get(type);
+        if (potentialRouter != null) {
+            checkState(potentialRouter.getDefaultService() == null,
+                    "Default service for routed RPC already registered.");
+            return potentialRouter.registerDefaultService(implementation);
+        }
+        T publicProxy = getRpcService(type);
+        RpcService currentDelegate = RuntimeCodeHelper.getDelegate(publicProxy);
+        checkState(currentDelegate == null, "Rpc service is already registered");
+        LOG.debug("Registering {} as global implementation of {} in {}",implementation,type.getSimpleName(),this);
+        RuntimeCodeHelper.setDelegate(publicProxy, implementation);
+        return new RpcProxyRegistration<T>(type, implementation, this);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public final <T extends RpcService> T getRpcService(Class<T> type) {
+
+        @SuppressWarnings("unchecked")
+        T potentialProxy = (T) publicProxies.get(type);
+        if (potentialProxy != null) {
+            return potentialProxy;
+        }
+        synchronized(this) {
+            /**
+             * Potential proxy could be instantiated by other thread while we were
+             * waiting for the lock.
+             */
+            
+            potentialProxy = (T) publicProxies.get(type);
+            if (potentialProxy != null) {
+                return (T) potentialProxy;
+            }
+            T proxy = rpcFactory.getDirectProxyFor(type);
+            LOG.debug("Created {} as public proxy for {} in {}",proxy,type.getSimpleName(),this);
+            publicProxies.put(type, proxy);
+            return proxy;
+        }
+    }
+
+    private <T extends RpcService> RpcRouter<T> getRpcRouter(Class<T> type) {
+        RpcRouter<?> potentialRouter = rpcRouters.get(type);
+        if (potentialRouter != null) {
+            return (RpcRouter<T>) potentialRouter;
+        }
+        synchronized(this) {
+            /**
+             * Potential Router could be instantiated by other thread while we were
+             * waiting for the lock.
+             */
+            potentialRouter = rpcRouters.get(type); 
+            if (potentialRouter != null) {
+                return (RpcRouter<T>) potentialRouter;
+            }
+            RpcRouter<T> router = rpcFactory.getRouterFor(type,name);
+            router.registerRouteChangeListener(new RouteChangeForwarder(type));
+            LOG.debug("Registering router {} as global implementation of {} in {}",router,type.getSimpleName(),this);
+            RuntimeCodeHelper.setDelegate(getRpcService(type), router.getInvocationProxy());
+            rpcRouters.put(type, router);
+            return router;
+        }
+    }
+
+    @Override
+    public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
+            L listener) {
+        return (ListenerRegistration<L>) routeChangeListeners.register(listener);
+    }
+
+    public RuntimeCodeGenerator getRpcFactory() {
+        return rpcFactory;
+    }
+
+    public void setRpcFactory(RuntimeCodeGenerator rpcFactory) {
+        this.rpcFactory = rpcFactory;
+    }
+
+    private class RouteChangeForwarder<T extends RpcService> implements
+            RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
+
+        private final Class<T> type;
+
+        public RouteChangeForwarder(Class<T> type) {
+            this.type = type;
+        }
+
+        @Override
+        public void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
+            Map<RpcContextIdentifier, Set<InstanceIdentifier<?>>> announcements = new HashMap<>();
+            for (Entry<Class<? extends BaseIdentity>, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements()
+                    .entrySet()) {
+                RpcContextIdentifier key = RpcContextIdentifier.contextFor(type, entry.getKey());
+                announcements.put(key, entry.getValue());
+            }
+            Map<RpcContextIdentifier, Set<InstanceIdentifier<?>>> removals = new HashMap<>();
+            for (Entry<Class<? extends BaseIdentity>, Set<InstanceIdentifier<?>>> entry : change.getRemovals()
+                    .entrySet()) {
+                RpcContextIdentifier key = RpcContextIdentifier.contextFor(type, entry.getKey());
+                removals.put(key, entry.getValue());
+            }
+            RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> toPublish = RoutingUtils
+                    .<RpcContextIdentifier, InstanceIdentifier<?>> change(announcements, removals);
+            for (ListenerRegistration<RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> listener : routeChangeListeners) {
+                try {
+                    listener.getInstance().onRouteChange(toPublish);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public static class RpcProxyRegistration<T extends RpcService> extends AbstractObjectRegistration<T> implements
+            RpcRegistration<T> {
+
+        private final Class<T> serviceType;
+        private RpcProviderRegistryImpl registry;
+
+        public RpcProxyRegistration(Class<T> type, T service, RpcProviderRegistryImpl registry) {
+            super(service);
+            serviceType = type;
+        }
+
+        @Override
+        public Class<T> getServiceType() {
+            return serviceType;
+        }
+
+        @Override
+        protected void removeRegistration() {
+            if (registry != null) {
+                T publicProxy = registry.getRpcService(serviceType);
+                RpcService currentDelegate = RuntimeCodeHelper.getDelegate(publicProxy);
+                if (currentDelegate == getInstance()) {
+                    RuntimeCodeHelper.setDelegate(publicProxy, null);
+                }
+                registry = null;
+            }
+        }
+    }
+}
@@ -1,42 +1,78 @@
 package org.opendaylight.controller.sal.binding.impl.connect.dom;
 
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
+
 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.DataCommitHandler.DataCommitTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.controller.sal.binding.spi.RpcContextIdentifier;
+import org.opendaylight.controller.sal.binding.spi.RpcRouter;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BindingIndependentDataServiceConnector implements //
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+
+import static com.google.common.base.Preconditions.*;
+import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.*;
+
+public class BindingIndependentConnector implements //
         RuntimeDataProvider, //
-        Provider, AutoCloseable {
+        Provider, //
+        AutoCloseable {
 
-    private final Logger LOG = LoggerFactory.getLogger(BindingIndependentDataServiceConnector.class);
+    private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
 
     private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
 
@@ -59,26 +95,41 @@ public class BindingIndependentDataServiceConnector implements //
 
     private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
 
+    private RpcProvisionRegistry biRpcRegistry;
+    private RpcProviderRegistryImpl baRpcRegistry;
+
+    private ListenerRegistration<DomToBindingRpcForwardingManager> domToBindingRpcManager;
+    // private ListenerRegistration<BindingToDomRpcForwardingManager>
+    // bindingToDomRpcManager;
+
+    private Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
+
+        @Override
+        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(InstanceIdentifier<?> input) {
+            return mappingService.toDataDom(input);
+        }
+
+    };
+
     @Override
     public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
         try {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
-            
-            
+
             CompositeNode result = biDataService.readOperationalData(biPath);
             Class<? extends DataObject> targetType = path.getTargetType();
-            
-            if(Augmentation.class.isAssignableFrom(targetType)) {
+
+            if (Augmentation.class.isAssignableFrom(targetType)) {
                 path = mappingService.fromDataDom(biPath);
                 Class<? extends Augmentation<?>> augmentType = (Class<? extends Augmentation<?>>) targetType;
                 DataObject parentTo = mappingService.dataObjectFromDataDom(path, result);
-                if(parentTo instanceof Augmentable<?>) {
+                if (parentTo instanceof Augmentable<?>) {
                     return (DataObject) ((Augmentable) parentTo).getAugmentation(augmentType);
                 }
-                
+
             }
             return mappingService.dataObjectFromDataDom(path, result);
-            
+
         } catch (DeserializationException e) {
             throw new IllegalStateException(e);
         }
@@ -183,11 +234,24 @@ public class BindingIndependentDataServiceConnector implements //
         this.baDataService = baDataService;
     }
 
+    public RpcProviderRegistry getRpcRegistry() {
+        return baRpcRegistry;
+    }
+
+    public void setRpcRegistry(RpcProviderRegistryImpl rpcRegistry) {
+        this.baRpcRegistry = rpcRegistry;
+    }
+
     public void start() {
         baDataService.registerDataReader(ROOT, this);
         baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
         biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
         baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
+
+        if (baRpcRegistry != null && biRpcRegistry != null) {
+            domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(new DomToBindingRpcForwardingManager());
+
+        }
     }
 
     public void setMappingService(BindingIndependentMappingService mappingService) {
@@ -205,6 +269,14 @@ public class BindingIndependentDataServiceConnector implements //
         start();
     }
 
+    public <T extends RpcService> void onRpcRouterCreated(Class<T> serviceType, RpcRouter<T> router) {
+
+    }
+
+    public void setDomRpcRegistry(RpcProvisionRegistry registry) {
+        biRpcRegistry = registry;
+    }
+
     @Override
     public void close() throws Exception {
         if (baCommitHandlerRegistration != null) {
@@ -358,4 +430,204 @@ public class BindingIndependentDataServiceConnector implements //
             return forwardedTransaction;
         }
     }
+
+    private class DomToBindingRpcForwardingManager implements
+            RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>> {
+
+        private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
+
+        @Override
+        public void onRouteChange(RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+            for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
+                bindingRoutesAdded(entry);
+            }
+        }
+
+        private void bindingRoutesAdded(Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
+            Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
+            Class<? extends RpcService> service = entry.getKey().getRpcService();
+            if (context != null) {
+                getRpcForwarder(service, context).registerPaths(context, service, entry.getValue());
+            }
+        }
+
+        private DomToBindingRpcForwarder getRpcForwarder(Class<? extends RpcService> service,
+                Class<? extends BaseIdentity> context) {
+            DomToBindingRpcForwarder potential = forwarders.get(service);
+            if (potential != null) {
+                return potential;
+            }
+            if (context == null) {
+                potential = new DomToBindingRpcForwarder(service);
+            } else {
+                potential = new DomToBindingRpcForwarder(service, context);
+            }
+            forwarders.put(service, potential);
+            return potential;
+        }
+
+    }
+
+    private class DomToBindingRpcForwarder implements RpcImplementation {
+
+        private final Set<QName> supportedRpcs;
+        private final WeakReference<Class<? extends RpcService>> rpcServiceType;
+        private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
+
+        public DomToBindingRpcForwarder(Class<? extends RpcService> service) {
+            this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
+            this.supportedRpcs = mappingService.getRpcQNamesFor(service);
+            for (QName rpc : supportedRpcs) {
+                biRpcRegistry.addRpcImplementation(rpc, this);
+            }
+            registrations = ImmutableSet.of();
+        }
+
+        public DomToBindingRpcForwarder(Class<? extends RpcService> service, Class<? extends BaseIdentity> context) {
+            this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
+            this.supportedRpcs = mappingService.getRpcQNamesFor(service);
+            registrations = new HashSet<>();
+            for (QName rpc : supportedRpcs) {
+                registrations.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
+            }
+            registrations = ImmutableSet.copyOf(registrations);
+        }
+
+        public void registerPaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
+                Set<InstanceIdentifier<?>> set) {
+            QName ctx = BindingReflections.findQName(context);
+            for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
+                    toDOMInstanceIdentifier)) {
+                for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
+                    reg.registerPath(ctx, path);
+                }
+            }
+        }
+
+        public void removePaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
+                Set<InstanceIdentifier<?>> set) {
+            QName ctx = BindingReflections.findQName(context);
+            for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
+                    toDOMInstanceIdentifier)) {
+                for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
+                    reg.unregisterPath(ctx, path);
+                }
+            }
+        }
+
+        @Override
+        public Set<QName> getSupportedRpcs() {
+            return supportedRpcs;
+        }
+
+        @Override
+        public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode domInput) {
+            checkArgument(rpc != null);
+            checkArgument(domInput != null);
+
+            Class<? extends RpcService> rpcType = rpcServiceType.get();
+            checkState(rpcType != null);
+            RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
+            checkState(rpcService != null);
+            CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
+            try {
+                return resolveInvocationStrategy(rpc, rpcType).invokeOn(rpcService, domUnwrappedInput);
+            } catch (Exception e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc,
+                final Class<? extends RpcService> rpcType) throws Exception {
+            return ClassLoaderUtils.withClassLoader(rpcType.getClassLoader(), new Callable<RpcInvocationStrategy>() {
+                @Override
+                public RpcInvocationStrategy call() throws Exception {
+                    String methodName = BindingMapping.getMethodName(rpc);
+                    Method targetMethod = null;
+                    for (Method possibleMethod : rpcType.getMethods()) {
+                        if (possibleMethod.getName().equals(methodName)
+                                && BindingReflections.isRpcMethod(possibleMethod)) {
+                            targetMethod = possibleMethod;
+                            break;
+                        }
+                    }
+                    checkState(targetMethod != null, "Rpc method not found");
+                    Optional<Class<?>> outputClass = BindingReflections.resolveRpcOutputClass(targetMethod);
+                    Optional<Class<? extends DataContainer>> inputClass = BindingReflections
+                            .resolveRpcInputClass(targetMethod);
+
+                    RpcInvocationStrategy strategy = null;
+                    if (outputClass.isPresent()) {
+                        if (inputClass.isPresent()) {
+                            strategy = new DefaultInvocationStrategy(targetMethod, outputClass.get(), inputClass.get());
+                        } else {
+                            strategy = new NoInputNoOutputInvocationStrategy(targetMethod);
+                        }
+                    } else {
+                        strategy = null;
+                    }
+                    return strategy;
+                }
+
+            });
+        }
+    }
+
+    private abstract class RpcInvocationStrategy {
+
+        protected final Method targetMethod;
+
+        public RpcInvocationStrategy(Method targetMethod) {
+            this.targetMethod = targetMethod;
+        }
+
+        public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
+                throws Exception;
+
+        public RpcResult<CompositeNode> invokeOn(RpcService rpcService, CompositeNode domInput) throws Exception {
+            return uncheckedInvoke(rpcService, domInput);
+        }
+    }
+
+    private class DefaultInvocationStrategy extends RpcInvocationStrategy {
+
+        @SuppressWarnings("rawtypes")
+        private WeakReference<Class> inputClass;
+
+        @SuppressWarnings("rawtypes")
+        private WeakReference<Class> outputClass;
+
+        public DefaultInvocationStrategy(Method targetMethod, Class<?> outputClass,
+                Class<? extends DataContainer> inputClass) {
+            super(targetMethod);
+            this.outputClass = new WeakReference(outputClass);
+            this.inputClass = new WeakReference(inputClass);
+        }
+
+        @Override
+        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
+            Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
+            if (result == null) {
+                return Rpcs.getRpcResult(false);
+            }
+            RpcResult<?> bindingResult = result.get();
+            return Rpcs.getRpcResult(true);
+        }
+
+    }
+
+    private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
+
+        public NoInputNoOutputInvocationStrategy(Method targetMethod) {
+            super(targetMethod);
+        }
+
+        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
+            Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
+            RpcResult<Void> bindingResult = result.get();
+            return Rpcs.getRpcResult(bindingResult.isSuccessful(), bindingResult.getErrors());
+        }
+
+    }
 }
index b1983fe224d89da96f4445efa86469cc0e0e6b9d..e16ae48ef4af289d4f6ebcd170f886670e35a97f 100644 (file)
@@ -1,10 +1,13 @@
 package org.opendaylight.controller.sal.binding.impl.connect.dom;
 
 import java.util.Map.Entry;
+import java.util.Set;
 
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 public interface BindingIndependentMappingService {
@@ -19,5 +22,9 @@ public interface BindingIndependentMappingService {
     DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) throws DeserializationException;
 
     InstanceIdentifier<?> fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry)  throws DeserializationException;
+    
+    Set<QName> getRpcQNamesFor(Class<? extends RpcService> service);
+
+    DataContainer dataObjectFromDataDom(Class<? extends DataContainer> inputClass, CompositeNode domInput);
 
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RoutingContext.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RoutingContext.java
new file mode 100644 (file)
index 0000000..49e056b
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.spi;
+
+public class RoutingContext {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcContextIdentifier.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcContextIdentifier.java
new file mode 100644 (file)
index 0000000..33569eb
--- /dev/null
@@ -0,0 +1,65 @@
+package org.opendaylight.controller.sal.binding.spi;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public final  class RpcContextIdentifier implements Immutable{
+
+    public final Class<? extends RpcService> rpcService;
+    public final Class<? extends BaseIdentity> routingContext;
+   
+    private RpcContextIdentifier(Class<? extends RpcService> rpcService, Class<? extends BaseIdentity> routingContext) {
+        super();
+        this.rpcService = rpcService;
+        this.routingContext = routingContext;
+    }
+
+    public Class<? extends RpcService> getRpcService() {
+        return rpcService;
+    }
+
+    public Class<? extends BaseIdentity> getRoutingContext() {
+        return routingContext;
+    }
+    
+    public static final RpcContextIdentifier contextForGlobalRpc(Class<? extends RpcService> serviceType) {
+        return new RpcContextIdentifier(serviceType, null);
+    }
+    
+    public static final RpcContextIdentifier contextFor(Class<? extends RpcService> serviceType,Class<? extends BaseIdentity> routingContext) {
+        return new RpcContextIdentifier(serviceType, routingContext);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((routingContext == null) ? 0 : routingContext.hashCode());
+        result = prime * result + ((rpcService == null) ? 0 : rpcService.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        RpcContextIdentifier other = (RpcContextIdentifier) obj;
+        if (routingContext == null) {
+            if (other.routingContext != null)
+                return false;
+        } else if (!routingContext.equals(other.routingContext))
+            return false;
+        if (rpcService == null) {
+            if (other.rpcService != null)
+                return false;
+        } else if (!rpcService.equals(other.rpcService))
+            return false;
+        return true;
+    }
+
+}
index 7db90b62fdefd090910eb0a6ecdbe1df8ca597be..621d048dfd771694d5b479588980140e9e873066 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.controller.sal.binding.spi;
 
 import java.util.Set;
 
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcImplementation;
@@ -26,7 +29,8 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
  *            Type of RpcService for which router provides routing information
  *            and route selection.
  */
-public interface RpcRouter<T extends RpcService> extends RpcImplementation{
+public interface RpcRouter<T extends RpcService> extends //
+        RouteChangePublisher<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
 
     /**
      * Returns a type of RpcService which is served by this instance of router.
@@ -72,12 +76,11 @@ public interface RpcRouter<T extends RpcService> extends RpcImplementation{
      * @return default instance responsible for processing RPCs.
      */
     T getDefaultService();
-    
-    /**
-     * 
-     */
-    void setDefaultService(T service);
 
     Set<Class<? extends BaseIdentity>> getContexts();
+    
+    RoutedRpcRegistration<T> addRoutedRpcImplementation(T service);
+    
+    RpcRegistration<T> registerDefaultService(T service);
 
 }
index a7a70c2839ca848bae7a0e45adc702c620ec4bcb..633506fec65b3ea4f186e1ba8520aed98750f0b1 100644 (file)
@@ -12,7 +12,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
 import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
 import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
index 1a97bd693a19c96ab295cb8f88cd63e213dc43f3..6f0db4cd8d3635d0cd43bea0e943dd7d5555fdd2 100644 (file)
@@ -61,13 +61,10 @@ public class RuntimeCodeGeneratorTest {
 
     @Test
     public void testGenerateRouter() throws Exception {
-        RpcRouter<FooService> product = codeGenerator.getRouterFor(FooService.class);
+        RpcRouter<FooService> product = codeGenerator.getRouterFor(FooService.class,"test");
         assertNotNull(product);
         assertNotNull(product.getInvocationProxy());
 
-        assertNotNull(product.getSupportedInputs());
-        assertTrue(product.getSupportedInputs().contains(SimpleInput.class));
-        assertTrue(product.getSupportedInputs().contains(InheritedContextInput.class));
         assertEquals("2 fields should be generated.", 2, product.getInvocationProxy().getClass().getFields().length);
 
         verifyRouting(product);
index 6d1a6991451135073f42b4a1afa8ff50ab853958..5abc8fe0f7931c443507f496c1f21f8e6a08852b 100644 (file)
@@ -1,5 +1,9 @@
 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.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -9,24 +13,23 @@ import java.util.Map;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.controller.sal.binding.test.AugmentationVerifier;
 import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.test.AugmentationVerifier;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
-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.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.Duration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.DurationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder;
@@ -38,10 +41,6 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-import com.google.common.collect.FluentIterable;
-
-import static org.junit.Assert.*;
-
 public class MultipleAugmentationPuts extends AbstractDataServiceTest implements DataChangeListener {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
@@ -86,35 +85,35 @@ public class MultipleAugmentationPuts extends AbstractDataServiceTest implements
         verifyNode(nodes, flowCapableNode).assertHasAugmentation(FlowCapableNode.class);
         ;
         assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
-        Node meterStatsNode = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics());
-        commitNodeAndVerifyTransaction(meterStatsNode);
-
-        assertNotNull(receivedChangeEvent);
-        verifyNode((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(), meterStatsNode);
-
-        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
-
-        Node mergedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
-
-        AugmentationVerifier.from(mergedNode) //
-                .assertHasAugmentation(FlowCapableNode.class) //
-                .assertHasAugmentation(NodeMeterStatistics.class);
-
-        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
-
-        Node meterStatsNodeWithDuration = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics(5, true));
-        commitNodeAndVerifyTransaction(meterStatsNodeWithDuration);
-
-        
-        Node nodeWithUpdatedList = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
-        AugmentationVerifier.from(nodeWithUpdatedList) //
-                .assertHasAugmentation(FlowCapableNode.class) //
-                .assertHasAugmentation(NodeMeterStatistics.class);
-        
-        List<MeterStats> meterStats = nodeWithUpdatedList.getAugmentation(NodeMeterStatistics.class).getMeterStatistics().getMeterStats();
-        assertNotNull(meterStats);
-        assertFalse(meterStats.isEmpty());
-        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+//        Node meterStatsNode = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics());
+//        commitNodeAndVerifyTransaction(meterStatsNode);
+//
+//        assertNotNull(receivedChangeEvent);
+//        verifyNode((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(), meterStatsNode);
+//
+//        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+//
+//        Node mergedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+//
+//        AugmentationVerifier.from(mergedNode) //
+//                .assertHasAugmentation(FlowCapableNode.class) //
+//                .assertHasAugmentation(NodeMeterStatistics.class);
+//
+//        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+//
+//        Node meterStatsNodeWithDuration = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics(5, true));
+//        commitNodeAndVerifyTransaction(meterStatsNodeWithDuration);
+//
+//        
+//        Node nodeWithUpdatedList = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+//        AugmentationVerifier.from(nodeWithUpdatedList) //
+//                .assertHasAugmentation(FlowCapableNode.class) //
+//                .assertHasAugmentation(NodeMeterStatistics.class);
+//        
+//        List<MeterStats> meterStats = nodeWithUpdatedList.getAugmentation(NodeMeterStatistics.class).getMeterStatistics().getMeterStats();
+//        assertNotNull(meterStats);
+//        assertFalse(meterStats.isEmpty());
+//        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
         testNodeRemove();
     }
 
@@ -186,7 +185,7 @@ public class MultipleAugmentationPuts extends AbstractDataServiceTest implements
 
             stats.add(statistic.build());
         }
-        meterStats.setMeterStats(stats);
+       // meterStats.setMeterStats(stats);
         nmsb.setMeterStatistics(meterStats.build());
         return nmsb.build();
     }
index 4e611c5fe2131651a0ccd6bf5744b57c72acd2d4..d4d27a14eceb68c3df38c8b826ae23845fb76e69 100644 (file)
@@ -7,15 +7,22 @@ import java.util.Set;
 
 import javassist.ClassPool;
 
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.controller.sal.binding.impl.BindingAwareBrokerImpl;
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
 import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.RpcRouterImpl;
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -31,7 +38,7 @@ import com.google.common.util.concurrent.MoreExecutors;
 
 import static com.google.common.base.Preconditions.*;
 
-public class BindingTestContext {
+public class BindingTestContext implements AutoCloseable {
     
     
     public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
@@ -40,10 +47,15 @@ public class BindingTestContext {
     private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
     
     private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
+    
+    
+    private BindingAwareBrokerImpl baBrokerImpl;
     private DataBrokerImpl baDataImpl;
+    private NotificationBrokerImpl baNotifyImpl;
+    private BindingIndependentConnector baConnectDataServiceImpl;
+
     private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
-    
-    private BindingIndependentDataServiceConnector connectorServiceImpl;
+    private BrokerImpl biBrokerImpl;
     private HashMapDataStore rawDataStore;
     private SchemaAwareDataStoreAdapter schemaAwareDataStore;
     private DataStoreStatsWrapper dataStoreStats;
@@ -56,6 +68,7 @@ public class BindingTestContext {
     private final ClassPool classPool;
 
     private final boolean startWithSchema;
+
     
     protected BindingTestContext(ListeningExecutorService executor, ClassPool classPool, boolean startWithSchema) {
         this.executor = executor;
@@ -93,15 +106,29 @@ public class BindingTestContext {
         baDataImpl.setExecutor(executor);
     }
     
+    public void startBindingBroker() {
+        checkState(executor != null,"Executor needs to be set");
+        checkState(baDataImpl != null,"Binding Data Broker must be started");
+        checkState(baNotifyImpl != null, "Notification Service must be started");
+        baBrokerImpl = new BindingAwareBrokerImpl("test",null);
+        
+        baBrokerImpl.setDataBroker(baDataImpl);
+        baBrokerImpl.setNotifyBroker(baNotifyImpl);
+        
+        baBrokerImpl.start();
+    }
+    
     public void startBindingToDomDataConnector() {
         checkState(baDataImpl != null,"Binding Data Broker needs to be started");
         checkState(biDataImpl != null,"DOM Data Broker needs to be started.");
         checkState(mappingServiceImpl != null,"DOM Mapping Service needs to be started.");
-        connectorServiceImpl = new BindingIndependentDataServiceConnector();
-        connectorServiceImpl.setBaDataService(baDataImpl);
-        connectorServiceImpl.setBiDataService(biDataImpl);
-        connectorServiceImpl.setMappingService(mappingServiceImpl);
-        connectorServiceImpl.start();
+        baConnectDataServiceImpl = new BindingIndependentConnector();
+        baConnectDataServiceImpl.setRpcRegistry(baBrokerImpl);
+        baConnectDataServiceImpl.setDomRpcRegistry(getDomRpcRegistry());
+        baConnectDataServiceImpl.setBaDataService(baDataImpl);
+        baConnectDataServiceImpl.setBiDataService(biDataImpl);
+        baConnectDataServiceImpl.setMappingService(mappingServiceImpl);
+        baConnectDataServiceImpl.start();
     }
     
     public void startBindingToDomMappingService() {
@@ -149,8 +176,11 @@ public class BindingTestContext {
     
     public void start() {
         startBindingDataBroker();
+        startBindingNotificationBroker();
+        startBindingBroker();
         startDomDataBroker();
         startDomDataStore();
+        startDomBroker();
         startBindingToDomMappingService();
         startBindingToDomDataConnector();
         if(startWithSchema) {
@@ -158,6 +188,19 @@ public class BindingTestContext {
         }
     }
 
+    private void startDomBroker() {
+        checkState(executor != null);
+        biBrokerImpl = new BrokerImpl();
+        biBrokerImpl.setExecutor(executor);
+        biBrokerImpl.setRouter(new RpcRouterImpl("test"));
+    }
+
+    public void startBindingNotificationBroker() {
+        checkState(executor != null);
+        baNotifyImpl = new NotificationBrokerImpl(executor);
+        
+    }
+
     public void loadYangSchemaFromClasspath() {
         String[] files = getAllYangFilesOnClasspath();
         updateYangSchema(files);
@@ -196,4 +239,24 @@ public class BindingTestContext {
                 dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
                 dataStoreStats.getRequestCommitAverageTime());
     }
+
+    public RpcProviderRegistry getBindingRpcRegistry() {
+        return baBrokerImpl;
+    }
+
+    public RpcProvisionRegistry getDomRpcRegistry() {
+        if(biBrokerImpl == null) {
+            return null;
+        }
+        return biBrokerImpl.getRouter();
+    }
+    
+    public RpcImplementation getDomRpcInvoker() {
+        return biBrokerImpl.getRouter();
+    }
+    
+    @Override
+    public void close() throws Exception {
+        
+    }
 }
diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java
new file mode 100644 (file)
index 0000000..1304f0d
--- /dev/null
@@ -0,0 +1,210 @@
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+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.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
+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.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.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._3.match.Ipv4MatchBuilder;
+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.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+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;
+
+import static org.junit.Assert.*;
+
+public class FlagsSerializationTest extends AbstractDataServiceTest {
+
+    private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+    private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
+    private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
+    private static final long FLOW_ID = 1234;
+    private static final short TABLE_ID = (short)0;
+    private static final String NODE_ID = "node:1";
+
+    private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+    private static final FlowKey FLOW_KEY = new FlowKey(new FlowId(FLOW_ID));
+    private static final TableKey TABLE_KEY = new TableKey(TABLE_ID);
+    
+    private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+            NODE_ID);
+
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
+            .child(Node.class, NODE_KEY).toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+            .toInstance();
+    private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
+
+
+
+//    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
+//    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+//            
+//            .node(Flows.QNAME) //
+//            .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
+//            .toInstance();
+    private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
+    InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) //
+            .augmentation(FlowCapableNode.class)
+            .child(Table.class,TABLE_KEY)
+            .child(Flow.class, FLOW_KEY) //
+            .toInstance();
+    private static final QName FLOW_FLAGS_QNAME = QName.create(Flow.QNAME, "flags");
+
+    @Test
+    public void testIndirectGeneration() throws Exception {
+
+        FlowModFlags checkOverlapFlags = new FlowModFlags(true,false,false,false,false);
+        ImmutableSet<String> domCheckOverlapFlags = ImmutableSet.<String>of("CHECK_OVERLAP");
+        testFlags(checkOverlapFlags,domCheckOverlapFlags);
+        
+        
+        
+        FlowModFlags allFalseFlags = new FlowModFlags(false,false,false,false,false);
+        ImmutableSet<String> domAllFalseFlags = ImmutableSet.<String>of();
+        testFlags(allFalseFlags,domAllFalseFlags);
+        
+        FlowModFlags allTrueFlags = new FlowModFlags(true,true,true,true,true);
+        ImmutableSet<String> domAllTrueFlags = ImmutableSet.<String>of("CHECK_OVERLAP","NO_BYT_COUNTS", "NO_PKT_COUNTS", "RESET_COUNTS", "SEND_FLOW_REM");
+        testFlags(allTrueFlags,domAllTrueFlags);
+        
+        FlowModFlags nullFlags = null;
+        ImmutableSet<String> domNullFlags = null;
+        testFlags(null,null);
+        
+        
+
+    }
+
+    private void testFlags(FlowModFlags flagsToTest, ImmutableSet<String> domFlags) throws Exception {
+        Flow flow = createFlow(flagsToTest);
+        assertNotNull(flow);
+        
+        CompositeNode domFlow = biDataService.readConfigurationData(mappingService.toDataDom(FLOW_INSTANCE_ID_BA));
+        
+        assertNotNull(domFlow);
+        org.opendaylight.yangtools.yang.data.api.Node<?> readedFlags = domFlow.getFirstSimpleByName(FLOW_FLAGS_QNAME);
+        
+        if(domFlags != null) {
+            assertNotNull(readedFlags);
+            assertEquals(domFlags,readedFlags.getValue());
+        } else {
+            assertNull(readedFlags);
+        }
+        assertEquals(flagsToTest, flow.getFlags());
+        
+        DataModificationTransaction transaction = baDataService.beginTransaction();
+        transaction.removeConfigurationData(FLOW_INSTANCE_ID_BA);
+        RpcResult<TransactionStatus> result = transaction.commit().get();
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+           
+    }
+
+    private Flow createFlow(FlowModFlags flagsToTest) 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.setFlags(flagsToTest);
+        
+        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());
+        return (Flow) baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA);
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java
new file mode 100644 (file)
index 0000000..92a0a3a
--- /dev/null
@@ -0,0 +1,159 @@
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.concurrent.Future;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
+import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
+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.inventory.rev130819.NodeContext;
+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.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+
+import static junit.framework.Assert.*;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class CrossBrokerRpcTest {
+
+    protected RpcProviderRegistry baRpcRegistry;
+    protected RpcProvisionRegistry biRpcRegistry;
+    private BindingTestContext testContext;
+    private RpcImplementation biRpcInvoker;
+    private MessageCapturingFlowService flowService;
+
+    public static final NodeId NODE_A = new NodeId("a");
+    public static final NodeId NODE_B = new NodeId("b");
+    public static final NodeId NODE_C = new NodeId("c");
+    public static final NodeId NODE_D = new NodeId("d");
+
+    public static final InstanceIdentifier<Node> BA_NODE_A_ID = createBANodeIdentifier(NODE_A);
+    public static final InstanceIdentifier<Node> BA_NODE_B_ID = createBANodeIdentifier(NODE_B);
+    public static final InstanceIdentifier<Node> BA_NODE_C_ID = createBANodeIdentifier(NODE_C);
+    public static final InstanceIdentifier<Node> BA_NODE_D_ID = createBANodeIdentifier(NODE_D);
+
+    public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier BI_NODE_A_ID = createBINodeIdentifier(NODE_A);
+    public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier BI_NODE_B_ID = createBINodeIdentifier(NODE_B);
+    public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier BI_NODE_C_ID = createBINodeIdentifier(NODE_C);
+    public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier BI_NODE_D_ID = createBINodeIdentifier(NODE_D);
+
+    private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+    private static final QName ADD_FLOW_QNAME = QName.create(NodeFlowRemoved.QNAME, "add-flow");
+    private static final QName REMOVE_FLOW_QNAME = QName.create(NodeFlowRemoved.QNAME, "remove-flow");
+    private static final QName UPDATE_FLOW_QNAME = QName.create(NodeFlowRemoved.QNAME, "update-flow");
+
+    @Before
+    public void setup() {
+        BindingBrokerTestFactory testFactory = new BindingBrokerTestFactory();
+        testFactory.setExecutor(MoreExecutors.sameThreadExecutor());
+        testFactory.setStartWithParsedSchema(true);
+        testContext = testFactory.getTestContext();
+
+        testContext.start();
+        baRpcRegistry = testContext.getBindingRpcRegistry();
+        biRpcRegistry = testContext.getDomRpcRegistry();
+        biRpcInvoker = testContext.getDomRpcInvoker();
+        assertNotNull(baRpcRegistry);
+        assertNotNull(biRpcRegistry);
+
+        flowService = MessageCapturingFlowService.create(baRpcRegistry);
+
+    }
+
+    @Test
+    public void bindingRoutedRpcProvider_DomInvokerTest() {
+
+        flowService//
+                .registerPath(NodeContext.class, BA_NODE_A_ID) //
+                .registerPath(NodeContext.class, BA_NODE_B_ID) //
+                .setAddFlowResult(addFlowResult(true, 10));
+
+        SalFlowService baFlowInvoker = baRpcRegistry.getRpcService(SalFlowService.class);
+        assertNotSame(flowService, baFlowInvoker);
+
+        AddFlowInput addFlowA = addFlow(BA_NODE_A_ID) //
+                .setPriority(100).setBarrier(true).build();
+
+        CompositeNode addFlowDom = toDomRpc(ADD_FLOW_QNAME, addFlowA);
+        assertNotNull(addFlowDom);
+        RpcResult<CompositeNode> domResult = biRpcInvoker.invokeRpc(ADD_FLOW_QNAME, addFlowDom);
+        assertNotNull(domResult);
+        assertTrue("DOM result is successful.", domResult.isSuccessful());
+        assertTrue("Bidning Add Flow RPC was captured.", flowService.getReceivedAddFlows().containsKey(BA_NODE_A_ID));
+        assertEquals(addFlowA, flowService.getReceivedAddFlows().get(BA_NODE_A_ID).iterator().next());
+    }
+
+    public void bindingRpcInvoker_DomRoutedProviderTest() {
+
+    }
+
+    private CompositeNode toDomRpcInput(DataObject addFlowA) {
+        return testContext.getBindingToDomMappingService().toDataDom(addFlowA);
+    }
+
+    @After
+    public void teardown() throws Exception {
+        testContext.close();
+    }
+
+    private static InstanceIdentifier<Node> createBANodeIdentifier(NodeId node) {
+        return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(node)).toInstance();
+    }
+
+    private static org.opendaylight.yangtools.yang.data.api.InstanceIdentifier createBINodeIdentifier(NodeId node) {
+        return org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().node(Nodes.QNAME)
+                .nodeWithKey(Node.QNAME, NODE_ID_QNAME, node.getValue()).toInstance();
+    }
+
+    private Future<RpcResult<AddFlowOutput>> addFlowResult(boolean success, long xid) {
+        AddFlowOutput output = new AddFlowOutputBuilder() //
+                .setTransactionId(new TransactionId(BigInteger.valueOf(xid))).build();
+        RpcResult<AddFlowOutput> result = Rpcs.getRpcResult(success, output, ImmutableList.<RpcError> of());
+        return Futures.immediateFuture(result);
+    }
+
+    private static AddFlowInputBuilder addFlow(InstanceIdentifier<Node> nodeId) {
+        AddFlowInputBuilder builder = new AddFlowInputBuilder();
+        builder.setNode(new NodeRef(nodeId));
+        return builder;
+    }
+
+    private CompositeNode toDomRpc(QName rpcName, AddFlowInput addFlowA) {
+        return new CompositeNodeTOImpl(rpcName, null,
+                Collections.<org.opendaylight.yangtools.yang.data.api.Node<?>> singletonList(toDomRpcInput(addFlowA)));
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java
new file mode 100644 (file)
index 0000000..74f0781
--- /dev/null
@@ -0,0 +1,122 @@
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static junit.framework.Assert.assertNotNull;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
+public class MessageCapturingFlowService implements SalFlowService, AutoCloseable {
+
+    private Future<RpcResult<AddFlowOutput>> addFlowResult;
+    private Future<RpcResult<RemoveFlowOutput>> removeFlowResult;
+    private Future<RpcResult<UpdateFlowOutput>> updateFlowResult;
+
+    private final Multimap<InstanceIdentifier<?>, AddFlowInput> receivedAddFlows = HashMultimap.create();
+    private final Multimap<InstanceIdentifier<?>, RemoveFlowInput> receivedRemoveFlows = HashMultimap.create();
+    private final Multimap<InstanceIdentifier<?>, UpdateFlowInput> receivedUpdateFlows = HashMultimap.create();
+    private RoutedRpcRegistration<SalFlowService> registration;
+
+    @Override
+    public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput arg0) {
+        receivedAddFlows.put(arg0.getNode().getValue(), arg0);
+        return addFlowResult;
+    }
+
+    @Override
+    public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput arg0) {
+        receivedRemoveFlows.put(arg0.getNode().getValue(), arg0);
+        return removeFlowResult;
+    }
+
+    @Override
+    public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput arg0) {
+        receivedUpdateFlows.put(arg0.getNode().getValue(), arg0);
+        return updateFlowResult;
+    }
+
+    public Future<RpcResult<AddFlowOutput>> getAddFlowResult() {
+        return addFlowResult;
+    }
+
+    public MessageCapturingFlowService setAddFlowResult(Future<RpcResult<AddFlowOutput>> addFlowResult) {
+        this.addFlowResult = addFlowResult;
+        return this;
+    }
+
+    public Future<RpcResult<RemoveFlowOutput>> getRemoveFlowResult() {
+        return removeFlowResult;
+    }
+
+    public MessageCapturingFlowService setRemoveFlowResult(Future<RpcResult<RemoveFlowOutput>> removeFlowResult) {
+        this.removeFlowResult = removeFlowResult;
+        return this;
+    }
+
+    public Future<RpcResult<UpdateFlowOutput>> getUpdateFlowResult() {
+        return updateFlowResult;
+    }
+
+    public MessageCapturingFlowService setUpdateFlowResult(Future<RpcResult<UpdateFlowOutput>> updateFlowResult) {
+        this.updateFlowResult = updateFlowResult;
+        return this;
+    }
+
+    public Multimap<InstanceIdentifier<?>, AddFlowInput> getReceivedAddFlows() {
+        return receivedAddFlows;
+    }
+
+    public Multimap<InstanceIdentifier<?>, RemoveFlowInput> getReceivedRemoveFlows() {
+        return receivedRemoveFlows;
+    }
+
+    public Multimap<InstanceIdentifier<?>, UpdateFlowInput> getReceivedUpdateFlows() {
+        return receivedUpdateFlows;
+    }
+
+    public MessageCapturingFlowService registerTo(RpcProviderRegistry registry) {
+        registration = registry.addRoutedRpcImplementation(SalFlowService.class, this);
+        assertNotNull(registration);
+        return this;
+    }
+
+    public void close() throws Exception {
+        registration.close();
+    }
+
+    public MessageCapturingFlowService registerPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+        registration.registerPath(context, path);
+        return this;
+    }
+
+    public MessageCapturingFlowService unregisterPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+        registration.unregisterPath(context, path);
+        return this;
+    }
+    
+    public static MessageCapturingFlowService create() {
+        return new MessageCapturingFlowService();
+    }
+    
+    public static MessageCapturingFlowService create(RpcProviderRegistry registry) {
+        MessageCapturingFlowService ret = new MessageCapturingFlowService();
+        ret.registerTo(registry);
+        return ret;
+    }
+    
+    
+}
\ No newline at end of file
index 15616215d35f13950c08167abe7b687490ba1078..112b57cd33fc2fbb43c08059a5274f9647574084 100644 (file)
@@ -54,6 +54,7 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "config-persister-api").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "netconf-api").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "ietf-netconf-monitoring").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "ietf-netconf-monitoring-extension").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "netconf-monitoring").versionAsInProject(), //
 
                 mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
index 89851c939323ce256585e341a2674d1ad98e259f..bee29a1ad19677820e18e36562bd6892d5be765e 100644 (file)
@@ -4,5 +4,5 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
 
 public interface RouteChangePublisher<C,P> {
 
-    ListenerRegistration<RouteChangeListener<C,P>> registerRouteChangeListener(RouteChangeListener<C,P> listener);
+    <L extends RouteChangeListener<C,P>> ListenerRegistration<L> registerRouteChangeListener(L listener);
 }
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java
new file mode 100644 (file)
index 0000000..60d0cdf
--- /dev/null
@@ -0,0 +1,92 @@
+package org.opendaylight.controller.md.sal.common.impl.routing;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public class RoutingUtils {
+    
+    public static <C,P> RouteChange<C,P> removalChange(C context,P path) {
+        final ImmutableMap<C, Set<P>> announcements = ImmutableMap.<C,Set<P>>of();
+        final ImmutableMap<C, Set<P>> removals = ImmutableMap.<C,Set<P>>of(context, ImmutableSet.of(path));
+        return new RouteChangeImpl<C,P>(announcements, removals);
+    }
+    
+    public static <C,P> RouteChange<C,P> announcementChange(C context,P path) {
+        final ImmutableMap<C, Set<P>> announcements = ImmutableMap.<C,Set<P>>of(context, ImmutableSet.of(path));
+        final ImmutableMap<C, Set<P>> removals = ImmutableMap.<C,Set<P>>of();
+        return new RouteChangeImpl<C,P>(announcements, removals);
+    }
+    
+    
+    public static <C,P> RouteChange<C,P> change(Map<C, Set<P>> announcements,
+            Map<C, Set<P>> removals) {
+        final ImmutableMap<C, Set<P>> immutableAnnouncements = ImmutableMap.<C,Set<P>>copyOf(announcements);
+        final ImmutableMap<C, Set<P>> immutableRemovals = ImmutableMap.<C,Set<P>>copyOf(removals);
+        return new RouteChangeImpl<C,P>(immutableAnnouncements, immutableRemovals);
+    }
+    
+    
+    private static class RouteChangeImpl<C,P> implements RouteChange<C, P> {
+        private final Map<C, Set<P>> removal;
+        private final Map<C, Set<P>> announcement;
+
+        public RouteChangeImpl(ImmutableMap<C, Set<P>> removal, ImmutableMap<C, Set<P>> announcement) {
+            super();
+            this.removal = removal;
+            this.announcement = announcement;
+        }
+
+        @Override
+        public Map<C, Set<P>> getAnnouncements() {
+            return announcement;
+        }
+        
+        @Override
+        public Map<C, Set<P>> getRemovals() {
+            return removal;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((announcement == null) ? 0 : announcement.hashCode());
+            result = prime * result + ((removal == null) ? 0 : removal.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            RouteChangeImpl other = (RouteChangeImpl) obj;
+            if (announcement == null) {
+                if (other.announcement != null)
+                    return false;
+            } else if (!announcement.equals(other.announcement))
+                return false;
+            if (removal == null) {
+                if (other.removal != null) {
+                    return false;
+                }
+            } else if (!removal.equals(other.removal))
+                return false;
+            return true;
+        }
+    }
+
+
+    
+}
index 7e8069a9b38253b3f434918462034d60a74bee34..ff15e72ba6fc3d1106a46bfadd08dfcd2e67bd60 100644 (file)
       <artifactId>concepts</artifactId>
       <version>0.1.1-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
   </dependencies>
 
   <packaging>bundle</packaging>
index 54e1a065f4b45374848bbc53a27b534864d98f7d..356ec8ff7c5ee6e84692970d702910b7bdc8c091 100644 (file)
@@ -11,17 +11,31 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+
+import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
+import com.google.common.collect.ImmutableList;
+
 public class Rpcs {
+    
+    public static <T> RpcResult<T> getRpcResult(boolean successful) {
+        RpcResult<T> ret = new RpcResultTO<T>(successful, null, ImmutableList.<RpcError>of());
+        return ret;
+    }
+    
     public static <T> RpcResult<T> getRpcResult(boolean successful, T result,
             Collection<RpcError> errors) {
         RpcResult<T> ret = new RpcResultTO<T>(successful, result, errors);
         return ret;
     }
 
-    private static class RpcResultTO<T> implements RpcResult<T>, Serializable {
+    public static <T> RpcResult<T> getRpcResult(boolean successful, Collection<RpcError> errors) {
+        return new RpcResultTO<T>(successful, null, errors);
+    }
+    
+    private static class RpcResultTO<T> implements RpcResult<T>, Serializable, Immutable {
 
         private final Collection<RpcError> errors;
         private final T result;
@@ -31,8 +45,7 @@ public class Rpcs {
                 Collection<RpcError> errors) {
             this.successful = successful;
             this.result = result;
-            this.errors = Collections.unmodifiableList(new ArrayList<RpcError>(
-                    errors));
+            this.errors = ImmutableList.copyOf(errors);
         }
 
         @Override
index 7ef594bad94cddd77db1136f6a2e9a311d4203e9..8f179987b9c769e9fb6bab288b4063f40bd3b873 100644 (file)
@@ -29,8 +29,10 @@ import org.slf4j.LoggerFactory
 import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
 import org.opendaylight.yangtools.concepts.ListenerRegistration
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
+import org.opendaylight.controller.sal.core.api.RpcImplementation
 
-public class BrokerImpl implements Broker, AutoCloseable {
+public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private static val log = LoggerFactory.getLogger(BrokerImpl);
 
     // Broker Generic Context
@@ -115,4 +117,12 @@ public class BrokerImpl implements Broker, AutoCloseable {
         deactivator?.close();
     }
     
+    override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
+        router.addRpcImplementation(rpcType,implementation);
+    }
+    
+    override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
+        router.addRoutedRpcImplementation(rpcType,implementation);
+    }
+    
 }
index d8680ce3b4fba50da12903344a4bad551de87075..5ee19a0e8fec876faf5d465ee3a140d373e53cd3 100644 (file)
@@ -15,6 +15,8 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
 import org.slf4j.LoggerFactory
 import org.opendaylight.yangtools.concepts.util.ListenerRegistry
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 
 class RpcRouterImpl implements RpcRouter, Identifiable<String> {
 
@@ -35,6 +37,20 @@ class RpcRouterImpl implements RpcRouter, Identifiable<String> {
     }
 
     override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
+                checkNotNull(rpcType, "Rpc Type should not be null");
+        checkNotNull(implementation, "Implementation should not be null.");
+        val reg = new RoutedRpcRegistrationImpl(rpcType, implementation, this);
+        implementations.put(rpcType, reg)
+
+        for (listener : rpcRegistrationListeners.listeners) {
+            try {
+                listener.instance.onRpcImplementationAdded(rpcType);
+            } catch (Exception e) {
+                log.error("Unhandled exception during invoking listener", e);
+            }
+        }
+
+        return reg;
     }
 
     override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
@@ -102,5 +118,23 @@ class RpcRegistrationImpl extends AbstractObjectRegistration<RpcImplementation>
     override protected removeRegistration() {
         router.remove(this);
     }
+}
+class RoutedRpcRegistrationImpl extends RpcRegistrationImpl implements RoutedRpcRegistration {
+
+
+    new(QName type, RpcImplementation instance, RpcRouterImpl router) {
+        super(type,instance,router)
+    }
 
+    override protected removeRegistration() {
+        router.remove(this);
+    }
+    override registerPath(QName context, InstanceIdentifier path) {
+        //
+        
+    }
+
+    override unregisterPath(QName context, InstanceIdentifier path) {
+        //
+    }
 }
index 4f4fadcc443a755809394998246fccfeb7845aa8..75e96491b68c2bf5ffd93b08412002f846b94b89 100644 (file)
@@ -151,19 +151,20 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         this.schema = null;
     }
 
-    protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified, boolean config) {
+    protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified,
+            boolean config) {
         long startTime = System.nanoTime();
         try {
-        DataSchemaNode node = schemaNodeFor(path);
-        return YangDataOperations.merge(node,stored,modified,config);
+            DataSchemaNode node = schemaNodeFor(path);
+            return YangDataOperations.merge(node, stored, modified, config);
         } finally {
-            //System.out.println("Merge time: " + ((System.nanoTime() - startTime) / 1000.0d));
+            // System.out.println("Merge time: " + ((System.nanoTime() -
+            // startTime) / 1000.0d));
         }
     }
-    
-    
+
     private DataSchemaNode schemaNodeFor(InstanceIdentifier path) {
-        checkState(schema != null,"YANG Schema is not available");
+        checkState(schema != null, "YANG Schema is not available");
         return YangSchemaUtils.getSchemaNode(schema, path);
     }
 
@@ -171,16 +172,16 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             DataModification<InstanceIdentifier, CompositeNode> original) {
         // NOOP for now
         NormalizedDataModification normalized = new NormalizedDataModification(original);
-        for (Entry<InstanceIdentifier,CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
+        for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
             normalized.putConfigurationData(entry.getKey(), entry.getValue());
         }
-        for (Entry<InstanceIdentifier,CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
+        for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
             normalized.putOperationalData(entry.getKey(), entry.getValue());
         }
         for (InstanceIdentifier entry : original.getRemovedConfigurationData()) {
             normalized.removeConfigurationData(entry);
         }
-        for(InstanceIdentifier entry : original.getRemovedOperationalData()) {
+        for (InstanceIdentifier entry : original.getRemovedOperationalData()) {
             normalized.removeOperationalData(entry);
         }
         return normalized;
@@ -284,7 +285,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             }
         }
     }
-    
+
     private class NormalizedDataModification extends AbstractDataModification<InstanceIdentifier, CompositeNode> {
 
         private Object identifier;
@@ -295,12 +296,12 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
             identifier = original;
             status = TransactionStatus.NEW;
         }
-        
+
         @Override
         public Object getIdentifier() {
             return this.identifier;
         }
-        
+
         @Override
         public TransactionStatus getStatus() {
             return status;
@@ -310,18 +311,19 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
         public Future<RpcResult<TransactionStatus>> commit() {
             throw new UnsupportedOperationException("Commit should not be invoked on this");
         }
-        
+
         @Override
-        protected CompositeNode mergeConfigurationData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) {
-            return mergeData(path,stored, modified,true);
+        protected CompositeNode mergeConfigurationData(InstanceIdentifier path, CompositeNode stored,
+                CompositeNode modified) {
+            return mergeData(path, stored, modified, true);
         }
-        
+
         @Override
-        protected CompositeNode mergeOperationalData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) {
+        protected CompositeNode mergeOperationalData(InstanceIdentifier path, CompositeNode stored,
+                CompositeNode modified) {
             // TODO Auto-generated method stub
-            return mergeData(path,stored,modified,false);
+            return mergeData(path, stored, modified, false);
         }
-        
     }
 
 }
index b8e0938a5f0901c9d7b73de541543aa472fca217..c973498e8549888e4b076d7e102c388c6222b9e8 100644 (file)
@@ -37,7 +37,7 @@
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
-      <artifactId>zeromq-routingtable.implementation</artifactId>
+      <artifactId>remoterpc-routingtable.implementation</artifactId>
       <!-- TODO: fix the version. Why is it not MD Sal project version?-->
       <version>0.4.1-SNAPSHOT</version>
     </dependency>
index dd7e36cfb4f8647656a6a0492731dfd730a4f458..dc2fdbf9a05382d19307d6cccb20c918c6c1aafc 100644 (file)
@@ -97,7 +97,7 @@
     </dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
-          <artifactId>zeromq-routingtable.implementation</artifactId>
+          <artifactId>remoterpc-routingtable.implementation</artifactId>
           <version>0.4.1-SNAPSHOT</version>
       </dependency>
       <dependency>
index a42c468c2af27ea5f2cb84887757ed8057a4466f..fb7872f8bcd4e1efdf27be0183fd20176651ac33 100644 (file)
@@ -3,15 +3,38 @@ package org.opendaylight.controller.sal.rest.impl;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.IOException;
-import java.util.*;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 import javax.activation.UnsupportedDataTypeException;
 
 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;
+import org.opendaylight.controller.sal.restconf.impl.RestCodec;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.*;
-import org.opendaylight.yangtools.yang.model.api.*;
-import org.opendaylight.yangtools.yang.model.api.type.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 import com.google.gson.stream.JsonWriter;
@@ -20,6 +43,7 @@ class JsonMapper {
 
     private final Set<LeafListSchemaNode> foundLeafLists = new HashSet<>();
     private final Set<ListSchemaNode> foundLists = new HashSet<>();
+    private final Logger logger = LoggerFactory.getLogger(JsonMapper.class); 
 
     public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
         Preconditions.checkNotNull(writer);
@@ -158,117 +182,42 @@ class JsonMapper {
     private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type,
             DataSchemaNode schema) throws IOException {
 
-        String value = String.valueOf(node.getValue());
-        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+        TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
 
-        // TODO check InstanceIdentifierTypeDefinition,
-        // IdentityrefTypeDefinition
+        // TODO check InstanceIdentifierTypeDefinition
         if (baseType instanceof IdentityrefTypeDefinition) {
             if (node.getValue() instanceof QName) {
-                QName qName = (QName) node.getValue();
-
-                ControllerContext contContext = ControllerContext.getInstance();
-                String moduleName = contContext.findModuleByNamespace(qName.getNamespace());
-
-                writer.value(moduleName + ":" + qName.getLocalName());
-            }
-
-        } else if (baseType instanceof LeafrefTypeDefinition) {
-            ControllerContext contContext = ControllerContext.getInstance();
-            LeafSchemaNode lfSchemaNode = contContext.resolveTypeFromLeafref((LeafrefTypeDefinition) baseType, schema);
-            if (lfSchemaNode != null) {
-                writeValueOfNodeByType(writer, node, lfSchemaNode.getType(), lfSchemaNode);
+                IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType).serialize(node.getValue());
+                IdentityValue valueFromDTO = valueDTO.getValuesWithNamespaces().get(0);
+                String moduleName = ControllerContext.getInstance().findModuleByNamespace(URI.create(valueFromDTO.getNamespace()));
+                writer.value(moduleName + ":" + valueFromDTO.getValue());
             } else {
-                writer.value(value);
+                logger.debug("Value of " + baseType.getQName().getNamespace() + ":"
+                        + baseType.getQName().getLocalName() + " is not instance of " + QName.class + " but is " + node.getValue().getClass());
+                writer.value(String.valueOf(node.getValue()));
             }
-        } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
-            writer.value(((InstanceIdentifierTypeDefinition) baseType).getPathStatement().toString());
-        } else if (baseType instanceof UnionTypeDefinition) {
-            processTypeIsUnionType(writer, (UnionTypeDefinition) baseType, value);
         } else if (baseType instanceof DecimalTypeDefinition || baseType instanceof IntegerTypeDefinition
                 || baseType instanceof UnsignedIntegerTypeDefinition) {
-            writer.value(new NumberForJsonWriter(value));
+            writer.value(new NumberForJsonWriter((String) RestCodec.from(baseType).serialize(node.getValue())));
         } else if (baseType instanceof BooleanTypeDefinition) {
-            writer.value(Boolean.parseBoolean(value));
+            writer.value(Boolean.parseBoolean((String) RestCodec.from(baseType).serialize(node.getValue())));
         } else if (baseType instanceof EmptyTypeDefinition) {
             writeEmptyDataTypeToJson(writer);
         } else {
+            String value = String.valueOf(RestCodec.from(baseType).serialize(node.getValue()));
+            if (value == null) {
+                value = String.valueOf(node.getValue());
+            }
             writer.value(value.equals("null") ? "" : value);
         }
     }
 
-    private void processTypeIsUnionType(JsonWriter writer, UnionTypeDefinition unionType, String value)
-            throws IOException {
-        if (value == null) {
-            writeEmptyDataTypeToJson(writer);
-        } else if ((isNumber(value))
-                && containsType(unionType, UnsignedIntegerTypeDefinition.class, IntegerTypeDefinition.class,
-                        DecimalTypeDefinition.class)) {
-            writer.value(new NumberForJsonWriter(value));
-        } else if (isBoolean(value) && containsType(unionType, BooleanTypeDefinition.class)) {
-            writer.value(Boolean.parseBoolean(value));
-        } else {
-            writer.value(value);
-        }
-    }
-
-    private boolean isBoolean(String value) {
-        if (value.equals("true") || value.equals("false")) {
-            return true;
-        }
-        return false;
-    }
-
     private void writeEmptyDataTypeToJson(JsonWriter writer) throws IOException {
         writer.beginArray();
         writer.nullValue();
         writer.endArray();
     }
 
-    private boolean isNumber(String value) {
-        try {
-            Double.valueOf(value);
-        } catch (NumberFormatException e) {
-            return false;
-        }
-        return true;
-    }
-
-    private boolean containsType(UnionTypeDefinition unionType, Class<?>... searchedTypes) {
-        List<TypeDefinition<?>> allUnionSubtypes = resolveAllUnionSubtypesFrom(unionType);
-
-        for (TypeDefinition<?> unionSubtype : allUnionSubtypes) {
-            for (Class<?> searchedType : searchedTypes) {
-                if (searchedType.isInstance(unionSubtype)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private List<TypeDefinition<?>> resolveAllUnionSubtypesFrom(UnionTypeDefinition inputType) {
-        List<TypeDefinition<?>> result = new ArrayList<>();
-        for (TypeDefinition<?> subtype : inputType.getTypes()) {
-            TypeDefinition<?> resolvedSubtype = subtype;
-
-            resolvedSubtype = resolveBaseTypeFrom(subtype);
-
-            if (resolvedSubtype instanceof UnionTypeDefinition) {
-                List<TypeDefinition<?>> subtypesFromRecursion = resolveAllUnionSubtypesFrom((UnionTypeDefinition) resolvedSubtype);
-                result.addAll(subtypesFromRecursion);
-            } else {
-                result.add(resolvedSubtype);
-            }
-        }
-
-        return result;
-    }
-
-    private TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
-        return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
-    }
-
     private void writeName(Node<?> node, DataSchemaNode schema, JsonWriter writer) throws IOException {
         String nameForOutput = node.getNodeType().getLocalName();
         if (schema.isAugmenting()) {
index 83e2d20d0e74334a8b138846e7fcd3396902c23f..f4c5034776ec1e83fa5022c7a68223d139d3060a 100644 (file)
@@ -9,6 +9,7 @@ import java.util.Set;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
 
 import com.google.common.collect.Lists;
 import com.google.gson.JsonElement;
@@ -52,8 +53,8 @@ class JsonReader {
     }
 
     private CompositeNodeWrapper createStructureWithRoot(String rootObjectName, JsonObject rootObject) {
-        CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFrom(rootObjectName),
-                getLocalNameFrom(rootObjectName));
+        CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFor(rootObjectName),
+                getLocalNameFor(rootObjectName));
         for (Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
             addChildToParent(childOfFirstNode.getKey(), childOfFirstNode.getValue(), firstNode);
         }
@@ -62,15 +63,15 @@ class JsonReader {
 
     private void addChildToParent(String childName, JsonElement childType, CompositeNodeWrapper parent) {
         if (childType.isJsonObject()) {
-            CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFrom(childName),
-                    getLocalNameFrom(childName));
+            CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName),
+                    getLocalNameFor(childName));
             parent.addValue(child);
             for (Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
                 addChildToParent(childOfChild.getKey(), childOfChild.getValue(), child);
             }
         } else if (childType.isJsonArray()) {
             if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) {
-                parent.addValue(new EmptyNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName)));
+                parent.addValue(new EmptyNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName)));
 
             } else {
                 for (JsonElement childOfChildType : childType.getAsJsonArray()) {
@@ -80,24 +81,36 @@ class JsonReader {
         } else if (childType.isJsonPrimitive()) {
             JsonPrimitive childPrimitive = childType.getAsJsonPrimitive();
             String value = childPrimitive.getAsString();
-            parent.addValue(new SimpleNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName), value));
+            parent.addValue(new SimpleNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName),
+                    resolveValueOfElement(value)));
         }
     }
 
-    private URI getNamespaceFrom(String jsonElementName) {
-        int indexOfDelimeter = jsonElementName.lastIndexOf(':');
-        if (indexOfDelimeter == -1) {
+    private URI getNamespaceFor(String jsonElementName) {
+        String[] moduleNameAndLocalName = jsonElementName.split(":");
+        if (moduleNameAndLocalName.length != 2) { // it is not "moduleName:localName"
             return null;
         }
-        return URI.create(jsonElementName.substring(0, indexOfDelimeter));
+        return URI.create(moduleNameAndLocalName[0]);
     }
 
-    private String getLocalNameFrom(String jsonElementName) {
-        int indexOfDelimeter = jsonElementName.lastIndexOf(':');
-        if (indexOfDelimeter == -1) {
+    private String getLocalNameFor(String jsonElementName) {
+        String[] moduleNameAndLocalName = jsonElementName.split(":");
+        if (moduleNameAndLocalName.length != 2) { // it is not "moduleName:localName"
             return jsonElementName;
         }
-        return jsonElementName.substring(indexOfDelimeter + 1, jsonElementName.length());
+        return moduleNameAndLocalName[1];
+    }
+
+    /**
+     * @param value
+     *            value of json element
+     * @return if value is "moduleName:localName" then {@link IdentityValuesDTO} else
+     *         the same string as parameter "value"
+     */
+    private Object resolveValueOfElement(String value) {
+        URI namespace = getNamespaceFor(value);
+        return namespace == null ? value : new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null);
     }
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java
new file mode 100644 (file)
index 0000000..6e70b9b
--- /dev/null
@@ -0,0 +1,15 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public final class RestUtil {
+
+    public final static TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
+        TypeDefinition<?> superType = type;
+        while (superType.getBaseType() != null) {
+            superType = superType.getBaseType();
+        }
+        return superType;
+    }
+
+}
index 53b401e4a2c55856dc215c4fc5b62987ebaa71f0..242f18d240122597bea4d1dac29a4f1a31ea9e31 100644 (file)
@@ -20,7 +20,7 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
 public class RestconfProvider implements BundleActivator, Provider, ServiceTrackerCustomizer<Broker, Broker> {
 
-    public final static String NOT_INITALIZED_MSG = "Restcof is not initialized yet. Please try again later";
+    public final static String NOT_INITALIZED_MSG = "Restconf is not initialized yet. Please try again later";
     
     private ListenerRegistration<SchemaServiceListener> listenerRegistration;
     private ServiceTracker<Broker, Broker> brokerServiceTrancker;
index 4a077e663f187f6d23e05a771d4ec988290c8c90..a3d658e7bfec43bca4dc743a460cab8bd6cea9de 100644 (file)
@@ -7,6 +7,9 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
+import org.opendaylight.controller.sal.restconf.impl.RestCodec;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
@@ -61,9 +64,9 @@ public class XmlMapper {
         Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
         if (data instanceof SimpleNode<?>) {
             if (schema instanceof LeafListSchemaNode) {
-                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType());
+                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType(), (DataSchemaNode) schema);
             } else if (schema instanceof LeafSchemaNode) {
-                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType());
+                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType(), (DataSchemaNode) schema);
             } else {
                 Object value = data.getValue();
                 if (value != null) {
@@ -88,18 +91,32 @@ public class XmlMapper {
         return itemEl;
     }
 
-    private void writeValueOfNodeByType(Element element, SimpleNode<?> node, TypeDefinition<?> type) {
+    private void writeValueOfNodeByType(Element element, SimpleNode<?> node, TypeDefinition<?> type, DataSchemaNode schema) {
 
-        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+        TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
 
-        if (baseType instanceof IdentityrefTypeDefinition && node.getValue() instanceof QName) {
-            QName value = (QName) node.getValue();
-            element.setAttribute("xmlns:x", value.getNamespace().toString());
-            element.setTextContent("x:" + value.getLocalName());
+        if (baseType instanceof IdentityrefTypeDefinition) {
+            if (node.getValue() instanceof QName) {
+                IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(type).serialize(node.getValue());
+                IdentityValue value = valueDTO.getValuesWithNamespaces().get(0);
+                String prefix = "x";
+                if (value.getPrefix() != null && !value.getPrefix().isEmpty()) {
+                    prefix = value.getPrefix();
+                }
+                element.setAttribute("xmlns:" + prefix, value.getNamespace());
+                element.setTextContent(prefix + ":" + value.getValue());
+            } else {
+                logger.debug("Value of " + baseType.getQName().getNamespace() + ":"
+                        + baseType.getQName().getLocalName() + " is not instance of " + QName.class + " but is " + node.getValue().getClass());
+                element.setTextContent(String.valueOf(node.getValue()));
+            }
         } else {
-            Object value = node.getValue();
-            if (value != null) {
-                element.setTextContent(String.valueOf(value));
+            if (node.getValue() != null) {
+                String value = String.valueOf(RestCodec.from(baseType).serialize(node.getValue()));
+                if (value.equals("null")) {
+                    value = String.valueOf(node.getValue());
+                }
+                element.setTextContent(value);
             }
         }
     }
@@ -122,8 +139,4 @@ public class XmlMapper {
         return null;
     }
 
-    private TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
-        return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
-    }
-
 }
index a53281492f23f28bd3e912c51cb8ae1ba1a752fa..014e839f2665c7e9aa7c89c5a9f344aaef377b7b 100644 (file)
@@ -14,6 +14,7 @@ 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.EmptyNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
@@ -123,11 +124,24 @@ public class XmlReader {
         return false;
     }
 
+    private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
+        checkArgument(startElement != null, "Start Element cannot be NULL!");
+        return new CompositeNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
+    }
+
     private NodeWrapper<? extends Node<?>> resolveSimpleNodeFromStartElement(final StartElement startElement)
             throws XMLStreamException {
         checkArgument(startElement != null, "Start Element cannot be NULL!");
-        String data = null;
+        String data = getValueOf(startElement);
+        if (data == null) {
+            return new EmptyNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
+        }
+        return new SimpleNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement),
+                resolveValueOfElement(data, startElement));
+    }
 
+    private String getValueOf(StartElement startElement) throws XMLStreamException {
+        String data = null;
         if (eventReader.hasNext()) {
             final XMLEvent innerEvent = eventReader.peek();
             if (innerEvent.isCharacters()) {
@@ -143,24 +157,36 @@ public class XmlReader {
                 }
             }
         }
-        if(data == null) {
-            return new EmptyNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
-        }
-        return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
+        return data;
     }
 
-    private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
-        checkArgument(startElement != null, "Start Element cannot be NULL!");
-        return new CompositeNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
-    }
-
-    private String getLocalNameFrom(StartElement startElement) {
+    private String getLocalNameFor(StartElement startElement) {
         return startElement.getName().getLocalPart();
     }
 
-    private URI getNamespaceFrom(StartElement startElement) {
+    private URI getNamespaceFor(StartElement startElement) {
         String namespaceURI = startElement.getName().getNamespaceURI();
         return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
     }
 
+    /**
+     * @param value
+     *            value of startElement
+     * @param startElement
+     *            element containing value
+     * @return if value is "prefix:value" then {@link IdentityValuesDTO} else the same
+     *         string as parameter "value"
+     */
+    private Object resolveValueOfElement(String value, StartElement startElement) {
+        String[] namespaceAndValue = value.split(":");
+        if (namespaceAndValue.length != 2) { // it is not "prefix:value"
+            return value;
+        }
+        String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
+        if (namespace != null && !namespace.isEmpty()) {
+            return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0]);
+        }
+        return value;
+    }
+
 }
index 930aa663bb4cc91b013d42dec40b5775921e95c2..eec2d452a178c15da2f0c70befa8c1367aae31eb 100644 (file)
@@ -1,6 +1,7 @@
 package org.opendaylight.controller.sal.restconf.impl
 
 import com.google.common.collect.BiMap
+import com.google.common.collect.FluentIterable
 import com.google.common.collect.HashBiMap
 import java.net.URI
 import java.net.URLDecoder
@@ -11,6 +12,7 @@ import java.util.Map
 import java.util.concurrent.ConcurrentHashMap
 import javax.ws.rs.core.Response
 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.controller.sal.rest.impl.RestUtil
 import org.opendaylight.controller.sal.rest.impl.RestconfProvider
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
@@ -18,6 +20,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdent
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
@@ -27,15 +30,10 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.model.api.SchemaNode
-import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
-
-import static com.google.common.base.Preconditions.*
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
 import org.slf4j.LoggerFactory
-import com.google.common.collect.FluentIterable
+
+import static com.google.common.base.Preconditions.*
 
 class ControllerContext implements SchemaServiceListener {
     val static LOG = LoggerFactory.getLogger(ControllerContext)
@@ -96,7 +94,7 @@ class ControllerContext implements SchemaServiceListener {
         return getLatestModule(startModule)
     }
 
-    private def getLatestModule(String moduleName) {
+    def getLatestModule(String moduleName) {
         checkPreconditions
         checkArgument(moduleName !== null && !moduleName.empty)
         val modules = schemas.modules.filter[m|m.name == moduleName]
@@ -142,20 +140,37 @@ class ControllerContext implements SchemaServiceListener {
         var module = uriToModuleName.get(namespace)
         if (module === null) {
             val moduleSchemas = schemas.findModuleByNamespace(namespace);
-            if(moduleSchemas === null) throw new IllegalArgumentException()
+            if(moduleSchemas === null) return null
             var latestModule = moduleSchemas.head
             for (m : moduleSchemas) {
                 if (m.revision.after(latestModule.revision)) {
                     latestModule = m
                 }
             }
-            if(latestModule === null) throw new IllegalArgumentException()
+            if(latestModule === null) return null
             uriToModuleName.put(namespace, latestModule.name)
             module = latestModule.name;
         }
         return module
     }
 
+    def findNamespaceByModule(String module) {
+        var namespace = moduleNameToUri.get(module)
+        if (namespace === null) {
+            val moduleSchemas = schemas.modules.filter[it|it.name.equals(module)]
+            var latestModule = moduleSchemas.head
+            for (m : moduleSchemas) {
+                if (m.revision.after(latestModule.revision)) {
+                    latestModule = m
+                }
+            }
+            if(latestModule === null) return null
+            namespace = latestModule.namespace
+            uriToModuleName.put(namespace, latestModule.name)
+        }
+        return namespace
+    }
+
     def CharSequence toRestconfIdentifier(QName qname) {
         checkPreconditions
         var module = uriToModuleName.get(qname.namespace)
@@ -295,11 +310,8 @@ class ControllerContext implements SchemaServiceListener {
         val typedef = (node as LeafSchemaNode).type;
         
         var decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded)
-        if(decoded == null) {
-            var baseType = typedef
-            while (baseType.baseType != null) {
-                baseType = baseType.baseType;
-            }
+        if(decoded === null) {
+            var baseType = RestUtil.resolveBaseTypeFrom(typedef)
             if(baseType instanceof IdentityrefTypeDefinition) {
                 decoded = toQName(urlDecoded)
             }
@@ -349,35 +361,4 @@ class ControllerContext implements SchemaServiceListener {
         }
     }
 
-    /**
-     * Resolve target type from leafref type.
-     * 
-     * According to RFC 6020 referenced element has to be leaf (chapter 9.9).
-     * Therefore if other element is referenced then null value is returned.
-     * 
-     * Currently only cases without path-predicate are supported.
-     * 
-     * @param leafRef
-     * @param schemaNode
-     *            data schema node which contains reference
-     * @return type if leaf is referenced and it is possible to find referenced
-     *         node in schema context. In other cases null value is returned
-     */
-    def LeafSchemaNode resolveTypeFromLeafref(LeafrefTypeDefinition leafRef, DataSchemaNode schemaNode) {
-        val xPath = leafRef.getPathStatement();
-        val module = SchemaContextUtil.findParentModule(schemas, schemaNode);
-
-        var SchemaNode foundSchemaNode
-        if (xPath.isAbsolute()) {
-            foundSchemaNode = SchemaContextUtil.findDataSchemaNode(schemas, module, xPath);
-        } else {
-            foundSchemaNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemas, module, schemaNode, xPath);
-        }
-
-        if (foundSchemaNode instanceof LeafSchemaNode) {
-            return foundSchemaNode as LeafSchemaNode;
-        }
-
-        return null;
-    }
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java
new file mode 100644 (file)
index 0000000..6924fb6
--- /dev/null
@@ -0,0 +1,60 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public final class IdentityValuesDTO {
+
+    private final List<IdentityValue> elementData = new ArrayList<>();
+
+    public IdentityValuesDTO(String namespace, String value, String prefix) {
+        elementData.add(new IdentityValue(namespace, value, prefix));
+    }
+
+    public void add(String namespace, String value, String prefix) {
+        elementData.add(new IdentityValue(namespace, value, prefix));
+    }
+
+    public List<IdentityValue> getValuesWithNamespaces() {
+        return Collections.unmodifiableList(elementData);
+    }
+
+    public static final class IdentityValue {
+
+        private String namespace;
+        private String value;
+        private String prefix;
+
+        public IdentityValue(String namespace, String value, String prefix) {
+            this.namespace = namespace;
+            this.value = value;
+            this.prefix = prefix;
+        }
+
+        public String getNamespace() {
+            return namespace;
+        }
+
+        public void setNamespace(String namespace) {
+            this.namespace = namespace;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        public String getPrefix() {
+            return prefix;
+        }
+
+        public void setPrefix(String prefix) {
+            this.prefix = prefix;
+        }
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java
new file mode 100644 (file)
index 0000000..450ba02
--- /dev/null
@@ -0,0 +1,123 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+
+import org.opendaylight.controller.sal.rest.impl.RestUtil;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.codec.IdentityrefCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RestCodec {
+
+    private RestCodec() {
+    }
+    
+    public static final Codec<Object, Object> from(TypeDefinition<?> typeDefinition) {
+        return new ObjectCodec(typeDefinition);
+    }
+    
+    @SuppressWarnings("rawtypes")
+    public static final class ObjectCodec implements Codec<Object, Object> {
+
+        private final Logger logger = LoggerFactory.getLogger(RestCodec.class);
+        
+        public static final Codec IDENTITYREF_DEFAULT_CODEC = new IdentityrefCodecImpl();
+        public static final Codec LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl();
+
+        private TypeDefinition<?> type;
+
+        private ObjectCodec(TypeDefinition<?> typeDefinition) {
+            type = RestUtil.resolveBaseTypeFrom(typeDefinition);
+        }
+        
+        @SuppressWarnings("unchecked")
+        @Override
+        public Object deserialize(Object input) {
+            try {
+                if (type instanceof IdentityrefTypeDefinition) {
+                    return IDENTITYREF_DEFAULT_CODEC.deserialize(input);
+                } else if (type instanceof LeafrefTypeDefinition) {
+                    return LEAFREF_DEFAULT_CODEC.deserialize(input);
+                } else {
+                    TypeDefinitionAwareCodec<Object,? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec.from(type);
+                    if (typeAwarecodec != null) {
+                        return typeAwarecodec.deserialize(String.valueOf(input));
+                    } else {
+                        logger.debug("Codec for type \"" + type.getQName().getLocalName() + "\" is not implemented yet.");
+                        return null;
+                    }
+                }
+            } catch (ClassCastException e) { // TODO remove this catch when everyone use codecs
+                logger.error("ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input), e);
+                return input;
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Object serialize(Object input) {
+            try {
+                if (type instanceof IdentityrefTypeDefinition) {
+                    return IDENTITYREF_DEFAULT_CODEC.serialize(input);
+                } else if (type instanceof LeafrefTypeDefinition) {
+                    return LEAFREF_DEFAULT_CODEC.serialize(input);
+                } else {
+                    TypeDefinitionAwareCodec<Object,? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec.from(type);
+                    if (typeAwarecodec != null) {
+                        return typeAwarecodec.serialize(input);
+                    } else {
+                        logger.debug("Codec for type \"" + type.getQName().getLocalName() + "\" is not implemented yet.");
+                        return null;
+                    }
+                }
+            } catch (ClassCastException e) { // TODO remove this catch when everyone use codecs
+                logger.error("ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input), e);
+                return input;
+            }
+        }
+        
+    }
+    
+    public static class IdentityrefCodecImpl implements IdentityrefCodec<IdentityValuesDTO> {
+
+        @Override
+        public IdentityValuesDTO serialize(QName data) {
+            return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix());
+        }
+
+        @Override
+        public QName deserialize(IdentityValuesDTO data) {
+            IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
+            String namespace = valueWithNamespace.getNamespace();
+            URI validNamespace = ControllerContext.getInstance().findNamespaceByModule(namespace);
+            if (validNamespace == null) {
+                validNamespace = URI.create(namespace);
+            }
+            return QName.create(validNamespace, null, valueWithNamespace.getValue());
+        }
+
+    }
+    
+    public static class LeafrefCodecImpl implements LeafrefCodec<String> {
+
+        @Override
+        public String serialize(Object data) {
+            return String.valueOf(data);
+        }
+
+        @Override
+        public Object deserialize(String data) {
+            return data;
+        }
+        
+    }
+    
+}
index 94a7756da65cefd02adbe3a00eecb69efe9a8dab..4645a411c17c88baa7d55d94c21fcb944faf4d2f 100644 (file)
@@ -6,18 +6,20 @@ import java.util.Set
 import javax.ws.rs.core.Response
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
 import org.opendaylight.controller.sal.rest.api.RestconfService
+import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.yangtools.yang.data.api.Node
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory
 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.data.impl.codec.TypeDefinitionAwareCodec
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
+
 import static javax.ws.rs.core.Response.Status.*
 
 class RestconfImpl implements RestconfService {
@@ -148,7 +150,7 @@ class RestconfImpl implements RestconfService {
         }
         val moduleName = controllerContext.findModuleByNamespace(validQName.namespace);
         if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
-            nodeBuilder.namespace.path == moduleName) {
+            nodeBuilder.namespace.toString == moduleName) {
             nodeBuilder.qname = validQName
         } else {
             throw new ResponseException(BAD_REQUEST,
@@ -164,12 +166,34 @@ class RestconfImpl implements RestconfService {
                     findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),
                     currentAugment)
             }
+            if(schema instanceof ListSchemaNode) {
+                val listKeys = (schema as ListSchemaNode).keyDefinition
+                for (listKey : listKeys) {
+                    var foundKey = false
+                    for (child : children) {
+                        if (child.unwrap.nodeType.localName == listKey.localName) {
+                            foundKey = true;
+                        }
+                    }
+                    if (!foundKey) {
+                        throw new ResponseException(BAD_REQUEST,
+                            "Missing key \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"")
+                    }
+                }
+            }
         } else if (nodeBuilder instanceof SimpleNodeWrapper) {
             val simpleNode = (nodeBuilder as SimpleNodeWrapper)
-            val stringValue = simpleNode.value as String;
-
-            val objectValue = TypeDefinitionAwareCodec.from(schema.typeDefinition)?.deserialize(stringValue);
-            simpleNode.setValue(objectValue)
+            val value = simpleNode.value
+            var inputValue = value;
+            
+            if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
+                if (value instanceof String) {
+                    inputValue = new IdentityValuesDTO(validQName.namespace.toString, value as String, null)
+                } // else value is instance of ValuesDTO
+            }
+            
+            val outputValue = RestCodec.from(schema.typeDefinition)?.deserialize(inputValue);
+            simpleNode.setValue(outputValue)
         } else if (nodeBuilder instanceof EmptyNodeWrapper) {
             val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
             if (schema instanceof LeafSchemaNode) {
@@ -183,11 +207,19 @@ class RestconfImpl implements RestconfService {
     }
 
     private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
-        node.type
+        var baseType = node.type
+        while (baseType.baseType !== null) {
+            baseType = baseType.baseType;
+        }
+        baseType
     }
 
     private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
-        node.type
+        var TypeDefinition<?> baseType = node.type
+        while (baseType.baseType !== null) {
+            baseType = baseType.baseType;
+        }
+        baseType
     }
 
     private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
index 9f3c6e51e95b1c9d53a231b62b63d4072c6374cc..97f8102127c2b71f69aaf729aeeeed598043aed0 100644 (file)
@@ -13,7 +13,7 @@ import com.google.common.base.Preconditions;
 
 public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<Object> {
     
-    private SimpleNode<?> simpleNode;
+    private SimpleNode<Object> simpleNode;
     
     private String localName;
     private Object value;
@@ -25,7 +25,7 @@ public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, Simp
         this.value = value;
     }
     
-    public SimpleNodeWrapper(URI namespace, String localName, String value) {
+    public SimpleNodeWrapper(URI namespace, String localName, Object value) {
         this(localName, value);
         this.namespace = namespace;
     }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonBasicDataTypesTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonBasicDataTypesTest.java
new file mode 100644 (file)
index 0000000..73d0c82
--- /dev/null
@@ -0,0 +1,349 @@
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+
+import javax.ws.rs.WebApplicationException;
+import javax.xml.bind.DatatypeConverter;
+
+import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+public class ToJsonBasicDataTypesTest {
+
+    @Test
+    public void simpleYangDataTest() {
+        String jsonOutput = "";
+        CompositeNode compositeNode = TestUtils.loadCompositeNode("/cnsn-to-json/simple-data-types/xml/data.xml");
+
+        Set<Module> modules = TestUtils.resolveModules("/cnsn-to-json/simple-data-types");
+        assertEquals(1, modules.size());
+        Module module = TestUtils.resolveModule(null, modules);
+        assertNotNull(module);
+        DataSchemaNode dataSchemaNode = TestUtils.resolveDataSchemaNode(module, null);
+        assertNotNull(dataSchemaNode);
+
+        TestUtils.normalizeCompositeNode(compositeNode, modules, dataSchemaNode, "simple-data-types:cont");
+
+        try {
+            jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(compositeNode, modules, dataSchemaNode);
+        } catch (WebApplicationException | IOException e) {
+            assertTrue(false); // shouldn't get here
+        }
+
+        System.out.println(jsonOutput);
+        verifyJsonOutput(jsonOutput);
+    }
+
+    private CompositeNode prepareData() {
+        MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
+                ModifyAction.CREATE, null);
+
+        List<Node<?>> childNodes = new ArrayList<>();
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint8Min"), cont, (byte) -128,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint8Max"), cont, (byte) 127,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint16Min"), cont, (short) -32768,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint16Max"), cont, (short) 32767,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint32Min"), cont,
+                (int) -2147483648, ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint32Max"), cont, (int) 2147483647,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint64Min"), cont, new Long(
+                "-9223372036854775807"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnint64Max"), cont, new Long(
+                "9223372036854775807"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnuint8Max"), cont, (short) 255,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnuint16Max"), cont, (int) 65535,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfnuint32Max"), cont, new Long(
+                "4294967295"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfstr"), cont, "lfstr",
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfstr1"), cont, "",
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfbool1"), cont, Boolean.TRUE,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfbool2"), cont, Boolean.FALSE,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfdecimal1"), cont, new BigDecimal(
+                "43.32"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfdecimal2"), cont, new BigDecimal(
+                "-0.43"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfdecimal3"), cont, new BigDecimal(
+                "43"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfdecimal4"), cont, new BigDecimal(
+                "43E3"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfdecimal6"), cont, new BigDecimal(
+                "33.12345"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfenum"), cont, "enum3",
+                ModifyAction.CREATE, null));
+
+        HashSet<String> bits = new HashSet<String>();
+        bits.add("bit3");
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfbits"), cont, bits,
+                ModifyAction.CREATE, null));
+
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfbinary"), cont, DatatypeConverter
+                .parseBase64Binary("AAaacdabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"),
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfempty"), cont, null,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion1"), cont, (int) 324,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion2"), cont, new BigDecimal(
+                "33.3"), ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion3"), cont, "55",
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion4"), cont, Boolean.TRUE,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion5"), cont, "true",
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion6"), cont, "false",
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion7"), cont, null,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion8"), cont, "",
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion9"), cont, "",
+                ModifyAction.CREATE, null));
+
+        HashSet<String> bits2 = new HashSet<String>();
+        bits2.add("bt1");
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion10"), cont, bits2,
+                ModifyAction.CREATE, null));
+
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion11"), cont, (short) 33,
+                ModifyAction.CREATE, null));
+        childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfunion12"), cont, Boolean.FALSE,
+                ModifyAction.CREATE, null));
+        try {
+            childNodes.add(NodeFactory.createMutableSimpleNode(TestUtils.buildQName("identityref1"), cont, new QName(
+                    new URI("simple:data:types"), "iden"), ModifyAction.CREATE, null));
+        } catch (URISyntaxException e) {
+        }
+
+        cont.getChildren().addAll(childNodes);
+
+        cont.init();
+
+        return cont;
+    }
+
+    private void verifyJsonOutput(String jsonOutput) {
+        StringReader strReader = new StringReader(jsonOutput);
+        JsonReader jReader = new JsonReader(strReader);
+
+        String exception = null;
+        try {
+            jsonReadCont(jReader);
+        } catch (IOException e) {
+            exception = e.getMessage();
+        }
+
+        assertNull("Error during reading Json output: " + exception, exception);
+    }
+
+    private void jsonReadCont(JsonReader jReader) throws IOException {
+        jReader.beginObject();
+        assertNotNull("cont1 is missing.", jReader.hasNext());
+
+        // Cont dataFromJson = new Cont(jReader.nextName());
+        jReader.nextName();
+        jsonReadContElements(jReader);
+
+        assertFalse("cont shouldn't have other element.", jReader.hasNext());
+        jReader.endObject();
+        // return dataFromJson;
+    }
+
+    private void jsonReadContElements(JsonReader jReader) throws IOException {
+        jReader.beginObject();
+        List<String> loadedLfs = new ArrayList<>();
+        boolean exceptForDecimal5Raised = false;
+        boolean enumChecked = false;
+        boolean bitsChecked = false;
+        boolean lfdecimal6Checked = false;
+        boolean lfdecimal4Checked = false;
+        boolean lfdecimal3Checked = false;
+        boolean lfdecimal2Checked = false;
+        boolean lfdecimal1Checked = false;
+        boolean lfbool1Checked = false;
+        boolean lfbool2Checked = false;
+        boolean lfstrChecked = false;
+        boolean lfbinaryChecked = false;
+        // boolean lfref1Checked = false;
+        boolean lfemptyChecked = false;
+        boolean lfstr1Checked = false;
+        boolean lfidentityrefChecked = false;
+
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            JsonToken peek = null;
+            try {
+                peek = jReader.peek();
+            } catch (IOException e) {
+                if (keyName.equals("lfdecimal5")) {
+                    exceptForDecimal5Raised = true;
+                } else {
+                    assertTrue("Key " + keyName + " has incorrect value for specifed type", false);
+                }
+            }
+
+            if (keyName.startsWith("lfnint") || keyName.startsWith("lfnuint")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+                try {
+                    jReader.nextLong();
+                } catch (NumberFormatException e) {
+                    assertTrue("Key " + keyName + " has incorrect value - " + e.getMessage(), false);
+                }
+                loadedLfs.add(keyName.substring(3));
+            } else if (keyName.equals("identityref1")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+                assertEquals("simple-data-types:iden", jReader.nextString());
+                lfidentityrefChecked = true;
+            } else if (keyName.equals("lfstr")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+                assertEquals("lfstr", jReader.nextString());
+                lfstrChecked = true;
+            } else if (keyName.equals("lfstr1")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+                assertEquals("", jReader.nextString());
+                lfstr1Checked = true;
+            } else if (keyName.equals("lfbool1")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
+                assertEquals(true, jReader.nextBoolean());
+                lfbool1Checked = true;
+            } else if (keyName.equals("lfbool2")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
+                assertEquals(false, jReader.nextBoolean());
+                lfbool2Checked = true;
+            } else if (keyName.equals("lfbool3")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
+                assertEquals(false, jReader.nextBoolean());
+            } else if (keyName.equals("lfdecimal1")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+                assertEquals(new Double(43.32), (Double) jReader.nextDouble());
+                lfdecimal1Checked = true;
+            } else if (keyName.equals("lfdecimal2")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+                assertEquals(new Double(-0.43), (Double) jReader.nextDouble());
+                lfdecimal2Checked = true;
+            } else if (keyName.equals("lfdecimal3")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+                assertEquals(new Double(43), (Double) jReader.nextDouble());
+                lfdecimal3Checked = true;
+            } else if (keyName.equals("lfdecimal4")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+                assertEquals(new Double(43E3), (Double) jReader.nextDouble());
+                lfdecimal4Checked = true;
+            } else if (keyName.equals("lfdecimal6")) {
+                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+                assertEquals(new Double(33.12345), (Double) jReader.nextDouble());
+                lfdecimal6Checked = true;
+            } else if (keyName.equals("lfenum")) {
+                assertEquals("enum3", jReader.nextString());
+                enumChecked = true;
+            } else if (keyName.equals("lfbits")) {
+                assertEquals("bit3 bit2", jReader.nextString());
+                bitsChecked = true;
+            } else if (keyName.equals("lfbinary")) {
+                assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", jReader.nextString());
+                lfbinaryChecked = true;
+            } else if (keyName.equals("lfempty")) {
+                jReader.beginArray();
+                jReader.nextNull();
+                jReader.endArray();
+                lfemptyChecked = true;
+            } else if (keyName.startsWith("lfunion")) {
+                checkLfUnion(jReader, keyName, peek);
+            } else {
+                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+            }
+
+        }
+        Collections.sort(loadedLfs);
+        String expectedLfsStr = "[int16Max, int16Min, int32Max, int32Min, int64Max, int64Min, int8Max, int8Min, uint16Max, uint32Max, uint8Max]";
+        String actualLfsStr = loadedLfs.toString();
+        assertEquals("Some leaves are missing", expectedLfsStr, actualLfsStr);
+        assertTrue("Enum wasn't checked", enumChecked);
+        assertTrue("Bits wasn't checked", bitsChecked);
+        assertTrue("Decimal1 wasn't checked", lfdecimal1Checked);
+        assertTrue("Decimal2 wasn't checked", lfdecimal2Checked);
+        assertTrue("Decimal3 wasn't checked", lfdecimal3Checked);
+        assertTrue("Decimal4 wasn't checked", lfdecimal4Checked);
+        assertTrue("Decimal5 wasn't checked", lfdecimal6Checked);
+        assertTrue("lfbool1 wasn't checked", lfbool1Checked);
+        assertTrue("lfbool2 wasn't checked", lfbool2Checked);
+        assertTrue("lfstr wasn't checked", lfstrChecked);
+        assertTrue("lfstr1 wasn't checked", lfstr1Checked);
+        assertTrue("lfbinary wasn't checked", lfbinaryChecked);
+        assertTrue("lfempty wasn't checked", lfemptyChecked);
+        assertTrue("lfidentityref wasn't checked", lfidentityrefChecked);
+        jReader.endObject();
+    }
+
+    private void checkLfUnion(JsonReader jReader, String keyName, JsonToken peek) throws IOException {
+        if (keyName.equals("lfunion1")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("324", jReader.nextString());
+        } else if (keyName.equals("lfunion2")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("33.3", jReader.nextString());
+        } else if (keyName.equals("lfunion3")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("55", jReader.nextString());
+        } else if (keyName.equals("lfunion4")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("true", jReader.nextString());
+        } else if (keyName.equals("lfunion5")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("true", jReader.nextString());
+        } else if (keyName.equals("lfunion6")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("false", jReader.nextString());
+        } else if (keyName.equals("lfunion7")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("", jReader.nextString());
+        } else if (keyName.equals("lfunion8")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("", jReader.nextString());
+        } else if (keyName.equals("lfunion9")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("", jReader.nextString());
+        } else if (keyName.equals("lfunion10")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("bt1", jReader.nextString());
+        } else if (keyName.equals("lfunion11")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("33", jReader.nextString());
+        } else if (keyName.equals("lfunion12")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("false", jReader.nextString());
+        } else if (keyName.equals("lfunion13")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("44", jReader.nextString());
+        } else if (keyName.equals("lfunion14")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            assertEquals("21", jReader.nextString());
+        }
+    }
+}
@@ -1,20 +1,20 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
-import java.io.*;
-import java.util.*;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Map;
+import java.util.Set;
 
 import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
 import org.opendaylight.controller.sal.restconf.impl.test.structures.*;
 import org.opendaylight.yangtools.yang.data.api.*;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
-import com.google.gson.stream.*;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
 
 public class ToJsonBasicYangTypesTest {
 
@@ -25,7 +25,7 @@ public class ToJsonBasicYangTypesTest {
     @Test
     public void compositeNodeAndYangWithJsonReaderEmptyDataTest() {
         String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(prepareCompositeNodeWithEmpties(),
-                "/yang-to-json-conversion/simple-yang-types", "/yang-to-json-conversion/simple-yang-types/xml");
+                "/cnsn-to-json/simple-yang-types", "/cnsn-to-json/simple-yang-types/xml", "simple-yang-types", "cont1");
         verifyJsonOutputForEmpty(jsonOutput);
     }
 
@@ -36,8 +36,8 @@ public class ToJsonBasicYangTypesTest {
     @Test
     public void xmlAndYangTypesWithJsonReaderTest() {
         String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
-                TestUtils.loadCompositeNode("/yang-to-json-conversion/simple-yang-types/xml/data.xml"),
-                "/yang-to-json-conversion/simple-yang-types", "/yang-to-json-conversion/simple-yang-types/xml");
+                TestUtils.loadCompositeNode("/cnsn-to-json/simple-yang-types/xml/data.xml"),
+                "/cnsn-to-json/simple-yang-types", "/cnsn-to-json/simple-yang-types/xml", "simple-yang-types", "cont1");
         verifyJsonOutput(jsonOutput);
     }
 
@@ -204,10 +204,12 @@ public class ToJsonBasicYangTypesTest {
         return lstItem;
     }
 
-    private String nextValue(JsonReader jReader) throws IOException {
+    private Object nextValue(JsonReader jReader) throws IOException {
         if (jReader.peek().equals(JsonToken.NULL)) {
             jReader.nextNull();
             return null;
+        } else if (jReader.peek().equals(JsonToken.NUMBER)) {
+            return jReader.nextInt();
         } else {
             return jReader.nextString();
         }
@@ -289,11 +291,11 @@ public class ToJsonBasicYangTypesTest {
         LstItem lst11_2 = null;
         LstItem lst11_3 = null;
         for (LstItem lstItem : lstItems) {
-            if (lstItem.getLfs().get("lf111").getValue().equals("1")) {
+            if (lstItem.getLfs().get("lf111").getValue().equals(1)) {
                 lst11_1 = lstItem;
-            } else if (lstItem.getLfs().get("lf111").getValue().equals("2")) {
+            } else if (lstItem.getLfs().get("lf111").getValue().equals(2)) {
                 lst11_2 = lstItem;
-            } else if (lstItem.getLfs().get("lf111").getValue().equals("3")) {
+            } else if (lstItem.getLfs().get("lf111").getValue().equals(3)) {
                 lst11_3 = lstItem;
             }
         }
@@ -307,8 +309,11 @@ public class ToJsonBasicYangTypesTest {
         assertEquals(1, lst11_1.getLfs().size());
         assertEquals(1, lst11_1.getConts().size());
         assertEquals(1, lst11_1.getLsts().size());
-        assertEquals(lst11_1.getLsts().get("lst111"), new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", "35"))
-                .addLstItem(new LstItem().addLf("lf1111", "34")).addLstItem(new LstItem()).addLstItem(new LstItem()));
+        assertEquals(
+                lst11_1.getLsts().get("lst111"),
+                new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", (int) 35))
+                        .addLstItem(new LstItem().addLf("lf1111", (int) 34)).addLstItem(new LstItem())
+                        .addLstItem(new LstItem()));
         assertEquals(lst11_1.getConts().get("cont111"), new Cont("cont111"));
         // : lst11_1
 
@@ -327,9 +332,10 @@ public class ToJsonBasicYangTypesTest {
         assertEquals(1, lst11_2_cont111.getLsts().size());
         assertTrue(lst11_2_cont111.getConts().isEmpty());
 
-        assertEquals(new LfLst("lflst1111").addLf("1024").addLf("4096"), lst11_2_cont111.getLfLsts().get("lflst1111"));
+        assertEquals(new LfLst("lflst1111").addLf((int) 1024).addLf((int) 4096),
+                lst11_2_cont111.getLfLsts().get("lflst1111"));
         assertEquals(
-                new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", "4")).addLstItem(
+                new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", (int) 4)).addLstItem(
                         new LstItem().addLf("lf1111A", "lf1111A str12")), lst11_2_cont111.getLsts().get("lst1111"));
         // :-cont111
         assertEquals(lst11_2.getLsts().get("lst112"), new Lst("lst112").addLstItem(new LstItem()));
@@ -369,9 +375,9 @@ public class ToJsonBasicYangTypesTest {
         assertNotNull(lflst12);
 
         assertEquals(3, lflst11.getLfs().size());
-        assertTrue(lflst11.getLfs().contains(new Lf("55")));
-        assertTrue(lflst11.getLfs().contains(new Lf("56")));
-        assertTrue(lflst11.getLfs().contains(new Lf("57")));
+        assertTrue(lflst11.getLfs().contains(new Lf(55)));
+        assertTrue(lflst11.getLfs().contains(new Lf(56)));
+        assertTrue(lflst11.getLfs().contains(new Lf(57)));
 
         assertEquals(3, lflst12.getLfs().size());
         assertTrue(lflst12.getLfs().contains(new Lf("lflst12 str1")));
@@ -387,9 +393,9 @@ public class ToJsonBasicYangTypesTest {
         LstItem lst11_2 = null;
         for (LstItem lstItem : lst11.getLstItems()) {
             Lf lf = lstItem.getLfs().get("lf111");
-            if (lf != null && lf.getValue().equals("140")) {
+            if (lf != null && lf.getValue().equals(140)) {
                 lst11_1 = lstItem;
-            } else if (lf != null && lf.getValue().equals("141")) {
+            } else if (lf != null && lf.getValue().equals(141)) {
                 lst11_2 = lstItem;
             }
         }
@@ -414,15 +420,15 @@ public class ToJsonBasicYangTypesTest {
 
         // cont111 check
         assertEquals(new Lf("lf1111", "lf1111 str2"), lst11_2_cont.getLfs().get("lf1111"));
-        assertEquals(new LfLst("lflst1111").addLf(new Lf("2049")).addLf(new Lf("1025")).addLf(new Lf("4097")),
-                lst11_2_cont.getLfLsts().get("lflst1111"));
+        assertEquals(new LfLst("lflst1111").addLf(new Lf(2049)).addLf(new Lf(1025)).addLf(new Lf(4097)), lst11_2_cont
+                .getLfLsts().get("lflst1111"));
 
         assertNotNull(lst11_2_cont.getLsts().get("lst1111"));
         checkLst1111(lst11_2_cont.getLsts().get("lst1111").getLstItems(), new Lf("lf1111A", "lf1111A str21"), new Lf(
-                "lf1111B", "5"), new Lf("lf1111A", "lf1111A str22"), new Lf("lf1111B", "8"));
+                "lf1111B", 5), new Lf("lf1111A", "lf1111A str22"), new Lf("lf1111B", 8));
 
-        checkLst11x(lst11_2.getLsts().get("lst111"), new LstItem().addLf(new Lf("lf1111", "55")),
-                new LstItem().addLf(new Lf("lf1111", "56")));
+        checkLst11x(lst11_2.getLsts().get("lst111"), new LstItem().addLf(new Lf("lf1111", 55)),
+                new LstItem().addLf(new Lf("lf1111", 56)));
         checkLst11x(lst11_2.getLsts().get("lst112"), new LstItem().addLf(new Lf("lf1121", "lf1121 str22")),
                 new LstItem().addLf(new Lf("lf1121", "lf1121 str21")));
     }
@@ -444,14 +450,14 @@ public class ToJsonBasicYangTypesTest {
 
         // cont111 check
         assertEquals(new Lf("lf1111", "lf1111 str"), lst11_1_cont.getLfs().get("lf1111"));
-        assertEquals(new LfLst("lflst1111").addLf(new Lf("2048")).addLf(new Lf("1024")).addLf(new Lf("4096")),
-                lst11_1_cont.getLfLsts().get("lflst1111"));
+        assertEquals(new LfLst("lflst1111").addLf(new Lf(2048)).addLf(new Lf(1024)).addLf(new Lf(4096)), lst11_1_cont
+                .getLfLsts().get("lflst1111"));
 
         assertNotNull(lst11_1_cont.getLsts().get("lst1111"));
         checkLst1111(lst11_1_cont.getLsts().get("lst1111").getLstItems(), new Lf("lf1111A", "lf1111A str11"), new Lf(
-                "lf1111B", "4"), new Lf("lf1111A", "lf1111A str12"), new Lf("lf1111B", "7"));
+                "lf1111B", 4), new Lf("lf1111A", "lf1111A str12"), new Lf("lf1111B", 7));
 
-        checkLst11x(lst11_1.getLsts().get("lst111"), new LstItem().addLf(new Lf("lf1111", "65")));
+        checkLst11x(lst11_1.getLsts().get("lst111"), new LstItem().addLf(new Lf("lf1111", 65)));
         checkLst11x(lst11_1.getLsts().get("lst112"), new LstItem().addLf(new Lf("lf1121", "lf1121 str11")));
     }
 
@@ -491,8 +497,8 @@ public class ToJsonBasicYangTypesTest {
                 null, ModifyAction.CREATE, null);
         cont1.getChildren().add(lst11_1);
 
-        MutableSimpleNode<?> lf111_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_1, "1",
-                ModifyAction.CREATE, null);
+        MutableSimpleNode<?> lf111_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_1,
+                (short) 1, ModifyAction.CREATE, null);
         lst11_1.getChildren().add(lf111_1);
 
         // lst111_1_1
@@ -500,7 +506,7 @@ public class ToJsonBasicYangTypesTest {
                 lst11_1, null, ModifyAction.CREATE, null);
         lst11_1.getChildren().add(lst111_1_1);
         MutableSimpleNode<?> lf1111_1_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111"),
-                lst111_1_1, "34", ModifyAction.CREATE, null);
+                lst111_1_1, (int) 34, ModifyAction.CREATE, null);
         lst111_1_1.getChildren().add(lf1111_1_1);
         lst111_1_1.init();
         // :lst111_1_1
@@ -510,7 +516,7 @@ public class ToJsonBasicYangTypesTest {
                 lst11_1, null, ModifyAction.CREATE, null);
         lst11_1.getChildren().add(lst111_1_2);
         MutableSimpleNode<?> lf1111_1_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111"),
-                lst111_1_2, "35", ModifyAction.CREATE, null);
+                lst111_1_2, (int) 35, ModifyAction.CREATE, null);
         lst111_1_2.getChildren().add(lf1111_1_2);
         lst111_1_2.init();
         // :lst111_1_2
@@ -541,8 +547,8 @@ public class ToJsonBasicYangTypesTest {
                 null, ModifyAction.CREATE, null);
         cont1.getChildren().add(lst11_2);
 
-        MutableSimpleNode<?> lf111_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_2, "2",
-                ModifyAction.CREATE, null);
+        MutableSimpleNode<?> lf111_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_2,
+                (short) 2, ModifyAction.CREATE, null);
         lst11_2.getChildren().add(lf111_2);
 
         // cont111_2
@@ -551,10 +557,10 @@ public class ToJsonBasicYangTypesTest {
         lst11_2.getChildren().add(cont111_2);
 
         MutableSimpleNode<?> lflst1111_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111"),
-                cont111_2, "1024", ModifyAction.CREATE, null);
+                cont111_2, (int) 1024, ModifyAction.CREATE, null);
         cont111_2.getChildren().add(lflst1111_2_2);
         MutableSimpleNode<?> lflst1111_2_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111"),
-                cont111_2, "4096", ModifyAction.CREATE, null);
+                cont111_2, (int) 4096, ModifyAction.CREATE, null);
         cont111_2.getChildren().add(lflst1111_2_3);
 
         // lst1111_2
@@ -562,16 +568,16 @@ public class ToJsonBasicYangTypesTest {
                 cont111_2, null, ModifyAction.CREATE, null);
         cont111_2.getChildren().add(lst1111_2_1);
         MutableSimpleNode<?> lf1111B_2_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111B"),
-                lst1111_2_1, "4", ModifyAction.CREATE, null);
+                lst1111_2_1, (short) 4, ModifyAction.CREATE, null);
         lst1111_2_1.getChildren().add(lf1111B_2_1);
         lst1111_2_1.init();
 
         MutableCompositeNode lst1111_2_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111"),
                 cont111_2, null, ModifyAction.CREATE, null);
         cont111_2.getChildren().add(lst1111_2_2);
-        MutableSimpleNode<?> lf1111B_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111A"),
+        MutableSimpleNode<?> lf1111A_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111A"),
                 lst1111_2_2, "lf1111A str12", ModifyAction.CREATE, null);
-        lst1111_2_2.getChildren().add(lf1111B_2_2);
+        lst1111_2_2.getChildren().add(lf1111A_2_2);
         lst1111_2_2.init();
         // :lst1111_2
 
@@ -591,8 +597,8 @@ public class ToJsonBasicYangTypesTest {
                 null, ModifyAction.CREATE, null);
         cont1.getChildren().add(lst11_3);
 
-        MutableSimpleNode<?> lf111_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_3, "3",
-                ModifyAction.CREATE, null);
+        MutableSimpleNode<?> lf111_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_3,
+                (short) 3, ModifyAction.CREATE, null);
         lst11_3.getChildren().add(lf111_3);
 
         // cont111_3
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonChoiceCaseTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/ToJsonChoiceCaseTest.java
new file mode 100644 (file)
index 0000000..b745411
--- /dev/null
@@ -0,0 +1,123 @@
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+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;
+
+public class ToJsonChoiceCaseTest extends YangAndXmlAndDataSchemaLoader {
+
+    @BeforeClass
+    public static void initialization() {
+        dataLoad("/cnsn-to-json/choice");
+    }
+
+    /**
+     * Test when some data are in one case node and other in another. This isn't
+     * correct. Next Json validator should return error because nodes has to be
+     * from one case below concrete choice.
+     * 
+     */
+    @Test
+    public void nodeSchemasOnVariousChoiceCasePathTest() {
+        testWrapper("/cnsn-to-json/choice/xml/data_various_path_err.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * Test when some data are in one case node and other in another.
+     * Additionally data are loadef from various choices. This isn't correct.
+     * Next Json validator should return error because nodes has to be from one
+     * case below concrete choice.
+     * 
+     */
+    @Test
+    public void nodeSchemasOnVariousChoiceCasePathAndMultipleChoicesTest() {
+        testWrapper("/cnsn-to-json/choice/xml/data_more_choices_same_level_various_paths_err.xml",
+                "choice-case-test:cont");
+    }
+
+    /**
+     * Test when second level data are red first, then first and at the end
+     * third level. Level represents pass through couple choice-case
+     */
+
+    @Test
+    public void nodeSchemasWithRandomOrderAccordingLevel() {
+        testWrapper("/cnsn-to-json/choice/xml/data_random_level.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * Test when element from no first case is used
+     */
+    @Test
+    public void nodeSchemasNotInFirstCase() {
+        testWrapper("/cnsn-to-json/choice/xml/data_no_first_case.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * Test when element in case is list
+     */
+    @Test
+    public void nodeSchemaAsList() {
+        testWrapper("/cnsn-to-json/choice/xml/data_list.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * Test when element in case is container
+     */
+    @Test
+    public void nodeSchemaAsContainer() {
+        testWrapper("/cnsn-to-json/choice/xml/data_container.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * Test when element in case is leaflist
+     */
+    @Test
+    public void nodeSchemaAsLeafList() {
+        testWrapper("/cnsn-to-json/choice/xml/data_leaflist.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * 
+     */
+    @Test
+    public void nodeSchemasInMultipleChoicesTest() {
+        testWrapper("/cnsn-to-json/choice/xml/data_more_choices_same_level.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * Test whether is possible to find data schema for node which is specified
+     * as dirrect subnode of choice (case without CASE key word)
+     */
+    @Test
+    public void nodeSchemasInCaseNotDefinedWithCaseKeyword() {
+        testWrapper("/cnsn-to-json/choice/xml/data_case_defined_without_case.xml", "choice-case-test:cont");
+    }
+
+    /**
+     * Test of multiple use of choices
+     */
+    @Test
+    public void nodeSchemasInThreeChoicesAtSameLevel() {
+        testWrapper("/cnsn-to-json/choice/xml/data_three_choices_same_level.xml", "choice-case-test:cont");
+    }
+
+    private void testWrapper(String xmlPath, String pathToSchemaNode) {
+        CompositeNode compNode = TestUtils.loadCompositeNode(xmlPath);
+        TestUtils.normalizeCompositeNode(compNode, modules, dataSchemaNode, pathToSchemaNode);
+        try {
+            TestUtils.writeCompNodeWithSchemaContextToJson(compNode, modules, dataSchemaNode);
+        } catch (WebApplicationException | IOException e) {
+            // shouldn't end here
+            assertTrue(false);
+        }
+    }
+}
@@ -1,14 +1,18 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
-import java.util.regex.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.ws.rs.WebApplicationException;
 
-import org.junit.*;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
 import org.opendaylight.yangtools.yang.data.api.*;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 
@@ -16,15 +20,14 @@ public class ToJsonIdentityrefTest extends YangAndXmlAndDataSchemaLoader {
 
     @BeforeClass
     public static void initialization() {
-        dataLoad("/yang-to-json-conversion/identityref", 2, "identityref-module", "cont");
+        dataLoad("/cnsn-to-json/identityref", 2, "identityref-module", "cont");
     }
 
     @Test
     public void identityrefToJsonTest() {
         String json = null;
         try {
-            json = TestUtils
-                    .writeCompNodeWithSchemaContextToJson(prepareCompositeNode(), null, modules, dataSchemaNode);
+            json = TestUtils.writeCompNodeWithSchemaContextToJson(prepareCompositeNode(), modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -40,9 +43,14 @@ public class ToJsonIdentityrefTest extends YangAndXmlAndDataSchemaLoader {
     private CompositeNode prepareCompositeNode() {
         MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
                 ModifyAction.CREATE, null);
-        MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1"), cont,
+        MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont1"), cont, null,
+                ModifyAction.CREATE, null);
+        cont.getChildren().add(cont1);
+
+        MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1"), cont1,
                 TestUtils.buildQName("name_test", "identityref:module", "2013-12-2"), ModifyAction.CREATE, null);
-        cont.getChildren().add(lf1);
+        cont1.getChildren().add(lf1);
+        cont1.init();
         cont.init();
 
         return cont;
@@ -1,4 +1,4 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -9,21 +9,30 @@ import java.util.regex.Matcher;
 import javax.ws.rs.WebApplicationException;
 
 import org.junit.*;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
+
+/**
+ * 
+ * All tests are commented now because leafref isn't supported now
+ * 
+ */
 
 public class ToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
 
     @BeforeClass
     public static void initialization() {
-        dataLoad("/yang-to-json-conversion/leafref", 2, "main-module", "cont");
+        dataLoad("/cnsn-to-json/leafref", 2, "main-module", "cont");
     }
 
+    @Ignore
     @Test
     public void leafrefAbsolutePathToExistingLeafTest() {
         String json = null;
         try {
-            json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
-                    .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_absolut_ref_to_existing_leaf.xml"),
-                    "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+            json = TestUtils.writeCompNodeWithSchemaContextToJson(
+                    TestUtils.loadCompositeNode("/cnsn-to-json/leafref/xml/data_absolut_ref_to_existing_leaf.xml"),
+                    modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -35,13 +44,14 @@ public class ToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
         assertTrue(mtch.matches());
     }
 
+    @Ignore
     @Test
     public void leafrefRelativePathToExistingLeafTest() {
         String json = null;
         try {
-            json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
-                    .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_relativ_ref_to_existing_leaf.xml"),
-                    "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+            json = TestUtils.writeCompNodeWithSchemaContextToJson(
+                    TestUtils.loadCompositeNode("/cnsn-to-json/leafref/xml/data_relativ_ref_to_existing_leaf.xml"),
+                    modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -57,13 +67,14 @@ public class ToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
      * Tests case when reference to not existing element is present. In this
      * case value from single node is printed as string.
      */
+    @Ignore
     @Test
     public void leafrefToNonExistingLeafTest() {
         String json = null;
         try {
-            json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
-                    .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_ref_to_non_existing_leaf.xml"),
-                    "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+            json = TestUtils.writeCompNodeWithSchemaContextToJson(
+                    TestUtils.loadCompositeNode("/cnsn-to-json/leafref/xml/data_ref_to_non_existing_leaf.xml"),
+                    modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -79,13 +90,14 @@ public class ToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
      * Tests case when non leaf element is referenced. In this case value from
      * single node is printed as string.
      */
+    @Ignore
     @Test
     public void leafrefToNotLeafTest() {
         String json = null;
         try {
             json = TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_ref_to_not_leaf.xml"),
-                    "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+                    TestUtils.loadCompositeNode("/cnsn-to-json/leafref/xml/data_ref_to_not_leaf.xml"), modules,
+                    dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -101,6 +113,7 @@ public class ToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
     /**
      * Tests case when leaflist element is refers to leaf.
      */
+    @Ignore
     @Test
     public void leafrefFromLeafListToLeafTest() {
         String json = null;
@@ -108,8 +121,8 @@ public class ToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
             json = TestUtils
                     .writeCompNodeWithSchemaContextToJson(
                             TestUtils
-                                    .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_relativ_ref_from_leaflist_to_existing_leaf.xml"),
-                            "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+                                    .loadCompositeNode("/cnsn-to-json/leafref/xml/data_relativ_ref_from_leaflist_to_existing_leaf.xml"),
+                            modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -126,13 +139,14 @@ public class ToJsonLeafrefType extends YangAndXmlAndDataSchemaLoader {
     /**
      * Tests case when leaflist element is refers to leaf.
      */
+    @Ignore
     @Test
     public void leafrefFromLeafrefToLeafrefTest() {
         String json = null;
         try {
-            json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
-                    .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_from_leafref_to_leafref.xml"),
-                    "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+            json = TestUtils.writeCompNodeWithSchemaContextToJson(
+                    TestUtils.loadCompositeNode("/cnsn-to-json/leafref/xml/data_from_leafref_to_leafref.xml"), modules,
+                    dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // shouldn't end here
             assertTrue(false);
@@ -1,8 +1,10 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
 
 import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 public class ToJsonWithAugmentTest {
 
@@ -12,9 +14,10 @@ public class ToJsonWithAugmentTest {
      */
     @Test
     public void augmentedElementsToJson() {
-        String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
-                TestUtils.loadCompositeNode("/yang-to-json-conversion/augmentation/xml/data.xml"),
-                "/yang-to-json-conversion/augmentation", "/yang-to-json-conversion/augmentation/xml", "yang", "cont");
+
+        CompositeNode compositeNode = TestUtils.loadCompositeNode("/cnsn-to-json/augmentation/xml/data.xml");
+        String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(compositeNode,
+                "/cnsn-to-json/augmentation", "/cnsn-to-json/augmentation/xml", "yang", "cont");
 
         assertTrue(jsonOutput.contains("\"augment-leaf:lf2\": \"lf2\""));
         assertTrue(jsonOutput.contains("\"augment-container:cont1\": {"));
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java
new file mode 100644 (file)
index 0000000..d043378
--- /dev/null
@@ -0,0 +1,247 @@
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.xml.test;
+
+import static org.junit.Assert.*;
+
+import java.io.StringWriter;
+import java.util.Set;
+
+import javax.activation.UnsupportedDataTypeException;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.XmlMapper;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.w3c.dom.Document;
+
+/**
+ * 
+ * CnSn = Composite node and Simple node data structure Class contains test of
+ * serializing simple nodes data values according data types from YANG schema to
+ * XML file
+ * 
+ */
+public class CnSnToXmlTest {
+
+    private static Set<Module> modules;
+    private static DataSchemaNode dataSchemaNode;
+
+    @BeforeClass
+    public static void initialization() {
+        modules = TestUtils.resolveModules("/cnsn-to-xml/yang");
+        assertEquals(2, modules.size());
+        Module module = TestUtils.resolveModule("basic-module", modules);
+        assertNotNull(module);
+        dataSchemaNode = TestUtils.resolveDataSchemaNode(module, "cont");
+        assertNotNull(dataSchemaNode);
+
+    }
+
+    @Test
+    public void snAsYangIdentityrefToXMLTest() {
+        serializeToXml(prepareIdentityrefData(), "<lf11 xmlns:x=\"referenced:module\">x:iden</lf11>");
+    }
+
+    @Test
+    public void snAsYangStringToXmlTest() {
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.STRING_DEFAULT_CODEC.deserialize("lfStr value"),
+                        "lfStr"), "<lfStr>lfStr value</lfStr>");
+    }
+
+    @Test
+    public void snAsYangInt8ToXmlTest() {
+        String elName = "lfInt8";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.INT8_DEFAULT_CODEC.deserialize("14"), elName), "<"
+                        + elName + ">14</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangInt16ToXmlTest() {
+        String elName = "lfInt16";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.INT16_DEFAULT_CODEC.deserialize("3000"), elName),
+                "<" + elName + ">3000</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangInt32ToXmlTest() {
+        String elName = "lfInt32";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.INT32_DEFAULT_CODEC.deserialize("201234"), elName),
+                "<" + elName + ">201234</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangInt64ToXmlTest() {
+        String elName = "lfInt64";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.INT64_DEFAULT_CODEC.deserialize("5123456789"),
+                        elName), "<" + elName + ">5123456789</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangUint8ToXmlTest() {
+        String elName = "lfUint8";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.UINT8_DEFAULT_CODEC.deserialize("200"), elName),
+                "<" + elName + ">200</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangUint16ToXmlTest() {
+        String elName = "lfUint16";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.UINT16_DEFAULT_CODEC.deserialize("4000"), elName),
+                "<" + elName + ">4000</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangUint32ToXmlTest() {
+        String elName = "lfUint32";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.UINT32_DEFAULT_CODEC.deserialize("4123456789"),
+                        elName), "<" + elName + ">4123456789</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangUint64ToXmlTest() {
+        String elName = "lfUint64";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.UINT64_DEFAULT_CODEC.deserialize("5123456789"),
+                        elName), "<" + elName + ">5123456789</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangBinaryToXmlTest() {
+        String elName = "lfBinary";
+        serializeToXml(
+                prepareCnStructForYangData(
+                        TypeDefinitionAwareCodec.BINARY_DEFAULT_CODEC
+                                .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"),
+                        elName), "<" + elName + ">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567</"
+                        + elName + ">");
+    }
+
+    @Test
+    public void snAsYangBitsToXmlTest() {
+        String elName = "lfBits";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.BITS_DEFAULT_CODEC.deserialize("one two"), elName),
+                "<" + elName + ">one two</" + elName + ">", "<" + elName + ">two one</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangEnumerationToXmlTest() {
+        String elName = "lfEnumeration";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.ENUMERATION_DEFAULT_CODEC.deserialize("enum2"),
+                        elName), "<" + elName + ">enum2</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangEmptyToXmlTest() {
+        String elName = "lfEmpty";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.EMPTY_DEFAULT_CODEC.deserialize(null), elName), "<"
+                        + elName + "/>");
+    }
+
+    @Test
+    public void snAsYangBooleanToXmlTest() {
+        String elName = "lfBoolean";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.BOOLEAN_DEFAULT_CODEC.deserialize("str"), elName),
+                "<" + elName + ">false</" + elName + ">");
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.BOOLEAN_DEFAULT_CODEC.deserialize("true"), elName),
+                "<" + elName + ">true</" + elName + ">");
+    }
+
+    @Test
+    public void snAsYangUnionToXmlTest() {
+        String elName = "lfUnion";
+        String int8 = "15";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.UNION_DEFAULT_CODEC.deserialize(int8), elName), "<"
+                        + elName + ">15</" + elName + ">");
+
+        String bits = "first second";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.UNION_DEFAULT_CODEC.deserialize(bits), elName), "<"
+                        + elName + ">first second</" + elName + ">");
+
+        String bool = "str";
+        serializeToXml(
+                prepareCnStructForYangData(TypeDefinitionAwareCodec.UNION_DEFAULT_CODEC.deserialize(bool), elName), "<"
+                        + elName + ">str</" + elName + ">");
+    }
+
+    private void serializeToXml(CompositeNode compositeNode, String... xmlRepresentation)
+            throws TransformerFactoryConfigurationError {
+        XmlMapper xmlMapper = new XmlMapper();
+        String xmlString = null;
+        if (dataSchemaNode instanceof DataNodeContainer) {
+            try {
+                Document doc = xmlMapper.write(compositeNode, (DataNodeContainer) dataSchemaNode);
+                DOMSource domSource = new DOMSource(doc);
+                StringWriter writer = new StringWriter();
+                StreamResult result = new StreamResult(writer);
+                TransformerFactory tf = TransformerFactory.newInstance();
+                Transformer transformer = tf.newTransformer();
+                transformer.transform(domSource, result);
+                xmlString = writer.toString();
+            } catch (UnsupportedDataTypeException | TransformerException e) {
+            }
+        }
+        assertNotNull(xmlMapper);
+        boolean containSearchedStr = false;
+        String strRepresentation = "";
+        for (String searchedStr : xmlRepresentation) {
+            if (xmlString.contains(searchedStr)) {
+                containSearchedStr = true;
+                break;
+            }
+            strRepresentation = strRepresentation + "[" + searchedStr + "]";
+        }
+        assertTrue("At least one of specified strings " + strRepresentation + " wasn't found.", containSearchedStr);
+
+    }
+
+    private CompositeNode prepareIdentityrefData() {
+        MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
+                TestUtils.buildQName("cont", "basic:module", "2013-12-2"), null, null, ModifyAction.CREATE, null);
+        MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
+                TestUtils.buildQName("cont1", "basic:module", "2013-12-2"), cont, null, ModifyAction.CREATE, null);
+        cont.getChildren().add(cont1);
+
+        MutableSimpleNode<Object> lf11 = NodeFactory.createMutableSimpleNode(
+                TestUtils.buildQName("lf11", "basic:module", "2013-12-2"), cont1,
+                TestUtils.buildQName("iden", "referenced:module", "2013-12-2"), ModifyAction.CREATE, null);
+        cont1.getChildren().add(lf11);
+        cont1.init();
+        cont.init();
+
+        return cont;
+    }
+
+    private CompositeNode prepareCnStructForYangData(Object data, String leafName) {
+        MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
+                ModifyAction.CREATE, null);
+
+        MutableSimpleNode<Object> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(leafName), cont, data,
+                ModifyAction.CREATE, null);
+        cont.getChildren().add(lf1);
+        cont.init();
+
+        return cont;
+    }
+
+}
@@ -1,43 +1,41 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
+package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
 import java.net.URISyntaxException;
 import java.util.List;
+import java.util.Set;
 
 import javax.ws.rs.WebApplicationException;
 
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.*;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.gson.JsonSyntaxException;
 
-public class FromJsonToCompositeNodeTest {
+public class JsonToCnSnTest {
 
-    private static final Logger LOG = LoggerFactory.getLogger(FromJsonToCompositeNodeTest.class);
+    private static final Logger LOG = LoggerFactory.getLogger(JsonToCnSnTest.class);
 
     @Test
     public void simpleListTest() {
-        simpleTest("/json-to-composite-node/simple-list.json", "/json-to-composite-node/simple-list-yang", "lst",
-                "simple:list:yang1", "simple-list-yang1");
+        simpleTest("/json-to-cnsn/simple-list.json", "/json-to-cnsn/simple-list-yang", "lst", "simple:list:yang1",
+                "simple-list-yang1");
     }
 
     @Test
     public void simpleContainerTest() {
-        simpleTest("/json-to-composite-node/simple-container.json", "/json-to-composite-node/simple-container-yang",
-                "cont", "simple:container:yang", "simple-container-yang");
+        simpleTest("/json-to-cnsn/simple-container.json", "/json-to-cnsn/simple-container-yang", "cont",
+                "simple:container:yang", "simple-container-yang");
     }
 
     /**
@@ -45,8 +43,7 @@ public class FromJsonToCompositeNodeTest {
      */
     @Test
     public void multipleItemsInLeafList() {
-        CompositeNode compositeNode = compositeContainerFromJson(
-                "/json-to-composite-node/multiple-leaflist-items.json", true);
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-cnsn/multiple-leaflist-items.json", true);
         assertNotNull(compositeNode);
         assertEquals(3, compositeNode.getChildren().size());
 
@@ -79,8 +76,7 @@ public class FromJsonToCompositeNodeTest {
      */
     @Test
     public void multipleItemsInListTest() {
-        CompositeNode compositeNode = compositeContainerFromJson("/json-to-composite-node/multiple-items-in-list.json",
-                true);
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-cnsn/multiple-items-in-list.json", true);
         assertNotNull(compositeNode);
 
         assertEquals("lst", compositeNode.getNodeType().getLocalName());
@@ -90,7 +86,7 @@ public class FromJsonToCompositeNodeTest {
 
     @Test
     public void nullArrayToSimpleNodeWithNullValueTest() {
-        CompositeNode compositeNode = compositeContainerFromJson("/json-to-composite-node/array-with-null.json", true);
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-cnsn/array-with-null.json", true);
         assertNotNull(compositeNode);
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
 
@@ -107,7 +103,7 @@ public class FromJsonToCompositeNodeTest {
     public void incorrectTopLevelElementsTest() {
         Throwable cause1 = null;
         try {
-            compositeContainerFromJson("/json-to-composite-node/wrong-top-level1.json", true);
+            compositeContainerFromJson("/json-to-cnsn/wrong-top-level1.json", true);
         } catch (WebApplicationException e) {
             cause1 = e;
         }
@@ -121,7 +117,7 @@ public class FromJsonToCompositeNodeTest {
 
         Throwable cause2 = null;
         try {
-            compositeContainerFromJson("/json-to-composite-node/wrong-top-level2.json", true);
+            compositeContainerFromJson("/json-to-cnsn/wrong-top-level2.json", true);
         } catch (WebApplicationException e) {
             cause2 = e;
         }
@@ -130,7 +126,7 @@ public class FromJsonToCompositeNodeTest {
 
         Throwable cause3 = null;
         try {
-            compositeContainerFromJson("/json-to-composite-node/wrong-top-level3.json", true);
+            compositeContainerFromJson("/json-to-cnsn/wrong-top-level3.json", true);
         } catch (WebApplicationException e) {
             cause3 = e;
         }
@@ -149,7 +145,7 @@ public class FromJsonToCompositeNodeTest {
      */
     @Test
     public void emptyDataReadTest() {
-        CompositeNode compositeNode = compositeContainerFromJson("/json-to-composite-node/empty-data.json", true);
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-cnsn/empty-data.json", true);
 
         assertNotNull(compositeNode);
 
@@ -162,7 +158,7 @@ public class FromJsonToCompositeNodeTest {
 
         String reason = null;
         try {
-            compositeContainerFromJson("/json-to-composite-node/empty-data1.json", true);
+            compositeContainerFromJson("/json-to-cnsn/empty-data1.json", true);
         } catch (JsonSyntaxException e) {
             reason = e.getMessage();
         }
@@ -180,16 +176,14 @@ public class FromJsonToCompositeNodeTest {
     @Test
     public void notSupplyNamespaceIfAlreadySupplied() {
 
-        CompositeNode compositeNode = compositeContainerFromJson("/json-to-composite-node/simple-list.json");
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-cnsn/simple-list.json");
         assertNotNull(compositeNode);
 
         DataSchemaNode dataSchemaNode1 = null;
         DataSchemaNode dataSchemaNode2 = null;
         try {
-            dataSchemaNode1 = TestUtils.obtainSchemaFromYang("/json-to-composite-node/simple-list-yang",
-                    "simple-list-yang1");
-            dataSchemaNode2 = TestUtils.obtainSchemaFromYang("/json-to-composite-node/simple-list-yang",
-                    "simple-list-yang2");
+            dataSchemaNode1 = TestUtils.obtainSchemaFromYang("/json-to-cnsn/simple-list-yang", "simple-list-yang1");
+            dataSchemaNode2 = TestUtils.obtainSchemaFromYang("/json-to-cnsn/simple-list-yang", "simple-list-yang2");
         } catch (FileNotFoundException e) {
             LOG.error(e.getMessage());
             assertTrue(false);
@@ -214,6 +208,64 @@ public class FromJsonToCompositeNodeTest {
 
     }
 
+    @Test
+    public void jsonIdentityrefToCompositeNode() {
+        CompositeNode compositeNode = compositeContainerFromJson("/json-to-cnsn/identityref/json/data.json");
+        assertNotNull(compositeNode);
+
+        Set<Module> modules = TestUtils.resolveModules("/json-to-cnsn/identityref");
+        assertEquals(2, modules.size());
+        Module module = TestUtils.resolveModule("identityref-module", modules);
+        assertNotNull(module);
+        DataSchemaNode dataSchemaNode = TestUtils.resolveDataSchemaNode(module, null);
+        assertNotNull(dataSchemaNode);
+
+        TestUtils.normalizeCompositeNode(compositeNode, modules, dataSchemaNode, "identityref-module:cont");
+
+        assertEquals("cont", compositeNode.getNodeType().getLocalName());
+
+        List<Node<?>> childs = compositeNode.getChildren();
+        assertEquals(1, childs.size());
+        Node<?> nd = childs.iterator().next();
+        assertTrue(nd instanceof CompositeNode);
+        assertEquals("cont1", nd.getNodeType().getLocalName());
+
+        childs = ((CompositeNode) nd).getChildren();
+        assertEquals(4, childs.size());
+        SimpleNode<?> lf11 = null;
+        SimpleNode<?> lf12 = null;
+        SimpleNode<?> lf13 = null;
+        SimpleNode<?> lf14 = null;
+        for (Node<?> child : childs) {
+            assertTrue(child instanceof SimpleNode);
+            if (child.getNodeType().getLocalName().equals("lf11")) {
+                lf11 = (SimpleNode<?>) child;
+            } else if (child.getNodeType().getLocalName().equals("lf12")) {
+                lf12 = (SimpleNode<?>) child;
+            } else if (child.getNodeType().getLocalName().equals("lf13")) {
+                lf13 = (SimpleNode<?>) child;
+            } else if (child.getNodeType().getLocalName().equals("lf14")) {
+                lf14 = (SimpleNode<?>) child;
+            }
+        }
+
+        assertTrue(lf11.getValue() instanceof QName);
+        assertEquals("iden", ((QName) lf11.getValue()).getLocalName());
+        assertEquals("identity:module", ((QName) lf11.getValue()).getNamespace().toString());
+
+        assertTrue(lf12.getValue() instanceof QName);
+        assertEquals("iden_local", ((QName) lf12.getValue()).getLocalName());
+        assertEquals("identityref:module", ((QName) lf12.getValue()).getNamespace().toString());
+
+        assertTrue(lf13.getValue() instanceof QName);
+        assertEquals("iden_local", ((QName) lf13.getValue()).getLocalName());
+        assertEquals("identityref:module", ((QName) lf13.getValue()).getNamespace().toString());
+
+        assertTrue(lf14.getValue() instanceof QName);
+        assertEquals("iden_local", ((QName) lf14.getValue()).getLocalName());
+        assertEquals("identity:module", ((QName) lf14.getValue()).getNamespace().toString());
+    }
+
     private void simpleTest(String jsonPath, String yangPath, String topLevelElementName, String namespace,
             String moduleName) {
         CompositeNode compositeNode = compositeContainerFromJson(jsonPath);
@@ -325,7 +377,7 @@ public class FromJsonToCompositeNodeTest {
             throws WebApplicationException {
 
         JsonToCompositeNodeProvider jsonToCompositeNodeProvider = JsonToCompositeNodeProvider.INSTANCE;
-        InputStream jsonStream = FromJsonToCompositeNodeTest.class.getResourceAsStream(jsonPath);
+        InputStream jsonStream = JsonToCnSnTest.class.getResourceAsStream(jsonPath);
         try {
             CompositeNode compositeNode = jsonToCompositeNodeProvider
                     .readFrom(null, null, null, null, null, jsonStream);
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ReadConfAndOperDataTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ReadConfAndOperDataTest.java
new file mode 100644 (file)
index 0000000..cac77eb
--- /dev/null
@@ -0,0 +1,118 @@
+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.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.FileNotFoundException;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+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.RestconfImpl;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import com.google.common.base.Charsets;
+
+public class ReadConfAndOperDataTest extends JerseyTest {
+
+    private static ControllerContext controllerContext;
+    private static BrokerFacade brokerFacade;
+    private static RestconfImpl restconfImpl;
+    private static final MediaType MEDIA_TYPE_DRAFT02 = new MediaType("application", "yang.data+xml");
+
+    @BeforeClass
+    public static void init() throws FileNotFoundException {
+        Set<Module> allModules = TestUtils.loadModules(RestconfImplTest.class.getResource("/full-versions/yangs")
+                .getPath());
+        SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+        controllerContext = ControllerContext.getInstance();
+        controllerContext.setSchemas(schemaContext);
+        brokerFacade = mock(BrokerFacade.class);
+        restconfImpl = RestconfImpl.getInstance();
+        restconfImpl.setBroker(brokerFacade);
+        restconfImpl.setControllerContext(controllerContext);
+    }
+
+    @Before
+    public void logs() {
+        List<LogRecord> loggedRecords = getLoggedRecords();
+        for (LogRecord l : loggedRecords) {
+            System.out.println(l.getMessage());
+        }
+    }
+
+    @Test
+    public void testReadConfigurationData() throws UnsupportedEncodingException, FileNotFoundException {
+
+        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
+
+        CompositeNode loadedCompositeNode = TestUtils.loadCompositeNodeWithXmlTreeBuilder("/parts/ietf-interfaces_interfaces.xml");
+        when(brokerFacade.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
+
+        Response response = target(uri).request(MEDIA_TYPE_DRAFT02).get();
+        assertEquals(200, response.getStatus());
+        
+        uri = createUri("/config/", "ietf-interfaces:interfaces/interface/example");
+        when(brokerFacade.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(null);
+        
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).get();
+        assertEquals(404, response.getStatus());
+    }
+
+    @Test
+    public void testReadOperationalData() throws UnsupportedEncodingException, FileNotFoundException {
+        String uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
+
+        CompositeNode loadedCompositeNode = TestUtils.loadCompositeNodeWithXmlTreeBuilder("/parts/ietf-interfaces_interfaces.xml");
+        when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
+
+        Response response = target(uri).request(MEDIA_TYPE_DRAFT02).get();
+        assertEquals(200, response.getStatus());
+        
+        uri = createUri("/config/", "ietf-interfaces:interfaces/interface/example");
+        when(brokerFacade.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(null);
+        
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).get();
+        assertEquals(404, response.getStatus());
+    }
+
+    private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
+        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
+    }
+
+    @Override
+    protected Application configure() {
+        enable(TestProperties.LOG_TRAFFIC);
+        enable(TestProperties.DUMP_ENTITY);
+        enable(TestProperties.RECORD_LOG_LEVEL);
+        set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue());
+
+        ResourceConfig resourceConfig = new ResourceConfig();
+        resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
+                XmlToCompositeNodeProvider.INSTANCE);
+        return resourceConfig;
+    }
+}
index c36de6e4eabc9abc11c10d20cb3eab353e73d096..41cc0ddb5130f0fc49e4b76f51e9d423f25fd47a 100644 (file)
@@ -1,7 +1,9 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static org.mockito.Mockito.*;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -9,9 +11,7 @@ import java.util.Set;
 
 import org.junit.BeforeClass;
 import org.junit.Test;
-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.restconf.impl.*;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.Module;
@@ -23,7 +23,8 @@ public class RestconfImplTest {
 
     @BeforeClass
     public static void init() throws FileNotFoundException {
-        Set<Module> allModules = TestUtils.loadModules(RestconfImplTest.class.getResource("/full-versions/yangs").getPath());
+        Set<Module> allModules = TestUtils.loadModules(RestconfImplTest.class.getResource("/full-versions/yangs")
+                .getPath());
         SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
         ControllerContext controllerContext = ControllerContext.getInstance();
         controllerContext.setSchemas(schemaContext);
@@ -33,7 +34,7 @@ public class RestconfImplTest {
     @Test
     public void testExample() throws FileNotFoundException {
         InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
-        CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream);
+        CompositeNode loadedCompositeNode = TestUtils.loadCompositeNodeWithXmlTreeBuilder(xmlStream);
         BrokerFacade brokerFacade = mock(BrokerFacade.class);
         when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
         assertEquals(loadedCompositeNode, brokerFacade.readOperationalData(null));
index 20dfb31dab3362261fb1496dd1da9246fbc8052a..366d99dbcb88a3dcb18f55c826b0b1c2dcc09b93 100644 (file)
@@ -1,13 +1,13 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.io.*;
-import java.net.*;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.sql.Date;
 import java.util.*;
 import java.util.concurrent.Future;
@@ -20,21 +20,23 @@ 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.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.rest.impl.*;
 import org.opendaylight.controller.sal.restconf.impl.*;
-import org.opendaylight.yangtools.yang.common.*;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.*;
 import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
 import org.opendaylight.yangtools.yang.model.api.*;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import org.slf4j.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
 import com.google.common.base.Preconditions;
 
-final class TestUtils {
+public final class TestUtils {
 
     private static final Logger logger = LoggerFactory.getLogger(TestUtils.class);
 
@@ -75,27 +77,7 @@ final class TestUtils {
         return result;
     }
 
-    public static CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
-        if (xmlInputStream == null) {
-            throw new IllegalArgumentException();
-        }
-        Node<?> dataTree;
-        try {
-            dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
-        } catch (XMLStreamException e) {
-            logger.error("Error during building data tree from XML", e);
-            return null;
-        }
-        if (dataTree == null) {
-            logger.error("data tree is null");
-            return null;
-        }
-        if (dataTree instanceof SimpleNode) {
-            logger.error("RPC XML was resolved as SimpleNode");
-            return null;
-        }
-        return (CompositeNode) dataTree;
-    }
+
 
     public static Document loadDocumentFrom(InputStream inputStream) {
         try {
@@ -131,18 +113,17 @@ final class TestUtils {
 
     }
 
-    static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath, String outputPath) {
-        return convertCompositeNodeDataAndYangToJson(compositeNode, yangPath, outputPath, null, null);
-    }
-
-    static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath,
+    public static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath,
             String outputPath, String searchedModuleName, String searchedDataSchemaName) {
         Set<Module> modules = resolveModules(yangPath);
         Module module = resolveModule(searchedModuleName, modules);
         DataSchemaNode dataSchemaNode = resolveDataSchemaNode(module, searchedDataSchemaName);
 
+        normalizeCompositeNode(compositeNode, modules, dataSchemaNode, searchedModuleName + ":"
+                + searchedDataSchemaName);
+
         try {
-            return writeCompNodeWithSchemaContextToJson(compositeNode, outputPath, modules, dataSchemaNode);
+            return writeCompNodeWithSchemaContextToJson(compositeNode, modules, dataSchemaNode);
         } catch (WebApplicationException | IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
@@ -151,7 +132,16 @@ final class TestUtils {
 
     }
 
-    static Module resolveModule(String searchedModuleName, Set<Module> modules) {
+    public static void normalizeCompositeNode(CompositeNode compositeNode, Set<Module> modules,
+            DataSchemaNode dataSchemaNode, String schemaNodePath) {
+        RestconfImpl restconf = RestconfImpl.getInstance();
+        ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext(modules));
+
+        TestUtils.prepareMockForRestconfBeforeNormalization(modules, dataSchemaNode, restconf);
+        restconf.createConfigurationData(schemaNodePath, compositeNode);
+    }
+
+    public static Module resolveModule(String searchedModuleName, Set<Module> modules) {
         assertNotNull("modules can't be null.", modules);
         Module module = null;
         if (searchedModuleName != null) {
@@ -167,11 +157,11 @@ final class TestUtils {
         return module;
     }
 
-    static Set<Module> resolveModules(String yangPath) {
+    public static Set<Module> resolveModules(String yangPath) {
         Set<Module> modules = null;
 
         try {
-            modules = TestUtils.loadModules(ToJsonBasicDataTypesTest.class.getResource(yangPath).getPath());
+            modules = TestUtils.loadModules(TestUtils.class.getResource(yangPath).getPath());
         } catch (FileNotFoundException e) {
             e.printStackTrace();
         }
@@ -179,7 +169,7 @@ final class TestUtils {
         return modules;
     }
 
-    static DataSchemaNode resolveDataSchemaNode(Module module, String searchedDataSchemaName) {
+    public static DataSchemaNode resolveDataSchemaNode(Module module, String searchedDataSchemaName) {
         assertNotNull("Module is missing", module);
 
         DataSchemaNode dataSchemaNode = null;
@@ -195,39 +185,33 @@ final class TestUtils {
         return dataSchemaNode;
     }
 
-    static String writeCompNodeWithSchemaContextToJson(CompositeNode compositeNode, String outputPath,
-            Set<Module> modules, DataSchemaNode dataSchemaNode) throws IOException, WebApplicationException {
+    public static String writeCompNodeWithSchemaContextToJson(CompositeNode compositeNode, Set<Module> modules,
+            DataSchemaNode dataSchemaNode) throws IOException, WebApplicationException {
         String jsonResult;
 
         assertNotNull(dataSchemaNode);
         assertNotNull("Composite node can't be null", compositeNode);
         ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
 
-        ControllerContext contContext = ControllerContext.getInstance();
-        contContext.setSchemas(loadSchemaContext(modules));
+        ControllerContext.getInstance().setSchemas(loadSchemaContext(modules));
 
         StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
         structuredDataToJsonProvider.writeTo(new StructuredData(compositeNode, dataSchemaNode), null, null, null, null,
                 null, byteArrayOS);
 
         jsonResult = byteArrayOS.toString();
-        if (outputPath != null) {
-            try {
-                outputToFile(byteArrayOS, outputPath);
-            } catch (IOException e) {
-                System.out.println("Output file wasn't cloased sucessfuly.");
-            }
-        }
 
         return jsonResult;
     }
 
-    static CompositeNode loadCompositeNode(String xmlDataPath) {
-        InputStream xmlStream = ToJsonBasicDataTypesTest.class.getResourceAsStream(xmlDataPath);
+    public static CompositeNode loadCompositeNode(String xmlDataPath) {
+        InputStream xmlStream = TestUtils.class.getResourceAsStream(xmlDataPath);
         CompositeNode compositeNode = null;
         try {
-            compositeNode = TestUtils.loadCompositeNode(xmlStream);
-        } catch (FileNotFoundException e) {
+            XmlReader xmlReader = new XmlReader();
+            compositeNode = xmlReader.read(xmlStream);
+
+        } catch (UnsupportedFormatException | XMLStreamException e) {
             e.printStackTrace();
         }
         return compositeNode;
@@ -236,7 +220,7 @@ final class TestUtils {
     static void outputToFile(ByteArrayOutputStream outputStream, String outputDir) throws IOException {
         FileOutputStream fileOS = null;
         try {
-            String path = ToJsonBasicDataTypesTest.class.getResource(outputDir).getPath();
+            String path = TestUtils.class.getResource(outputDir).getPath();
             File outFile = new File(path + "/data.json");
             fileOS = new FileOutputStream(outFile);
             try {
@@ -285,7 +269,7 @@ final class TestUtils {
     }
 
     private static FileReader getFileReader(String path) {
-        String fullPath = ToJsonBasicDataTypesTest.class.getResource(path).getPath();
+        String fullPath = TestUtils.class.getResource(path).getPath();
         assertNotNull("Path to file can't be null.", fullPath);
         File file = new File(fullPath);
         assertNotNull("File can't be null", file);
@@ -317,7 +301,7 @@ final class TestUtils {
         return strBuilder.toString();
     }
 
-    static QName buildQName(String name, String uri, String date) {
+    public static QName buildQName(String name, String uri, String date) {
         try {
             URI u = new URI(uri);
             Date dt = null;
@@ -330,11 +314,11 @@ final class TestUtils {
         }
     }
 
-    static QName buildQName(String name) {
+    public static QName buildQName(String name) {
         return buildQName(name, "", null);
     }
 
-    static void supplementNamespace(DataSchemaNode dataSchemaNode, CompositeNode compositeNode) {
+    public static void supplementNamespace(DataSchemaNode dataSchemaNode, CompositeNode compositeNode) {
         RestconfImpl restconf = RestconfImpl.getInstance();
 
         InstanceIdWithSchemaNode instIdAndSchema = new InstanceIdWithSchemaNode(mock(InstanceIdentifier.class),
@@ -358,13 +342,14 @@ final class TestUtils {
         restconf.createConfigurationData("something", compositeNode);
     }
 
-    static DataSchemaNode obtainSchemaFromYang(String yangFolder) throws FileNotFoundException {
+    public static DataSchemaNode obtainSchemaFromYang(String yangFolder) throws FileNotFoundException {
         return obtainSchemaFromYang(yangFolder, null);
     }
 
-    static DataSchemaNode obtainSchemaFromYang(String yangFolder, String moduleName) throws FileNotFoundException {
+    public static DataSchemaNode obtainSchemaFromYang(String yangFolder, String moduleName)
+            throws FileNotFoundException {
         Set<Module> modules = null;
-        modules = TestUtils.loadModules(ToJsonBasicDataTypesTest.class.getResource(yangFolder).getPath());
+        modules = TestUtils.loadModules(TestUtils.class.getResource(yangFolder).getPath());
 
         if (modules == null) {
             return null;
@@ -403,7 +388,7 @@ final class TestUtils {
 
     }
 
-    static void addDummyNamespaceToAllNodes(NodeWrapper<?> wrappedNode) throws URISyntaxException {
+    public static void addDummyNamespaceToAllNodes(NodeWrapper<?> wrappedNode) throws URISyntaxException {
         wrappedNode.setNamespace(new URI(""));
         if (wrappedNode instanceof CompositeNodeWrapper) {
             for (NodeWrapper<?> childNodeWrapper : ((CompositeNodeWrapper) wrappedNode).getValues()) {
@@ -412,4 +397,56 @@ final class TestUtils {
         }
     }
 
+    public static void prepareMockForRestconfBeforeNormalization(Set<Module> modules, DataSchemaNode dataSchemaNode,
+            RestconfImpl restconf) {
+        ControllerContext instance = ControllerContext.getInstance();
+        instance.setSchemas(TestUtils.loadSchemaContext(modules));
+        restconf.setControllerContext(ControllerContext.getInstance());
+
+        BrokerFacade mockedBrokerFacade = mock(BrokerFacade.class);
+        when(mockedBrokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class)))
+                .thenReturn(
+                        new DummyFuture.Builder().rpcResult(
+                                new DummyRpcResult.Builder<TransactionStatus>().result(TransactionStatus.COMMITED)
+                                        .build()).build());
+        restconf.setBroker(mockedBrokerFacade);
+    }
+    
+    static CompositeNode loadCompositeNodeWithXmlTreeBuilder(String xmlDataPath) {
+        InputStream xmlStream = TestUtils.class.getResourceAsStream(xmlDataPath);
+        CompositeNode compositeNode = null;
+        try {
+            compositeNode = TestUtils.loadCompositeNodeWithXmlTreeBuilder(xmlStream);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        return compositeNode;
+        
+        
+        
+    }
+    
+    
+    public static CompositeNode loadCompositeNodeWithXmlTreeBuilder(InputStream xmlInputStream) throws FileNotFoundException {
+        if (xmlInputStream == null) {
+            throw new IllegalArgumentException();
+        }
+        Node<?> dataTree;
+        try {
+            dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
+        } catch (XMLStreamException e) {
+            logger.error("Error during building data tree from XML", e);
+            return null;
+        }
+        if (dataTree == null) {
+            logger.error("data tree is null");
+            return null;
+        }
+        if (dataTree instanceof SimpleNode) {
+            logger.error("RPC XML was resolved as SimpleNode");
+            return null;
+        }
+        return (CompositeNode) dataTree;
+    }        
+
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonBasicDataTypesTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonBasicDataTypesTest.java
deleted file mode 100644 (file)
index 69de9f8..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.*;
-import java.util.*;
-
-import org.junit.Test;
-
-import com.google.gson.stream.*;
-
-public class ToJsonBasicDataTypesTest {
-
-    @Test
-    public void simpleYangDataTest() {
-        String jsonOutput;
-        jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
-                TestUtils.loadCompositeNode("/yang-to-json-conversion/simple-data-types/xml/data.xml"),
-                "/yang-to-json-conversion/simple-data-types", "/yang-to-json-conversion/simple-data-types/xml");
-        verifyJsonOutput(jsonOutput);
-    }
-
-    private void verifyJsonOutput(String jsonOutput) {
-        StringReader strReader = new StringReader(jsonOutput);
-        JsonReader jReader = new JsonReader(strReader);
-
-        String exception = null;
-        try {
-            jsonReadCont(jReader);
-        } catch (IOException e) {
-            exception = e.getMessage();
-        }
-
-        assertNull("Error during reading Json output: " + exception, exception);
-    }
-
-    private void jsonReadCont(JsonReader jReader) throws IOException {
-        jReader.beginObject();
-        assertNotNull("cont1 is missing.", jReader.hasNext());
-
-        // Cont dataFromJson = new Cont(jReader.nextName());
-        jReader.nextName();
-        jsonReadContElements(jReader);
-
-        assertFalse("cont shouldn't have other element.", jReader.hasNext());
-        jReader.endObject();
-        // return dataFromJson;
-    }
-
-    private void jsonReadContElements(JsonReader jReader) throws IOException {
-        jReader.beginObject();
-        List<String> loadedLfs = new ArrayList<>();
-        boolean exceptForDecimal5Raised = false;
-        boolean enumChecked = false;
-        boolean bitsChecked = false;
-        boolean lfdecimal6Checked = false;
-        boolean lfdecimal4Checked = false;
-        boolean lfdecimal3Checked = false;
-        boolean lfdecimal2Checked = false;
-        boolean lfdecimal1Checked = false;
-        boolean lfbool1Checked = false;
-        boolean lfbool2Checked = false;
-        boolean lfstrChecked = false;
-        boolean lfbinaryChecked = false;
-        // boolean lfref1Checked = false;
-        boolean lfemptyChecked = false;
-        boolean lfstr1Checked = false;
-
-        while (jReader.hasNext()) {
-            String keyName = jReader.nextName();
-            JsonToken peek = null;
-            try {
-                peek = jReader.peek();
-            } catch (IOException e) {
-                if (keyName.equals("lfdecimal5")) {
-                    exceptForDecimal5Raised = true;
-                } else {
-                    assertTrue("Key " + keyName + " has incorrect value for specifed type", false);
-                }
-            }
-
-            if (keyName.startsWith("lfnint") || keyName.startsWith("lfnuint")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-                try {
-                    jReader.nextLong();
-                } catch (NumberFormatException e) {
-                    assertTrue("Key " + keyName + " has incorrect value - " + e.getMessage(), false);
-                }
-                loadedLfs.add(keyName.substring(3));
-            } else if (keyName.equals("lfstr")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-                assertEquals("lfstr", jReader.nextString());
-                lfstrChecked = true;
-            } else if (keyName.equals("lfstr1")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-                assertEquals("", jReader.nextString());
-                lfstr1Checked = true;
-            } else if (keyName.equals("lfbool1")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
-                assertEquals(true, jReader.nextBoolean());
-                lfbool1Checked = true;
-            } else if (keyName.equals("lfbool2")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
-                assertEquals(false, jReader.nextBoolean());
-                lfbool2Checked = true;
-            } else if (keyName.equals("lfbool3")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
-                assertEquals(false, jReader.nextBoolean());
-            } else if (keyName.equals("lfdecimal1")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-                assertEquals(new Double(43.32), (Double) jReader.nextDouble());
-                lfdecimal1Checked = true;
-            } else if (keyName.equals("lfdecimal2")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-                assertEquals(new Double(-0.43), (Double) jReader.nextDouble());
-                lfdecimal2Checked = true;
-            } else if (keyName.equals("lfdecimal3")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-                assertEquals(new Double(43), (Double) jReader.nextDouble());
-                lfdecimal3Checked = true;
-            } else if (keyName.equals("lfdecimal4")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-                assertEquals(new Double(43E3), (Double) jReader.nextDouble());
-                lfdecimal4Checked = true;
-            } else if (keyName.equals("lfdecimal6")) {
-                assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-                assertEquals(new Double(33.12345), (Double) jReader.nextDouble());
-                lfdecimal6Checked = true;
-            } else if (keyName.equals("lfenum")) {
-                assertEquals("enum3", jReader.nextString());
-                enumChecked = true;
-            } else if (keyName.equals("lfbits")) {
-                assertEquals("bit3", jReader.nextString());
-                bitsChecked = true;
-            } else if (keyName.equals("lfbinary")) {
-                assertEquals("AAaacdabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%%-#^", jReader.nextString());
-                lfbinaryChecked = true;
-            } else if (keyName.equals("lfempty")) {
-                jReader.beginArray();
-                jReader.nextNull();
-                jReader.endArray();
-                lfemptyChecked = true;
-            } else if (keyName.startsWith("lfunion")) {
-                checkLfUnion(jReader, keyName, peek);
-            } else {
-                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
-            }
-
-        }
-        Collections.sort(loadedLfs);
-        String expectedLfsStr = "[int16Max, int16Min, int32Max, int32Min, int64Max, int64Min, int8Max, int8Min, uint16Max, uint32Max, uint8Max]";
-        String actualLfsStr = loadedLfs.toString();
-        assertEquals("Some leaves are missing", expectedLfsStr, actualLfsStr);
-        // assertTrue("For lfdecimal5 wasn't catch error",exceptForDecimal5Raised);
-        assertTrue("Enum wasn't checked", enumChecked);
-        assertTrue("Bits wasn't checked", bitsChecked);
-        assertTrue("Decimal1 wasn't checked", lfdecimal1Checked);
-        assertTrue("Decimal2 wasn't checked", lfdecimal2Checked);
-        assertTrue("Decimal3 wasn't checked", lfdecimal3Checked);
-        assertTrue("Decimal4 wasn't checked", lfdecimal4Checked);
-        assertTrue("Decimal5 wasn't checked", lfdecimal6Checked);
-        assertTrue("lfbool1 wasn't checked", lfbool1Checked);
-        assertTrue("lfbool2 wasn't checked", lfbool2Checked);
-        assertTrue("lfstr wasn't checked", lfstrChecked);
-        assertTrue("lfstr1 wasn't checked", lfstr1Checked);
-        assertTrue("lfbinary wasn't checked", lfbinaryChecked);
-        assertTrue("lfempty wasn't checked", lfemptyChecked);
-        // assertTrue("lfref1 wasn't checked", lfref1Checked);
-
-        jReader.endObject();
-
-    }
-
-    private void checkLfUnion(JsonReader jReader, String keyName, JsonToken peek) throws IOException {
-        if (keyName.equals("lfunion1")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion2")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion3")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-            jReader.nextInt();
-        } else if (keyName.equals("lfunion4")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
-            jReader.nextBoolean();
-        } else if (keyName.equals("lfunion5")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion6")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion7")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion8")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion9")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion10")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion11")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
-            jReader.nextString();
-        } else if (keyName.equals("lfunion12")) {
-            assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
-            jReader.nextBoolean();
-        }
-    }
-}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonChoiceCaseTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonChoiceCaseTest.java
deleted file mode 100644 (file)
index c5682cb..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
-
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-
-import javax.ws.rs.WebApplicationException;
-
-import org.junit.*;
-
-public class ToJsonChoiceCaseTest extends YangAndXmlAndDataSchemaLoader {
-
-    @BeforeClass
-    public static void initialization() {
-        dataLoad("/yang-to-json-conversion/choice");
-    }
-
-    /**
-     * Test when some data are in one case node and other in another. This isn't
-     * correct. Next Json validator should return error because nodes has to be
-     * from one case below concrete choice.
-     * 
-     */
-    @Test
-    public void nodeSchemasOnVariousChoiceCasePathTest() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_various_path_err.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test when some data are in one case node and other in another.
-     * Additionally data are loadef from various choices. This isn't correct.
-     * Next Json validator should return error because nodes has to be from one
-     * case below concrete choice.
-     * 
-     */
-    @Test
-    public void nodeSchemasOnVariousChoiceCasePathAndMultipleChoicesTest() {
-        try {
-            TestUtils
-                    .writeCompNodeWithSchemaContextToJson(
-                            TestUtils
-                                    .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_more_choices_same_level_various_paths_err.xml"),
-                            "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test when second level data are red first, then first and at the end
-     * third level. Level represents pass through couple choice-case
-     */
-
-    @Test
-    public void nodeSchemasWithRandomOrderAccordingLevel() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_random_level.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test when element from no first case is used
-     */
-    @Test
-    public void nodeSchemasNotInFirstCase() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_no_first_case.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test when element in case is list
-     */
-    @Test
-    public void nodeSchemaAsList() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_list.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test when element in case is container
-     */
-    @Test
-    public void nodeSchemaAsContainer() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_container.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test when element in case is leaflist
-     */
-    @Test
-    public void nodeSchemaAsLeafList() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(
-                    TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_leaflist.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * 
-     */
-    @Test
-    public void nodeSchemasInMultipleChoicesTest() {
-        try {
-            TestUtils
-                    .writeCompNodeWithSchemaContextToJson(TestUtils
-                            .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_more_choices_same_level.xml"),
-                            "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test whether is possible to find data schema for node which is specified
-     * as dirrect subnode of choice (case without CASE key word)
-     */
-    @Test
-    public void nodeSchemasInCaseNotDefinedWithCaseKeyword() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
-                    .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_case_defined_without_case.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-
-    /**
-     * Test of multiple use of choices
-     */
-    @Test
-    public void nodeSchemasInThreeChoicesAtSameLevel() {
-        try {
-            TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
-                    .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_three_choices_same_level.xml"),
-                    "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
-        } catch (WebApplicationException | IOException e) {
-            // shouldn't end here
-            assertTrue(false);
-        }
-    }
-}
index ec7dba67b9a35392845e93588862411f45362b49..4cea120d4d1896f498394e176184d1b63e3b262c 100644 (file)
@@ -11,8 +11,7 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLEncoder;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.Future;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
@@ -33,12 +32,10 @@ import org.opendaylight.controller.sal.rest.api.Draft01;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 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.RestconfImpl;
+import org.opendaylight.controller.sal.restconf.impl.*;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -77,14 +74,31 @@ public class XmlProvidersTest extends JerseyTest {
     public void testStructuredDataToXmlProvider() throws FileNotFoundException, UnsupportedEncodingException {
         String uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
 
-        InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
-        CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream);
+        CompositeNode loadedCompositeNode = prepareCompositeNodeWithIetfInterfacesInterfacesData();
         when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
 
         Response response = target(uri).request(MEDIA_TYPE).get();
         assertEquals(200, response.getStatus());
     }
 
+    private 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) {
+        }
+
+        return null;
+    }
+
     @Test
     public void testBadFormatXmlToCompositeNodeProvider() throws UnsupportedEncodingException, URISyntaxException {
         String uri = createUri("/operations/", "ietf-interfaces:interfaces/interface/eth0");
index a1e06c3cabfa1d1cbeb207c676da1583cb4643d2..afd40d1c2ba6aee49ed4124380e1cddd14b98585 100644 (file)
@@ -1,21 +1,20 @@
 package org.opendaylight.controller.sal.restconf.impl.test.structures;
 
 public class Lf extends YangElement {
-    private String value;
+    private Object value;
     private int numOfEqualItems = 0;
 
-
-    public Lf(String name, String value) {
+    public Lf(String name, Object value) {
         super(name);
         this.value = value;
     }
 
-    public Lf(String value) {
+    public Lf(Object value) {
         super("");
         this.value = value;
     }
 
-    public String getValue() {
+    public Object getValue() {
         return value;
     }
 
@@ -43,11 +42,10 @@ public class Lf extends YangElement {
         }
         return true;
     }
-    
+
     public void incNumOfEqualItems() {
         this.numOfEqualItems++;
     }
-    
 
     @Override
     public int hashCode() {
index 87fed95f6ff15b4a2a3800a0adaa25c1aaf62ba0..dda590944ace0f6bd5cf6c1462a1e352af016358 100644 (file)
@@ -1,6 +1,7 @@
 package org.opendaylight.controller.sal.restconf.impl.test.structures;
 
-import java.util.*;
+import java.util.HashSet;
+import java.util.Set;
 
 public class LfLst extends YangElement {
     Set<Lf> lfs;
@@ -10,11 +11,10 @@ public class LfLst extends YangElement {
         lfs = new HashSet<>();
     }
 
-    public LfLst addLf(String value) {
+    public LfLst addLf(Object value) {
         return addLf(new Lf(value));
     }
 
-    
     public LfLst addLf(Lf lf) {
         while (this.lfs.contains(lf)) {
             lf.incNumOfEqualItems();
index 9eb58b5344186690484658ffa489fc376df811cd..10582de08374e4302765437da257c44af7b7ce01 100644 (file)
@@ -1,6 +1,7 @@
 package org.opendaylight.controller.sal.restconf.impl.test.structures;
 
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
 
 public class LstItem {
     String lstName;
@@ -42,7 +43,7 @@ public class LstItem {
         return this;
     }
 
-    public LstItem addLf(String name, String value) {
+    public LstItem addLf(String name, Object value) {
         lfs.put(name, new Lf(name, value));
         return this;
     }
@@ -1,23 +1,27 @@
-package org.opendaylight.controller.sal.restconf.impl.test;
+package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import java.io.*;
 import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Set;
 
 import javax.ws.rs.WebApplicationException;
 
-import org.junit.*;
+import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.*;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.*;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.slf4j.*;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-public class FromXmlToCompositeNodeTest {
-    private static final Logger LOG = LoggerFactory.getLogger(FromXmlToCompositeNodeTest.class);
+public class XmlToCnSnTest {
+    private static final Logger LOG = LoggerFactory.getLogger(XmlToCnSnTest.class);
 
     /**
      * top level element represents container. second level element is list with
@@ -25,11 +29,11 @@ public class FromXmlToCompositeNodeTest {
      */
     @Test
     public void testXmlDataContainer() {
-        CompositeNode compNode = compositeContainerFromXml("/xml-to-composite-node/data-container.xml", false);
+        CompositeNode compNode = compositeNodeFromXml("/xml-to-cnsn/data-container.xml", false);
         assertNotNull(compNode);
         DataSchemaNode dataSchemaNode = null;
         try {
-            dataSchemaNode = TestUtils.obtainSchemaFromYang("/xml-to-composite-node/data-container-yang");
+            dataSchemaNode = TestUtils.obtainSchemaFromYang("/xml-to-cnsn/data-container-yang");
         } catch (FileNotFoundException e) {
             LOG.error(e.getMessage());
             assertTrue(false);
@@ -73,13 +77,12 @@ public class FromXmlToCompositeNodeTest {
 
     @Test
     public void testXmlDataList() {
-        CompositeNode compNode = compositeContainerFromXml("/xml-to-composite-node/data-list.xml", false);
+        CompositeNode compNode = compositeNodeFromXml("/xml-to-cnsn/data-list.xml", false);
         assertNotNull(compNode);
 
         DataSchemaNode dataSchemaNode = null;
         try {
-            dataSchemaNode = TestUtils.obtainSchemaFromYang("/xml-to-composite-node/data-list-yang",
-                    "data-container-yang");
+            dataSchemaNode = TestUtils.obtainSchemaFromYang("/xml-to-cnsn/data-list-yang", "data-container-yang");
         } catch (FileNotFoundException e) {
             LOG.error(e.getMessage());
         }
@@ -145,7 +148,7 @@ public class FromXmlToCompositeNodeTest {
 
     @Test
     public void testXmlEmptyData() {
-        CompositeNode compNode = compositeContainerFromXml("/xml-to-composite-node/empty-data.xml", true);
+        CompositeNode compNode = compositeNodeFromXml("/xml-to-cnsn/empty-data.xml", true);
         assertEquals("cont", compNode.getNodeType().getLocalName());
         SimpleNode<?> lf1 = null;
         SimpleNode<?> lflst1_1 = null;
@@ -189,6 +192,72 @@ public class FromXmlToCompositeNodeTest {
 
     }
 
+    /**
+     * Test case like this <lf11 xmlns:x="namespace">x:identity</lf11>
+     */
+    @Test
+    public void testIdentityrefNmspcInElement() {
+        testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-nmspc-in-element.xml", "/xml-to-cnsn/identityref",
+                "identityref-module", "cont", 2, "iden", "identity:module");
+    }
+
+    /**
+     * 
+     * Test case like <lf11 xmlns="namespace1"
+     * xmlns:x="namespace">identity</lf11>
+     */
+
+    @Test
+    public void testIdentityrefDefaultNmspcInElement() {
+        testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-default-nmspc-in-element.xml",
+                "/xml-to-cnsn/identityref/yang-augments", "general-module", "cont", 3, "iden", "identityref:module");
+    }
+
+    /**
+     * 
+     * Test case like <cont1 xmlns="namespace1"> <lf11
+     * xmlns:x="namespace">identity</lf11> </cont1>
+     */
+    @Test
+    public void testIdentityrefDefaultNmspcInParrentElement() {
+        testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-default-nmspc-in-parrent-element.xml",
+                "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "identityref:module");
+    }
+
+    /**
+     * 
+     * Test case like <cont1 xmlns="namespace1" xmlns:x="namespace">
+     * <lf11>x:identity</lf11> </cont1>
+     */
+    @Test
+    public void testIdentityrefNmspcInParrentElement() {
+        testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-nmspc-in-parrent-element.xml",
+                "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "z:namespace");
+
+    }
+
+    /**
+     * 
+     * Test case like (without namespace in xml) <cont1> <lf11>x:identity</lf11>
+     * </cont1>
+     */
+    @Test
+    public void testIdentityrefNoNmspcValueWithPrefix() {
+        testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-no-nmspc-value-with-prefix.xml",
+                "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "x:iden", "identityref:module");
+    }
+
+    /**
+     * 
+     * Test case like (without namespace in xml) <cont1> <lf11>identity</lf11>
+     * </cont1>
+     */
+    @Test
+    public void testIdentityrefNoNmspcValueWithoutPrefix() {
+        testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-no-nmspc-value-without-prefix.xml",
+                "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "identityref:module");
+    }
+
     private void verifyCommonPartAOfXml(CompositeNode compNode, String suf, String nameSpace) {
         SimpleNode<?> lf1suf = null;
         SimpleNode<?> lflst1suf_1 = null;
@@ -254,10 +323,10 @@ public class FromXmlToCompositeNodeTest {
         assertEquals((short) 100, cont1_lf11.getValue());
     }
 
-    private CompositeNode compositeContainerFromXml(String xmlPath, boolean dummyNamespaces) {
+    private CompositeNode compositeNodeFromXml(String xmlPath, boolean dummyNamespaces) {
         XmlToCompositeNodeProvider xmlToCompositeNodeProvider = XmlToCompositeNodeProvider.INSTANCE;
         try {
-            InputStream xmlStream = FromXmlToCompositeNodeTest.class.getResourceAsStream(xmlPath);
+            InputStream xmlStream = XmlToCnSnTest.class.getResourceAsStream(xmlPath);
             CompositeNode compositeNode = xmlToCompositeNodeProvider.readFrom(null, null, null, null, null, xmlStream);
             if (dummyNamespaces) {
                 try {
@@ -277,4 +346,47 @@ public class FromXmlToCompositeNodeTest {
         return null;
     }
 
+    private void testIdentityrefToCnSn(String xmlPath, String yangPath, String moduleName, String schemaName,
+            int moduleCount, String resultLocalName, String resultNamespace) {
+        CompositeNode compositeNode = compositeNodeFromXml(xmlPath, false);
+        assertNotNull(compositeNode);
+
+        Set<Module> modules = TestUtils.resolveModules(yangPath);
+        assertEquals(moduleCount, modules.size());
+        Module module = TestUtils.resolveModule(moduleName, modules);
+        assertNotNull(module);
+        DataSchemaNode dataSchemaNode = TestUtils.resolveDataSchemaNode(module, null);
+        assertNotNull(dataSchemaNode);
+
+        TestUtils.normalizeCompositeNode(compositeNode, modules, dataSchemaNode, moduleName + ":" + schemaName);
+
+        SimpleNode<?> lf11 = getLf11(compositeNode);
+        assertTrue(lf11.getValue() instanceof QName);
+        QName qName = (QName) lf11.getValue();
+        assertEquals(resultLocalName, qName.getLocalName());
+        assertEquals(resultNamespace, qName.getNamespace().toString());
+
+    }
+
+    private SimpleNode<?> getLf11(CompositeNode compositeNode) {
+        assertEquals("cont", compositeNode.getNodeType().getLocalName());
+
+        List<Node<?>> childs = compositeNode.getChildren();
+        assertEquals(1, childs.size());
+        Node<?> nd = childs.iterator().next();
+        assertTrue(nd instanceof CompositeNode);
+        assertEquals("cont1", nd.getNodeType().getLocalName());
+
+        childs = ((CompositeNode) nd).getChildren();
+        SimpleNode<?> lf11 = null;
+        for (Node<?> child : childs) {
+            assertTrue(child instanceof SimpleNode);
+            if (child.getNodeType().getLocalName().equals("lf11")) {
+                lf11 = (SimpleNode<?>) child;
+            }
+        }
+        assertNotNull(lf11);
+        return lf11;
+    }
+
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/identityref/identityref-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/identityref/identityref-module.yang
new file mode 100644 (file)
index 0000000..20f91b2
--- /dev/null
@@ -0,0 +1,21 @@
+module identityref-module {
+  namespace "identityref:module";  
+
+  prefix "iderefmod";
+  
+  import identity-module {prefix idemo; revision-date 2013-12-2;}
+   
+  revision 2013-12-2 {    
+  }
+  
+       container cont {
+          container cont1 {
+               leaf lf1 {
+                       type identityref {
+                               base "idemo:iden";
+                       }
+               }
+               }
+       }
+         
+}
\ No newline at end of file
@@ -5,6 +5,9 @@ module simple-data-types {
   revision 2013-11-12 {    
   }
   
+  identity iden {
+  }
+  
   typedef tpdfempty {
        type empty;
   }
@@ -245,6 +248,26 @@ module simple-data-types {
     leaf lfunion12 {
                type tpdfun2;
     }
+    
+    leaf lfunion13 {
+        type tpdfbit;    
+    }
+        
+    leaf lfunion14 {
+        type union {
+            type enumeration {
+                enum zero;
+                enum one;
+            }
+            type uint16;
+        }    
+    }    
+    
+    leaf identityref1 {
+        type identityref {
+            base iden;
+        }
+    }
          
          
   }
similarity index 80%
rename from opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-data-types/xml/data.xml
rename to opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/xml/data.xml
index 0d31e9037a763b3732274da5eddc2512a8c8ecb4..56872a337d0124be4789789ef8f58427ab378278 100644 (file)
@@ -21,9 +21,9 @@
        <lfdecimal4>43E3</lfdecimal4>
        <lfdecimal6>33.12345</lfdecimal6>
        <lfenum>enum3</lfenum>
-       <lfbits>bit3</lfbits>   
-       <lfbinary>AAaacdabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%%-#^</lfbinary>
-       <lfempty></lfempty>
+       <lfbits>bit3 bit2</lfbits>      
+       <lfbinary>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</lfbinary>
+       <lfempty />
        <lfunion1>324</lfunion1>
        <lfunion2>33.3</lfunion2>
        <lfunion3>55</lfunion3>
@@ -36,4 +36,8 @@
        <lfunion10>bt1</lfunion10>
        <lfunion11>33</lfunion11>
        <lfunion12>false</lfunion12>
+       <lfunion13>44</lfunion13>
+       <lfunion14>21</lfunion14>
+       <lfempty />
+       <identityref1 xmlns:x="simple:data:types">x:iden</identityref1>
 </cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/aug-referenced-elements-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/aug-referenced-elements-module.yang
new file mode 100644 (file)
index 0000000..1b861f5
--- /dev/null
@@ -0,0 +1,18 @@
+module aug-referenced-elements-module {
+  namespace "aug:referenced:elements:module";  
+
+  prefix "augrefelmo";
+  
+  import referenced-elements-module {prefix refelmo; revision-date 2013-12-3;}
+   
+  revision 2013-12-3 {    
+  }
+  
+  augment "/refelmo:cont" {
+    leaf lf2 {
+        type boolean;
+    }
+  }
+  
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/eferenced-elements-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/eferenced-elements-module.yang
new file mode 100644 (file)
index 0000000..fd6e0fb
--- /dev/null
@@ -0,0 +1,20 @@
+module referenced-elements-module {
+  namespace "referenced:elements:module";  
+
+  prefix "refelmo";
+   
+  revision 2013-12-3 {    
+  }
+  
+       container cont {
+               leaf lf1 {
+                       type string;                            
+                       }
+               }
+               leaf-list lflst1 {
+                       type uint32;
+               }
+               
+       }
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/rinstance-identifier-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/instance_identifier/rinstance-identifier-module.yang
new file mode 100644 (file)
index 0000000..61ce822
--- /dev/null
@@ -0,0 +1,16 @@
+module instance-identifier-module {
+  namespace "instance:identifier:module";  
+
+  prefix "inidmod";
+   
+  revision 2013-12-3 {    
+  }
+  
+       container cont {
+               leaf lf1 {
+                       type instance-identifier {                              
+                       }
+               }
+       }
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/yang/basic-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/yang/basic-module.yang
new file mode 100644 (file)
index 0000000..7023c94
--- /dev/null
@@ -0,0 +1,96 @@
+module basic-module {
+  namespace "basic:module";  
+
+  prefix "basmod";
+  
+  import referenced-module {prefix refmo; revision-date 2013-12-2;}
+   
+  revision 2013-12-2 {    
+  }
+  
+       container cont {
+          container cont1 {
+               leaf lf11 {
+                       type identityref {
+                               base "refmo:iden";
+                       }
+               }
+               }
+               leaf lfStr {
+                 type string;
+               }
+               leaf lfInt8 {
+                 type int8;
+               }
+               
+               leaf lfInt16 {
+                 type int16;
+               }
+               
+               leaf lfInt32 {
+                 type int32;
+               }
+               
+               leaf lfInt64 {
+                 type int64;
+               }
+               
+               leaf lfUint8 {
+                 type uint8;
+               }
+               
+               leaf lfUint16 {
+                 type uint16;
+               }
+               
+               leaf lfUint32 {
+                 type uint32;
+               }
+               
+               leaf lfUint64 {
+                 type uint64;
+               }
+               
+               leaf lfBinary {
+                 type binary;
+               }
+               
+               leaf lfBits {
+                 type bits {
+                     bit one;
+                     bit two;
+                     bit three;
+                 }
+               }
+               
+               leaf lfEnumeration {
+                 type enumeration {
+                     enum enum1;
+                     enum enum2;
+                     enum enum3;
+                 }
+               }
+               
+               leaf lfEmpty {
+                 type empty;
+               }
+               
+               leaf lfBoolean {
+                 type boolean;
+               }
+               
+               leaf lfUnion {
+                 type union {
+                     type int8;
+                     type string;
+                     type bits {
+                         bit first;
+                         bit second;
+                     }
+                     type boolean;
+                 }
+               }
+               
+       }
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/yang/referenced-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-xml/yang/referenced-module.yang
new file mode 100644 (file)
index 0000000..9821b1e
--- /dev/null
@@ -0,0 +1,10 @@
+module referenced-module {
+  namespace "referenced:module";  
+
+  prefix "refmod";
+  revision 2013-12-2 {    
+  }
+  
+       identity iden {         
+       }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/identity-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/identity-module.yang
new file mode 100644 (file)
index 0000000..30890bf
--- /dev/null
@@ -0,0 +1,10 @@
+module identity-module {
+  namespace "identity:module";  
+
+  prefix "idemod";
+  revision 2013-12-2 {    
+  }
+  
+       identity iden {         
+       }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/identityref-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/identityref-module.yang
new file mode 100644 (file)
index 0000000..b90b533
--- /dev/null
@@ -0,0 +1,39 @@
+module identityref-module {
+  namespace "identityref:module";  
+
+  prefix "iderefmod";
+  
+  import identity-module {prefix idemo; revision-date 2013-12-2;}
+   
+  revision 2013-12-2 {    
+  }
+  
+  identity iden_local {
+  }
+  
+       container cont {
+          container cont1 {
+               leaf lf11 {
+                       type identityref {
+                               base "idemo:iden";
+                       }
+               }
+               leaf lf12 {
+                       type identityref {
+                               base "iden_local";
+                       }
+               }
+               leaf lf13 {
+                       type identityref {
+                               base "iden_local";
+                       }
+               }
+               leaf lf14 {
+                       type identityref {
+                               base "iden_local";
+                       }
+               }
+               }
+       }
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/json/data.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/json-to-cnsn/identityref/json/data.json
new file mode 100644 (file)
index 0000000..320ee05
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "cont":{
+        "cont1":{
+            "lf11":"identity-module:iden",
+            "lf12":"iden_local",              
+            "identityref-module:lf13":"iden_local",
+            "identityref-module:lf14":"identity-module:iden_local"  
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-nmspc-in-attributes.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/data-nmspc-in-attributes.xml
new file mode 100644 (file)
index 0000000..848c020
--- /dev/null
@@ -0,0 +1,5 @@
+<cont xmlns:x="x:namespace" xmlns:y="y:namespace">
+    <cont1 xmlns:z="z:namespace" xmlns:a="a:namespace" xmlns:b="b:namespace">
+        <lf11 xmlns:c="identity:module">c:iden</lf11>
+    </cont1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/identity-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/identity-module.yang
new file mode 100644 (file)
index 0000000..30890bf
--- /dev/null
@@ -0,0 +1,10 @@
+module identity-module {
+  namespace "identity:module";  
+
+  prefix "idemod";
+  revision 2013-12-2 {    
+  }
+  
+       identity iden {         
+       }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/identityref-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/identityref-module.yang
new file mode 100644 (file)
index 0000000..a43d439
--- /dev/null
@@ -0,0 +1,21 @@
+module identityref-module {
+  namespace "identityref:module";  
+
+  prefix "iderefmod";
+  
+  import identity-module {prefix idemo; revision-date 2013-12-2;}
+   
+  revision 2013-12-2 {    
+  }
+  
+       container cont {
+          container cont1 {
+               leaf lf11 {
+                       type identityref {
+                               base "idemo:iden";
+                       }
+               }
+               }
+       }
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-default-nmspc-in-element.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-default-nmspc-in-element.xml
new file mode 100644 (file)
index 0000000..aae2af3
--- /dev/null
@@ -0,0 +1,5 @@
+<cont xmlns="general:module" xmlns:x="x:namespace" xmlns:y="y:namespace">
+    <cont1 xmlns:z="z:namespace" xmlns:a="a:namespace" xmlns:b="b:namespace">        
+        <lf11 xmlns="identityref:module" xmlns:c="c:namespace">iden</lf11>  
+    </cont1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-default-nmspc-in-parrent-element.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-default-nmspc-in-parrent-element.xml
new file mode 100644 (file)
index 0000000..621d2bc
--- /dev/null
@@ -0,0 +1,5 @@
+<cont xmlns:x="x:namespace" xmlns:y="y:namespace">
+    <cont1 xmlns="identityref:module" xmlns:z="z:namespace" xmlns:a="a:namespace" xmlns:b="b:namespace">        
+        <lf11 xmlns:c="c:namespace">iden</lf11>  
+    </cont1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-nmspc-in-element.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-nmspc-in-element.xml
new file mode 100644 (file)
index 0000000..76de72d
--- /dev/null
@@ -0,0 +1,5 @@
+<cont xmlns="identityref:module" xmlns:x="x:namespace" xmlns:y="y:namespace">
+    <cont1 xmlns:z="z:namespace" xmlns:a="a:namespace" xmlns:b="b:namespace">
+        <lf11 xmlns:c="identity:module">c:iden</lf11>
+    </cont1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-nmspc-in-parrent-element.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-nmspc-in-parrent-element.xml
new file mode 100644 (file)
index 0000000..497c35f
--- /dev/null
@@ -0,0 +1,5 @@
+<cont xmlns="identityref:module" xmlns:x="x:namespace" xmlns:y="y:namespace">
+    <cont1 xmlns:c="identity:module" xmlns:z="z:namespace" xmlns:a="a:namespace" xmlns:b="b:namespace">        
+        <lf11>z:iden</lf11>  
+    </cont1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-no-nmspc-value-with-prefix.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-no-nmspc-value-with-prefix.xml
new file mode 100644 (file)
index 0000000..925442f
--- /dev/null
@@ -0,0 +1,5 @@
+<cont>
+    <cont1>   
+        <lf11>x:iden</lf11>  
+    </cont1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-no-nmspc-value-without-prefix.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/xml/data-no-nmspc-value-without-prefix.xml
new file mode 100644 (file)
index 0000000..5a86eb0
--- /dev/null
@@ -0,0 +1,5 @@
+<cont>
+    <cont1>
+        <lf11>iden</lf11>  
+    </cont1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/yang-augments/general-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/yang-augments/general-module.yang
new file mode 100644 (file)
index 0000000..f1a1ea6
--- /dev/null
@@ -0,0 +1,14 @@
+module general-module {
+  namespace "general:module";  
+
+  prefix "genmod";
+  revision 2013-12-12 {    
+  }
+
+    container cont {
+       container cont1 {
+        }
+    }
+
+  
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/yang-augments/identity-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-cnsn/identityref/yang-augments/identity-module.yang
new file mode 100644 (file)
index 0000000..30890bf
--- /dev/null
@@ -0,0 +1,10 @@
+module identity-module {
+  namespace "identity:module";  
+
+  prefix "idemod";
+  revision 2013-12-2 {    
+  }
+  
+       identity iden {         
+       }
+}
\ No newline at end of file
@@ -4,12 +4,13 @@ module identityref-module {
   prefix "iderefmod";
   
   import identity-module {prefix idemo; revision-date 2013-12-2;}
+  import general-module {prefix gmo; revision-date 2013-12-12;}
    
   revision 2013-12-2 {    
   }
   
-       container cont {
-               leaf lf1 {
+       augment "/gmo:cont/gmo:cont1" {
+               leaf lf11 {
                        type identityref {
                                base "idemo:iden";
                        }
index 11cce72ef1516655e26d7a5b28daaa37d880d5f9..998d5d8faaf24fd09e10d6a5865f1a5c169e6d96 100644 (file)
@@ -21,6 +21,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.
  */
 public class MultipartMessageManager {
 
+    /*
+     *  Map for tx id and type of request, to keep track of all the request sent 
+     *  by Statistics Manager. Statistics Manager won't entertain any multipart 
+     *  response for which it didn't send the request.  
+     */
+    
+    private static Map<TransactionId,StatsRequestType> txIdToRequestTypeMap = new ConcurrentHashMap<TransactionId,StatsRequestType>();
+    /*
+     * Map to keep track of the request tx id for flow table statistics request.
+     * Because flow table statistics multi part response do not contains the table id.
+     */
     private static Map<TransactionId,Short> txIdTotableIdMap = new ConcurrentHashMap<TransactionId,Short>();
     
     public MultipartMessageManager(){}
@@ -34,4 +45,23 @@ public class MultipartMessageManager {
     public void setTxIdAndTableIdMapEntry(TransactionId id,Short tableId){
         txIdTotableIdMap.put(id, tableId);
     }
+    
+    public void addTxIdToRequestTypeEntry (TransactionId id,StatsRequestType type){
+        txIdToRequestTypeMap.put(id, type);
+    }
+    public StatsRequestType removeTxId(TransactionId id){
+        return txIdToRequestTypeMap.remove(id);
+    }
+    
+    public enum StatsRequestType{
+        ALL_FLOW,
+        AGGR_FLOW,
+        ALL_PORT,
+        ALL_FLOW_TABLE,
+        ALL_QUEUE_STATS,
+        ALL_GROUP,
+        ALL_METER,
+        GROUP_DESC,
+        METER_CONFIG
+    }
 }
index a659a4088695ce392471dba4c1c81cabc72d8d81..e84b437b533f8c1deba3d3d67634ee70f5096c15 100644 (file)
@@ -14,6 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
@@ -22,6 +23,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericQueueStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericTableStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics;
@@ -54,6 +56,9 @@ public class NodeStatistics {
     private final Map<Short,GenericTableStatistics> flowTableAndStatisticsMap = 
             new HashMap<Short,GenericTableStatistics>();
     
+    private final Map<NodeConnectorId,Map<QueueId,GenericQueueStatistics>> NodeConnectorAndQueuesStatsMap = 
+            new HashMap<NodeConnectorId,Map<QueueId,GenericQueueStatistics>>();
+    
     public NodeStatistics(){
         
     }
@@ -128,4 +133,8 @@ public class NodeStatistics {
     public Map<NodeConnectorId, NodeConnectorStatistics> getNodeConnectorStats() {
         return nodeConnectorStats;
     }
+
+    public Map<NodeConnectorId, Map<QueueId, GenericQueueStatistics>> getNodeConnectorAndQueuesStatsMap() {
+        return NodeConnectorAndQueuesStatsMap;
+    }
 }
index 521de7e394ee69fd3d5dfdda4bf8f546a1b513c0..738c2cb9a8f6375d8681a5e824b0d2f953d1a211 100644 (file)
@@ -5,12 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-/*
- * TODO: Handle multipart messages with following flag true 
- * OFPMPF_REPLY_MORE = 1 << 0
- * Better accumulate all the messages and update local cache 
- * and configurational data store
- */
+
 package org.opendaylight.controller.md.statistics.manager;
 
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
index b7b408211851d0ce09f8fa6fb825ca04a340e755..19cf0ed386bda52aed1ab8b572dd1c5cea821d53 100644 (file)
@@ -15,6 +15,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.md.statistics.manager.MultipartMessageManager.StatsRequestType;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
@@ -43,9 +44,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllPortsStatisticsInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllPortsStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.GetAllQueuesStatisticsFromAllPortsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
@@ -71,6 +75,8 @@ public class StatisticsProvider implements AutoCloseable {
 
     private OpendaylightFlowTableStatisticsService flowTableStatsService;
 
+    private OpendaylightQueueStatisticsService queueStatsService;
+
     private final MultipartMessageManager multipartMessageManager = new MultipartMessageManager();
     
     private Thread statisticsRequesterThread;
@@ -129,6 +135,9 @@ public class StatisticsProvider implements AutoCloseable {
         flowTableStatsService = StatisticsManagerActivator.getProviderContext().
                 getRpcService(OpendaylightFlowTableStatisticsService.class);
         
+        queueStatsService = StatisticsManagerActivator.getProviderContext().
+                getRpcService(OpendaylightQueueStatisticsService.class);
+        
         statisticsRequesterThread = new Thread( new Runnable(){
 
             @Override
@@ -177,9 +186,11 @@ public class StatisticsProvider implements AutoCloseable {
 
                 sendAllFlowsStatsFromAllTablesRequest(targetNodeRef);
 
-                sendAllPortStatisticsRequest(targetNodeRef);
+                sendAllNodeConnectorsStatisticsRequest(targetNodeRef);
                 
                 sendAllFlowTablesStatisticsRequest(targetNodeRef);
+                
+                sendAllQueueStatsFromAllNodeConnector (targetNodeRef);
 
             }catch(Exception e){
                 spLogger.error("Exception occured while sending statistics requests : {}",e);
@@ -191,13 +202,9 @@ public class StatisticsProvider implements AutoCloseable {
 
                 try{
                   sendAllGroupStatisticsRequest(targetNodeRef);
-                  Thread.sleep(1000);
                   sendAllMeterStatisticsRequest(targetNodeRef);
-                  Thread.sleep(1000);
                   sendGroupDescriptionRequest(targetNodeRef);
-                  Thread.sleep(1000);
                   sendMeterConfigStatisticsRequest(targetNodeRef);
-                  Thread.sleep(1000);
                 }catch(Exception e){
                     spLogger.error("Exception occured while sending statistics requests : {}", e);
                 }
@@ -205,27 +212,32 @@ public class StatisticsProvider implements AutoCloseable {
         }
     }
 
-    private void sendAllFlowTablesStatisticsRequest(NodeRef targetNodeRef) {
+    private void sendAllFlowTablesStatisticsRequest(NodeRef targetNodeRef) throws InterruptedException, ExecutionException {
         final GetFlowTablesStatisticsInputBuilder input = 
                 new GetFlowTablesStatisticsInputBuilder();
         
         input.setNode(targetNodeRef);
 
-        @SuppressWarnings("unused")
         Future<RpcResult<GetFlowTablesStatisticsOutput>> response = 
                 flowTableStatsService.getFlowTablesStatistics(input.build());
+
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.ALL_FLOW_TABLE);
+
     }
 
-    private void sendAllFlowsStatsFromAllTablesRequest(NodeRef targetNode){
+    private void sendAllFlowsStatsFromAllTablesRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
         final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input =
                 new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder();
         
         input.setNode(targetNode);
         
-        @SuppressWarnings("unused")
         Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> response = 
                 flowStatsService.getAllFlowsStatisticsFromAllFlowTables(input.build());
         
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.ALL_FLOW);
+        
     }
     
     private void sendAggregateFlowsStatsFromAllTablesRequest(NodeKey targetNodeKey) throws InterruptedException, ExecutionException{
@@ -245,6 +257,8 @@ public class StatisticsProvider implements AutoCloseable {
                         flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build());
                 
                 multipartMessageManager.setTxIdAndTableIdMapEntry(response.get().getResult().getTransactionId(), id);
+                this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                        , StatsRequestType.AGGR_FLOW);
             }
         }
         
@@ -261,63 +275,90 @@ public class StatisticsProvider implements AutoCloseable {
 //                        flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build());`
 //                
 //                multipartMessageManager.setTxIdAndTableIdMapEntry(response.get().getResult().getTransactionId(), (short)1);
+        
     }
 
-    private void sendAllPortStatisticsRequest(NodeRef targetNode){
+    private void sendAllNodeConnectorsStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
         
-        final GetAllPortsStatisticsInputBuilder input = new GetAllPortsStatisticsInputBuilder();
+        final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder();
         
         input.setNode(targetNode);
 
-        @SuppressWarnings("unused")
-        Future<RpcResult<GetAllPortsStatisticsOutput>> response = 
-                portStatsService.getAllPortsStatistics(input.build());
+        Future<RpcResult<GetAllNodeConnectorsStatisticsOutput>> response = 
+                portStatsService.getAllNodeConnectorsStatistics(input.build());
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.ALL_PORT);
+
     }
 
-    private void sendAllGroupStatisticsRequest(NodeRef targetNode){
+    private void sendAllGroupStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
         
         final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
         
         input.setNode(targetNode);
 
-        @SuppressWarnings("unused")
         Future<RpcResult<GetAllGroupStatisticsOutput>> response = 
                 groupStatsService.getAllGroupStatistics(input.build());
+        
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.ALL_GROUP);
+
     }
     
-    private void sendGroupDescriptionRequest(NodeRef targetNode){
+    private void sendGroupDescriptionRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
         final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
         
         input.setNode(targetNode);
 
-        @SuppressWarnings("unused")
         Future<RpcResult<GetGroupDescriptionOutput>> response = 
                 groupStatsService.getGroupDescription(input.build());
+
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.GROUP_DESC);
+
     }
     
-    private void sendAllMeterStatisticsRequest(NodeRef targetNode){
+    private void sendAllMeterStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
         
         GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
         
         input.setNode(targetNode);
 
-        @SuppressWarnings("unused")
         Future<RpcResult<GetAllMeterStatisticsOutput>> response = 
                 meterStatsService.getAllMeterStatistics(input.build());
+        
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.ALL_METER);;
+
     }
     
-    private void sendMeterConfigStatisticsRequest(NodeRef targetNode){
+    private void sendMeterConfigStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
         
         GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
         
         input.setNode(targetNode);
 
-        @SuppressWarnings("unused")
         Future<RpcResult<GetAllMeterConfigStatisticsOutput>> response = 
                 meterStatsService.getAllMeterConfigStatistics(input.build());
         
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.METER_CONFIG);;
+
     }
     
+    private void sendAllQueueStatsFromAllNodeConnector(NodeRef targetNode) throws InterruptedException, ExecutionException {
+        GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder();
+        
+        input.setNode(targetNode);
+        
+        Future<RpcResult<GetAllQueuesStatisticsFromAllPortsOutput>> response = 
+                queueStatsService.getAllQueuesStatisticsFromAllPorts(input.build());
+        
+        this.multipartMessageManager.addTxIdToRequestTypeEntry(response.get().getResult().getTransactionId()
+                , StatsRequestType.ALL_QUEUE_STATS);;
+
+    }
+
     public ConcurrentMap<NodeId, NodeStatistics> getStatisticsCache() {
         return statisticsCache;
     }
index a4a7e1e6613f6ee0425bec4fded4798681e0dd35..5c21fd6e1042f6ad8a3134a950a1eb43e6581ad8 100644 (file)
@@ -13,7 +13,11 @@ import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
@@ -25,10 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.A
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowTableStatisticsUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.NodeConnectorStatisticsUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
@@ -40,6 +41,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev13
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.QueueKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
@@ -53,6 +58,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.desc.GroupDescBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
 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;
@@ -72,26 +82,44 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterConfigStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterConfigStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericQueueStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.PortStatisticsUpdate;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Class implement statistics manager related listener interface and augment all the 
+ * received statistics data to data stores.
+ * TODO: Need to add error message listener and clean-up the associated tx id 
+ * if it exists in the tx-id cache.
+ * @author vishnoianil
+ *
+ */
 public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsListener,
         OpendaylightMeterStatisticsListener, 
         OpendaylightFlowStatisticsListener,
         OpendaylightPortStatisticsListener,
-        OpendaylightFlowTableStatisticsListener{
+        OpendaylightFlowTableStatisticsListener,
+        OpendaylightQueueStatisticsListener{
     
     public final static Logger sucLogger = LoggerFactory.getLogger(StatisticsUpdateCommiter.class);
 
@@ -110,7 +138,10 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
    
     @Override
     public void onMeterConfigStatsUpdated(MeterConfigStatsUpdated notification) {
-
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+        
         //Add statistics to local cache
         ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
         if(!cache.containsKey(notification.getId())){
@@ -119,29 +150,40 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         cache.get(notification.getId()).setMeterConfigStats(notification.getMeterConfigStats());
         
         //Publish data to configuration data store
-        DataModificationTransaction it = this.statisticsManager.startChange();
         NodeKey key = new NodeKey(notification.getId());
-        NodeRef ref = getNodeRef(key);
-        
-        final NodeBuilder nodeData = new NodeBuilder(); 
-        nodeData.setKey(key);
         
-        NodeMeterConfigStatsBuilder meterConfig= new NodeMeterConfigStatsBuilder();
-        MeterConfigStatsBuilder stats = new MeterConfigStatsBuilder();
-        stats.setMeterConfigStats(notification.getMeterConfigStats());
-        meterConfig.setMeterConfigStats(stats.build());
-        
-        //Update augmented data
-        nodeData.addAugmentation(NodeMeterConfigStats.class, meterConfig.build());
+        List<MeterConfigStats> eterConfigStatsList = notification.getMeterConfigStats();
         
-        InstanceIdentifier<? extends Object> refValue = ref.getValue();
-        it.putOperationalData(refValue, nodeData.build());
-        it.commit();
+        for(MeterConfigStats meterConfigStats : eterConfigStatsList){
+            DataModificationTransaction it = this.statisticsManager.startChange();
+            MeterBuilder meterBuilder = new MeterBuilder();
+            MeterKey meterKey = new MeterKey(meterConfigStats.getMeterId());
+            meterBuilder.setKey(meterKey);
+            
+            InstanceIdentifier<Meter> meterRef = InstanceIdentifier.builder(Nodes.class).child(Node.class,key)
+                                                                                        .augmentation(FlowCapableNode.class)
+                                                                                        .child(Meter.class,meterKey).toInstance();
+            
+            NodeMeterConfigStatsBuilder meterConfig= new NodeMeterConfigStatsBuilder();
+            MeterConfigStatsBuilder stats = new MeterConfigStatsBuilder();
+            stats.fieldsFrom(meterConfigStats);
+            meterConfig.setMeterConfigStats(stats.build());
+            
+            //Update augmented data
+            meterBuilder.addAugmentation(NodeMeterConfigStats.class, meterConfig.build());
+            it.putOperationalData(meterRef, meterBuilder.build());
+            it.commit();
 
+        }
     }
 
     @Override
     public void onMeterStatisticsUpdated(MeterStatisticsUpdated notification) {
+        
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+
         //Add statistics to local cache
         ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
         if(!cache.containsKey(notification.getId())){
@@ -149,30 +191,41 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         }
         cache.get(notification.getId()).setMeterStatistics(notification.getMeterStats());
         
-        //Publish data to configuration data store
-        DataModificationTransaction it = this.statisticsManager.startChange();
         NodeKey key = new NodeKey(notification.getId());
-        NodeRef ref = getNodeRef(key);
-        
-        final NodeBuilder nodeData = new NodeBuilder(); 
-        nodeData.setKey(key);
         
-        NodeMeterStatisticsBuilder meterStats= new NodeMeterStatisticsBuilder();
-        MeterStatisticsBuilder stats = new MeterStatisticsBuilder();
-        stats.setMeterStats(notification.getMeterStats());
-        meterStats.setMeterStatistics(stats.build());
+        List<MeterStats> meterStatsList = notification.getMeterStats();
         
-        //Update augmented data
-        nodeData.addAugmentation(NodeMeterStatistics.class, meterStats.build());
-        
-        InstanceIdentifier<? extends Object> refValue = ref.getValue();
-        it.putOperationalData(refValue, nodeData.build());
-        it.commit();
+        for(MeterStats meterStats : meterStatsList){
 
+            //Publish data to configuration data store
+            DataModificationTransaction it = this.statisticsManager.startChange();
+            MeterBuilder meterBuilder = new MeterBuilder();
+            MeterKey meterKey = new MeterKey(meterStats.getMeterId());
+            meterBuilder.setKey(meterKey);
+            
+            InstanceIdentifier<Meter> meterRef = InstanceIdentifier.builder(Nodes.class).child(Node.class,key)
+                                                                                        .augmentation(FlowCapableNode.class)
+                                                                                        .child(Meter.class,meterKey).toInstance();
+            
+            NodeMeterStatisticsBuilder meterStatsBuilder= new NodeMeterStatisticsBuilder();
+            MeterStatisticsBuilder stats = new MeterStatisticsBuilder();
+            stats.fieldsFrom(meterStats);
+            meterStatsBuilder.setMeterStatistics(stats.build());
+
+            //Update augmented data
+            meterBuilder.addAugmentation(NodeMeterStatistics.class, meterStatsBuilder.build());
+            it.putOperationalData(meterRef, meterBuilder.build());
+            it.commit();
+        }
     }
 
     @Override
     public void onGroupDescStatsUpdated(GroupDescStatsUpdated notification) {
+        
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+
         //Add statistics to local cache
         ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
         if(!cache.containsKey(notification.getId())){
@@ -181,30 +234,40 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         cache.get(notification.getId()).setGroupDescStats(notification.getGroupDescStats());
         
         //Publish data to configuration data store
-        DataModificationTransaction it = this.statisticsManager.startChange();
         NodeKey key = new NodeKey(notification.getId());
-        NodeRef ref = getNodeRef(key);
-        
-        final NodeBuilder nodeData = new NodeBuilder(); 
-        nodeData.setKey(key);
-        
-        NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder();
-        GroupDescBuilder stats = new GroupDescBuilder();
-        stats.setGroupDescStats(notification.getGroupDescStats());
-        groupDesc.setGroupDesc(stats.build());
-        
-        //Update augmented data
-        nodeData.addAugmentation(NodeGroupDescStats.class, groupDesc.build());
+        List<GroupDescStats> groupDescStatsList = notification.getGroupDescStats();
 
-        InstanceIdentifier<? extends Object> refValue = ref.getValue();
-        it.putOperationalData(refValue, nodeData.build());
-        it.commit();
+        for(GroupDescStats groupDescStats : groupDescStatsList){
+            DataModificationTransaction it = this.statisticsManager.startChange();
+            
+            GroupBuilder groupBuilder = new GroupBuilder();
+            GroupKey groupKey = new GroupKey(groupDescStats.getGroupId());
+            groupBuilder.setKey(groupKey);
+            
+            InstanceIdentifier<Group> groupRef = InstanceIdentifier.builder(Nodes.class).child(Node.class,key)
+                                                                                        .augmentation(FlowCapableNode.class)
+                                                                                        .child(Group.class,groupKey).toInstance();
+
+            NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder();
+            GroupDescBuilder stats = new GroupDescBuilder();
+            stats.fieldsFrom(groupDescStats);
+            groupDesc.setGroupDesc(stats.build());
+            
+            //Update augmented data
+            groupBuilder.addAugmentation(NodeGroupDescStats.class, groupDesc.build());
 
+            it.putOperationalData(groupRef, groupBuilder.build());
+            it.commit();
+        }
     }
 
     @Override
     public void onGroupStatisticsUpdated(GroupStatisticsUpdated notification) {
         
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+
         //Add statistics to local cache
         ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
         if(!cache.containsKey(notification.getId())){
@@ -213,33 +276,30 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         cache.get(notification.getId()).setGroupStatistics(notification.getGroupStats());
         
         //Publish data to configuration data store
-        
-        DataModificationTransaction it = this.statisticsManager.startChange();
         NodeKey key = new NodeKey(notification.getId());
-        NodeRef ref = getNodeRef(key);
-
-        final NodeBuilder nodeData = new NodeBuilder(); 
-        nodeData.setKey(key);
-        
-        NodeGroupStatisticsBuilder groupStats = new NodeGroupStatisticsBuilder();
-        GroupStatisticsBuilder stats = new GroupStatisticsBuilder();
-        stats.setGroupStats(notification.getGroupStats());
-        groupStats.setGroupStatistics(stats.build());
-                
-        //Update augmented data
-        nodeData.addAugmentation(NodeGroupStatistics.class, groupStats.build());
+        List<GroupStats> groupStatsList = notification.getGroupStats();
 
-        InstanceIdentifier<? extends Object> refValue = ref.getValue();
-        it.putOperationalData(refValue, nodeData.build());
-        it.commit();
-
-//        for (GroupStats groupstat : notification.getGroupStats()) {
-//        
-//            GroupStatsKey groupKey = groupstat.getKey();
-//            InstanceIdentifier<? extends Object> id = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).augmentation(NodeGroupStatistics.class).child(GroupStatistics.class).child(GroupStats.class,groupKey).toInstance();
-//            it.putOperationalData(id, groupstat);
-//            it.commit();
-//        }
+        for(GroupStats groupStats : groupStatsList){
+            DataModificationTransaction it = this.statisticsManager.startChange();
+            
+            GroupBuilder groupBuilder = new GroupBuilder();
+            GroupKey groupKey = new GroupKey(groupStats.getGroupId());
+            groupBuilder.setKey(groupKey);
+            
+            InstanceIdentifier<Group> groupRef = InstanceIdentifier.builder(Nodes.class).child(Node.class,key)
+                                                                                        .augmentation(FlowCapableNode.class)
+                                                                                        .child(Group.class,groupKey).toInstance();
+
+            NodeGroupStatisticsBuilder groupStatisticsBuilder= new NodeGroupStatisticsBuilder();
+            GroupStatisticsBuilder stats = new GroupStatisticsBuilder();
+            stats.fieldsFrom(groupStats);
+            groupStatisticsBuilder.setGroupStatistics(stats.build());
+            
+            //Update augmented data
+            groupBuilder.addAugmentation(NodeGroupStatistics.class, groupStatisticsBuilder.build());
+            it.putOperationalData(groupRef, groupBuilder.build());
+            it.commit();
+        }
     }
     
     @Override
@@ -315,8 +375,13 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
 
     @Override
     public void onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
+        
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+
         NodeKey key = new NodeKey(notification.getId());
-        sucLogger.info("Received flow stats update : {}",notification.toString());
+        sucLogger.debug("Received flow stats update : {}",notification.toString());
         
         for(FlowAndStatisticsMapList map: notification.getFlowAndStatisticsMapList()){
             short tableId = map.getTableId();
@@ -395,8 +460,8 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
 
             flowStatisticsData.setFlowStatistics(flowStatistics.build());
                 
-            sucLogger.info("Flow : {}",flowRule.toString());
-            sucLogger.info("Statistics to augment : {}",flowStatistics.build().toString());
+            sucLogger.debug("Flow : {}",flowRule.toString());
+            sucLogger.debug("Statistics to augment : {}",flowStatistics.build().toString());
 
             InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
                     .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
@@ -437,7 +502,7 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
                         .child(Flow.class,newFlowKey).toInstance();
                 flowBuilder.setKey(newFlowKey);
                 flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
-                sucLogger.debug("Flow was no present in data store, augmenting statistics as an unaccounted flow");
+                sucLogger.info("Flow was no present in data store, augmenting statistics as an unaccounted flow");
                 it.putOperationalData(flowRef, flowBuilder.build());
                 it.commit();
             }
@@ -446,6 +511,10 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
 
     @Override
     public void onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+
         NodeKey key = new NodeKey(notification.getId());
         sucLogger.debug("Received aggregate flow statistics update : {}",notification.toString());
         
@@ -482,9 +551,13 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
     }
 
     @Override
-    public void onPortStatisticsUpdate(PortStatisticsUpdate notification) {
+    public void onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) {
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+
         NodeKey key = new NodeKey(notification.getId());
-        sucLogger.info("Received port stats update : {}",notification.toString());
+        sucLogger.debug("Received port stats update : {}",notification.toString());
         
         //Add statistics to local cache
         ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
@@ -537,6 +610,10 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
 
     @Override
     public void onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
+
         NodeKey key = new NodeKey(notification.getId());
         sucLogger.debug("Received flow table statistics update : {}",notification.toString());
         
@@ -574,24 +651,63 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
     }
 
     @Override
-    public void onFlowStatisticsUpdated(FlowStatisticsUpdated notification) {
-        // TODO Auto-generated method stub
-        //TODO: Depricated, will clean it up once sal-compatibility is fixed.
-        //Sal-Compatibility code usage this notification event.
+    public void onQueueStatisticsUpdate(QueueStatisticsUpdate notification) {
         
-    }
+        //Check if response is for the request statistics-manager sent.
+        if(this.statisticsManager.getMultipartMessageManager().removeTxId(notification.getTransactionId()) == null)
+            return;
 
-    @Override
-    public void onFlowTableStatisticsUpdated(FlowTableStatisticsUpdated notification) {
-        // TODO Auto-generated method stub
-        //TODO: Need to implement it yet
+        NodeKey key = new NodeKey(notification.getId());
+        sucLogger.debug("Received queue stats update : {}",notification.toString());
         
-    }
+        //Add statistics to local cache
+        ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+        if(!cache.containsKey(notification.getId())){
+            cache.put(notification.getId(), new NodeStatistics());
+        }
+        
+        List<QueueIdAndStatisticsMap> queuesStats = notification.getQueueIdAndStatisticsMap();
+        for(QueueIdAndStatisticsMap swQueueStats : queuesStats){
+            
+            if(!cache.get(notification.getId()).getNodeConnectorAndQueuesStatsMap().containsKey(swQueueStats.getNodeConnectorId())){
+                cache.get(notification.getId()).getNodeConnectorAndQueuesStatsMap().put(swQueueStats.getNodeConnectorId(), new HashMap<QueueId,GenericQueueStatistics>());
+            }
+            
+            FlowCapableNodeConnectorQueueStatisticsDataBuilder queueStatisticsDataBuilder = new FlowCapableNodeConnectorQueueStatisticsDataBuilder();
+            
+            FlowCapableNodeConnectorQueueStatisticsBuilder queueStatisticsBuilder = new FlowCapableNodeConnectorQueueStatisticsBuilder();
+            
+            queueStatisticsBuilder.fieldsFrom(swQueueStats);
+            
+            queueStatisticsDataBuilder.setFlowCapableNodeConnectorQueueStatistics(queueStatisticsBuilder.build());
+            
+            cache.get(notification.getId()).getNodeConnectorAndQueuesStatsMap()
+                                            .get(swQueueStats.getNodeConnectorId())
+                                            .put(swQueueStats.getQueueId(), queueStatisticsBuilder.build());
+            
+            
+            DataModificationTransaction it = this.statisticsManager.startChange();
 
-    @Override
-    public void onNodeConnectorStatisticsUpdated(NodeConnectorStatisticsUpdated notification) {
-        // TODO Auto-generated method stub
-        //TODO: Need to implement it yet
+            InstanceIdentifier<Queue> queueRef 
+                    = InstanceIdentifier.builder(Nodes.class)
+                                        .child(Node.class, key)
+                                        .child(NodeConnector.class, new NodeConnectorKey(swQueueStats.getNodeConnectorId()))
+                                        .augmentation(FlowCapableNodeConnector.class)
+                                        .child(Queue.class, new QueueKey(swQueueStats.getQueueId())).toInstance();
+            
+            QueueBuilder queueBuilder = new QueueBuilder();
+            queueBuilder.addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, queueStatisticsDataBuilder.build());
+            queueBuilder.setKey(new QueueKey(swQueueStats.getQueueId()));
+
+            sucLogger.info("Augmenting queue statistics {} of queue {} to port {}"
+                                        ,queueStatisticsDataBuilder.build().toString(),
+                                        swQueueStats.getQueueId(),
+                                        swQueueStats.getNodeConnectorId());
+            
+            it.putOperationalData(queueRef, queueBuilder.build());
+            it.commit();
+            
+        }
         
     }
 
@@ -669,4 +785,5 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         }
         return true;
     }
+
 }
index ed8f02bf569974daeb14b91eeccd81e32d7f0a25..7cd43bd79a01b4b4436a12cfa5721e14108e165d 100644 (file)
@@ -8,12 +8,16 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
+import org.opendaylight.controller.config.api.LookupRegistry;
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
 import org.opendaylight.controller.config.yang.store.api.YangStoreService;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
+import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
@@ -42,12 +46,38 @@ public class NetconfOperationServiceImpl implements NetconfOperationService {
             String netconfSessionIdForReporting) throws YangStoreException {
 
         yangStoreSnapshot = yangStoreService.getYangStoreSnapshot();
+        checkConsistencyBetweenYangStoreAndConfig(jmxClient, yangStoreSnapshot);
+
         transactionProvider = new TransactionProvider(jmxClient, netconfSessionIdForReporting);
         operationProvider = new NetconfOperationProvider(yangStoreSnapshot, jmxClient, transactionProvider,
                 netconfSessionIdForReporting);
         capabilities = setupCapabilities(yangStoreSnapshot);
     }
 
+
+    @VisibleForTesting
+    static void checkConsistencyBetweenYangStoreAndConfig(LookupRegistry jmxClient, YangStoreSnapshot yangStoreSnapshot) {
+        Set<String> missingModulesFromConfig = Sets.newHashSet();
+
+        Set<String> modulesSeenByConfig = jmxClient.getAvailableModuleFactoryQNames();
+        Map<String, Map<String, ModuleMXBeanEntry>> moduleMXBeanEntryMap = yangStoreSnapshot.getModuleMXBeanEntryMap();
+
+        for (Map<String, ModuleMXBeanEntry> moduleNameToMBE : moduleMXBeanEntryMap.values()) {
+            for (ModuleMXBeanEntry moduleMXBeanEntry : moduleNameToMBE.values()) {
+                String moduleSeenByYangStore = moduleMXBeanEntry.getYangModuleQName().toString();
+                if(modulesSeenByConfig.contains(moduleSeenByYangStore) == false)
+                    missingModulesFromConfig.add(moduleSeenByYangStore);
+            }
+        }
+
+        Preconditions
+                .checkState(
+                        missingModulesFromConfig.isEmpty(),
+                        "There are inconsistencies between configuration subsystem and yangstore in terms of discovered yang modules, yang modules missing from config subsystem but present in yangstore: %s, %sAll modules present in config: %s",
+                        missingModulesFromConfig, System.lineSeparator(), modulesSeenByConfig);
+
+    }
+
     @Override
     public void close() {
         yangStoreSnapshot.close();
diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImplTest.java
new file mode 100644 (file)
index 0000000..53e14ba
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.opendaylight.controller.config.api.LookupRegistry;
+import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
+import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class NetconfOperationServiceImplTest {
+
+    private static final Date date1970_01_01;
+
+    static {
+        try {
+            date1970_01_01 = new SimpleDateFormat("yyyy-MM-dd").parse("1970-01-01");
+        } catch (ParseException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Test
+    public void testCheckConsistencyBetweenYangStoreAndConfig_ok() throws Exception {
+        NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(
+                mockJmxClient("qname1", "qname2"),
+                mockYangStoreSnapshot("qname2", "qname1"));
+    }
+
+    @Test
+    public void testCheckConsistencyBetweenYangStoreAndConfig_ok2() throws Exception {
+        NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(
+                mockJmxClient("qname1", "qname2", "qname4", "qname5"),
+                mockYangStoreSnapshot("qname2", "qname1"));
+    }
+
+    @Test
+    public void testCheckConsistencyBetweenYangStoreAndConfig_ok3() throws Exception {
+        NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(
+                mockJmxClient(),
+                mockYangStoreSnapshot());
+    }
+
+    @Test
+    public void testCheckConsistencyBetweenYangStoreAndConfig_yangStoreMore() throws Exception {
+        try {
+            NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(mockJmxClient("qname1"),
+                    mockYangStoreSnapshot("qname2", "qname1"));
+            fail("An exception of type " + IllegalArgumentException.class + " was expected");
+        } catch (IllegalStateException e) {
+            String message = e.getMessage();
+            Assert.assertThat(
+                    message,
+                    JUnitMatchers
+                            .containsString("missing from config subsystem but present in yangstore: [(namespace?revision=1970-01-01)qname2]"));
+            Assert.assertThat(
+                    message,
+                    JUnitMatchers
+                            .containsString("All modules present in config: [(namespace?revision=1970-01-01)qname1]"));
+        }
+    }
+
+    private YangStoreSnapshot mockYangStoreSnapshot(String... qnames) {
+        YangStoreSnapshot mock = mock(YangStoreSnapshot.class);
+
+        Map<String, Map<String, ModuleMXBeanEntry>> map = Maps.newHashMap();
+
+        Map<String, ModuleMXBeanEntry> innerMap = Maps.newHashMap();
+
+        int i = 1;
+        for (String qname : qnames) {
+            innerMap.put(Integer.toString(i++), mockMBeanEntry(qname));
+        }
+
+        map.put("1", innerMap);
+
+        doReturn(map).when(mock).getModuleMXBeanEntryMap();
+
+        return mock;
+    }
+
+    private ModuleMXBeanEntry mockMBeanEntry(String qname) {
+        ModuleMXBeanEntry mock = mock(ModuleMXBeanEntry.class);
+        QName q = getQName(qname);
+        doReturn(q).when(mock).getYangModuleQName();
+        return mock;
+    }
+
+    private QName getQName(String qname) {
+        return new QName(URI.create("namespace"), date1970_01_01, qname);
+    }
+
+    private LookupRegistry mockJmxClient(String... visibleQNames) {
+        LookupRegistry mock = mock(LookupRegistry.class);
+        Set<String> qnames = Sets.newHashSet();
+        for (String visibleQName : visibleQNames) {
+            QName q = getQName(visibleQName);
+            qnames.add(q.toString());
+        }
+        doReturn(qnames).when(mock).getAvailableModuleFactoryQNames();
+        return mock;
+    }
+}
index 7fc2b584b88d7902a956f5a399145fee0fabad4f..20bd386063419523d439dcb46102851208b6a7db 100644 (file)
@@ -90,6 +90,7 @@
                             org.opendaylight.controller.netconf.client,
                             org.opendaylight.controller.netconf.util.osgi,
                             org.opendaylight.controller.netconf.util.xml,
+                            org.opendaylight.controller.netconf.util.messages,
                             io.netty.channel,
                             io.netty.channel.nio,
                             io.netty.util.concurrent,
index 89c27032851b0b63eb9141a87f8768518688cc66..0b623baaa480dde170d6866d7fe1564242ed704e 100644 (file)
@@ -8,14 +8,24 @@
 
 package org.opendaylight.controller.netconf.persist.impl;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import io.netty.channel.EventLoopGroup;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.concurrent.Immutable;
+
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.client.NetconfClient;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageAdditionalHeader;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -25,14 +35,8 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import javax.annotation.concurrent.Immutable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetSocketAddress;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 @Immutable
 public class ConfigPusher {
@@ -127,10 +131,14 @@ public class ConfigPusher {
 
         long deadline = pollingStart + timeout;
 
+        String additionalHeader = NetconfMessageAdditionalHeader.toString("unknown", address.getAddress().getHostAddress(),
+                Integer.toString(address.getPort()), "tcp", Optional.of("persister"));
+
         Set<String> latestCapabilities = new HashSet<>();
         while (System.currentTimeMillis() < deadline) {
             attempt++;
-            NetconfClientDispatcher netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup);
+            NetconfClientDispatcher netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup,
+                    nettyThreadgroup, additionalHeader);
             NetconfClient netconfClient;
             try {
                 netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher);
diff --git a/opendaylight/netconf/ietf-netconf-monitoring-extension/pom.xml b/opendaylight/netconf/ietf-netconf-monitoring-extension/pom.xml
new file mode 100644 (file)
index 0000000..aebaaeb
--- /dev/null
@@ -0,0 +1,101 @@
+<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">
+    <parent>
+        <artifactId>netconf-subsystem</artifactId>
+        <groupId>org.opendaylight.controller</groupId>
+        <version>0.2.3-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-netconf-monitoring-extension</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+      <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>ietf-netconf-monitoring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>${yangtools.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>
+                                        target/generated-sources/monitoring
+                                    </outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>maven-sal-api-gen-plugin</artifactId>
+                        <version>${yangtools.binding.version}</version>
+                    </dependency>
+                </dependencies>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>1.7</version>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>target/generated-sources/sal</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            com.google.common.collect,
+                            org.opendaylight.yangtools.yang.binding,
+                            org.opendaylight.yangtools.yang.common,
+                            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004,
+                        </Import-Package>
+                        <Export-Package>
+                            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/opendaylight/netconf/ietf-netconf-monitoring-extension/src/main/yang/ietf-netconf-monitoring-extension.yang b/opendaylight/netconf/ietf-netconf-monitoring-extension/src/main/yang/ietf-netconf-monitoring-extension.yang
new file mode 100644 (file)
index 0000000..e8f2ec3
--- /dev/null
@@ -0,0 +1,31 @@
+module ietf-netconf-monitoring-extension {
+
+    yang-version 1;
+
+    namespace
+      "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension";
+
+    prefix ncme;
+
+    import ietf-netconf-monitoring {
+      prefix ncm;
+    }
+
+    revision "2013-12-10" {
+      description "Initial revision.";
+
+    }
+
+    identity netconf-tcp {
+      base ncm:transport;
+      description
+        "NETCONF over TCP.";
+    }
+
+    augment "/ncm:netconf-state/ncm:sessions/ncm:session" {
+      leaf session-identifier {
+        type string;
+      }
+    }
+
+}
\ No newline at end of file
index 0fce4748a40af53113d865492dd1f6ada93ce19a..856bd77c202ee73ee0cd65758f64ad598fd96f6a 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>ietf-netconf-monitoring</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ietf-netconf-monitoring-extension</artifactId>
+            <version>${project.version}</version>
+        </dependency>
 
         <dependency>
             <groupId>org.opendaylight.bgpcep</groupId>
index a0fddd79f2f0fcff8afced3ab91fcf21aeeea44d..7877843ccb99c7ad91230467720b7bbf17f72e25 100644 (file)
@@ -8,9 +8,10 @@
 
 package org.opendaylight.controller.netconf.api;
 
-import com.google.common.base.Optional;
 import org.w3c.dom.Document;
 
+import com.google.common.base.Optional;
+
 /**
  * NetconfMessage represents a wrapper around org.w3c.dom.Document. Needed for
  * implementing ProtocolMessage interface.
index 6ac57a88c9f4750513d8be139354f78abd5575a6..fc6f87db5d797748d622364b8db3dd5e9a65f58e 100644 (file)
@@ -13,8 +13,10 @@ import io.netty.channel.socket.SocketChannel;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.Promise;
+
 import java.io.Closeable;
 import java.net.InetSocketAddress;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
@@ -26,6 +28,8 @@ import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+
 public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSession, NetconfClientSessionListener> implements Closeable {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
@@ -36,7 +40,13 @@ public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSes
     public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
         super(bossGroup, workerGroup);
         timer = new HashedWheelTimer();
-        this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer);
+        this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.<String>absent());
+    }
+
+    public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup, String additionalHeader) {
+        super(bossGroup, workerGroup);
+        timer = new HashedWheelTimer();
+        this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.of(additionalHeader));
     }
 
     public Future<NetconfClientSession> createClient(InetSocketAddress address,
index db0b953bddf4f7c730fcd271bb7e5e603bcc0eb1..abfbdd526c5f7bb6796c7c0273060e7b91aa8933 100644 (file)
@@ -8,10 +8,13 @@
 
 package org.opendaylight.controller.netconf.client;
 
-import com.google.common.base.Preconditions;
 import io.netty.channel.Channel;
 import io.netty.util.Timer;
 import io.netty.util.concurrent.Promise;
+
+import java.io.IOException;
+import java.io.InputStream;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -20,15 +23,18 @@ import org.opendaylight.protocol.framework.SessionNegotiator;
 import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
 import org.xml.sax.SAXException;
 
-import java.io.IOException;
-import java.io.InputStream;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorFactory {
 
     private final Timer timer;
 
-    public NetconfClientSessionNegotiatorFactory(Timer timer) {
+    private final Optional<String> additionalHeader;
+
+    public NetconfClientSessionNegotiatorFactory(Timer timer, Optional<String> additionalHeader) {
         this.timer = timer;
+        this.additionalHeader = additionalHeader;
     }
 
     private static NetconfMessage loadHelloMessageTemplate() {
@@ -45,7 +51,11 @@ public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorF
     public SessionNegotiator getSessionNegotiator(SessionListenerFactory sessionListenerFactory, Channel channel,
             Promise promise) {
         // Hello message needs to be recreated every time
-        NetconfSessionPreferences proposal = new NetconfSessionPreferences(loadHelloMessageTemplate());
+        NetconfMessage helloMessage = loadHelloMessageTemplate();
+        if(this.additionalHeader.isPresent()) {
+            helloMessage = new NetconfMessage(helloMessage.getDocument(), additionalHeader.get());
+        }
+        NetconfSessionPreferences proposal = new NetconfSessionPreferences(helloMessage);
         return new NetconfClientSessionNegotiator(proposal, promise, channel, timer,
                 sessionListenerFactory.getSessionListener());
     }
index 4de6cc35c0dad3f00afe949821a1dab59f4bc3da..ee07b3949d6dd2f040da183a46dde263abe6d9af 100644 (file)
@@ -14,8 +14,10 @@ import io.netty.channel.socket.SocketChannel;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.Promise;
+
 import java.io.IOException;
 import java.net.InetSocketAddress;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
@@ -31,6 +33,8 @@ import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.SessionListener;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 
+import com.google.common.base.Optional;
+
 public class NetconfSshClientDispatcher extends NetconfClientDispatcher {
 
     private AuthenticationHandler authHandler;
@@ -42,7 +46,15 @@ public class NetconfSshClientDispatcher extends NetconfClientDispatcher {
         super(bossGroup, workerGroup);
         this.authHandler = authHandler;
         this.timer = new HashedWheelTimer();
-        this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer);
+        this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.<String>absent());
+    }
+
+    public NetconfSshClientDispatcher(AuthenticationHandler authHandler, EventLoopGroup bossGroup,
+            EventLoopGroup workerGroup, String additionalHeader) {
+        super(bossGroup, workerGroup, additionalHeader);
+        this.authHandler = authHandler;
+        this.timer = new HashedWheelTimer();
+        this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.of(additionalHeader));
     }
 
     public Future<NetconfClientSession> createClient(InetSocketAddress address,
index e073aaca8d039dddf4f6c976dcbe1e30de1b4dd7..b056f9be873feff65d2b731d66b6ef8fe0d8c4cd 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>ietf-netconf-monitoring</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ietf-netconf-monitoring-extension</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>netconf-util</artifactId>
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas,
+                            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
+                            org.opendaylight.yangtools.yang.binding,
                         </Import-Package>
                     </instructions>
                 </configuration>
index b6921794296e3f04d02d6e36ef45762a8888ecec..4cc05b7b42fa40a17f9552e2d459b1bfdb85cea6 100644 (file)
@@ -8,13 +8,21 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import com.google.common.base.Preconditions;
 import io.netty.channel.Channel;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
 import org.opendaylight.protocol.framework.SessionListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.NetconfTcp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1Builder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Transport;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
@@ -25,10 +33,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import com.google.common.base.Preconditions;
 
 public class NetconfServerSession extends NetconfSession implements NetconfManagementSession {
 
@@ -91,14 +96,18 @@ public class NetconfServerSession extends NetconfSession implements NetconfManag
         builder.setOutNotifications(new ZeroBasedCounter32(0L));
 
         builder.setKey(new SessionKey(getSessionId()));
+
+        Session1Builder builder1 = new Session1Builder();
+        builder1.setSessionIdentifier(header.getSessionType());
+        builder.addAugmentation(Session1.class, builder1.build());
+
         return builder.build();
     }
 
     private Class<? extends Transport> getTransportForString(String transport) {
         switch(transport) {
             case "ssh" : return NetconfSsh.class;
-            // TODO what about tcp
-            case "tcp" : return NetconfSsh.class;
+            case "tcp" : return NetconfTcp.class;
             default: throw new IllegalArgumentException("Unknown transport type " + transport);
         }
     }
index 01ac018b3eadc3ee85d6ffd7a5e12fb8cbaf2daa..8ba4cdc052057333df0154162153adf9ee663e2f 100644 (file)
@@ -8,28 +8,27 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import io.netty.channel.Channel;
 import io.netty.util.Timer;
 import io.netty.util.concurrent.Promise;
+
+import java.net.InetSocketAddress;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
+import org.opendaylight.controller.netconf.impl.util.AdditionalHeaderUtil;
 import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
 import org.opendaylight.protocol.framework.SessionListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import com.google.common.base.Optional;
 
 public class NetconfServerSessionNegotiator extends
         AbstractNetconfSessionNegotiator<NetconfServerSessionPreferences, NetconfServerSession> {
 
     static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionNegotiator.class);
 
-    private static final AdditionalHeader DEFAULT_HEADER = new AdditionalHeader();
-
     protected NetconfServerSessionNegotiator(NetconfServerSessionPreferences sessionPreferences,
             Promise<NetconfServerSession> promise, Channel channel, Timer timer, SessionListener sessionListener) {
         super(sessionPreferences, promise, channel, timer, sessionListener);
@@ -41,36 +40,28 @@ public class NetconfServerSessionNegotiator extends
 
         AdditionalHeader parsedHeader;
         if (additionalHeader.isPresent()) {
-            parsedHeader = new AdditionalHeader(additionalHeader.get());
+            parsedHeader = AdditionalHeaderUtil.fromString(additionalHeader.get());
         } else {
-            parsedHeader = DEFAULT_HEADER;
+            parsedHeader = new AdditionalHeader("unknown", ((InetSocketAddress)channel.localAddress()).getHostString(),
+                    "tcp", "client");
         }
         logger.debug("Additional header from hello parsed as {} from {}", parsedHeader, additionalHeader);
 
         return new NetconfServerSession(sessionListener, channel, sessionPreferences.getSessionId(), parsedHeader);
     }
 
-    static class AdditionalHeader {
+    public static class AdditionalHeader {
 
-        private static final Pattern pattern = Pattern
-                .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+)[^\\]]+\\]");
         private final String username;
         private final String address;
         private final String transport;
+        private final String sessionIdentifier;
 
-        public AdditionalHeader(String addHeaderAsString) {
-            addHeaderAsString = addHeaderAsString.trim();
-            Matcher matcher = pattern.matcher(addHeaderAsString);
-            Preconditions.checkArgument(matcher.matches(), "Additional header in wrong format %s, expected %s",
-                    addHeaderAsString, pattern);
-            this.username = matcher.group("username");
-            this.address = matcher.group("address");
-            this.transport = matcher.group("transport");
-        }
-
-        private AdditionalHeader() {
-            this.username = this.address = "unknown";
-            this.transport = "ssh";
+        public AdditionalHeader(String userName, String hostAddress, String transport, String sessionIdentifier) {
+            this.address = hostAddress;
+            this.username = userName;
+            this.transport = transport;
+            this.sessionIdentifier = sessionIdentifier;
         }
 
         String getUsername() {
@@ -85,6 +76,10 @@ public class NetconfServerSessionNegotiator extends
             return transport;
         }
 
+        String getSessionType() {
+            return sessionIdentifier;
+        }
+
         @Override
         public String toString() {
             final StringBuffer sb = new StringBuffer("AdditionalHeader{");
@@ -95,4 +90,5 @@ public class NetconfServerSessionNegotiator extends
             return sb.toString();
         }
     }
+
 }
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/AdditionalHeaderUtil.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/AdditionalHeaderUtil.java
new file mode 100644 (file)
index 0000000..5c630dd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.impl.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiator.AdditionalHeader;
+
+import com.google.common.base.Preconditions;
+
+public class AdditionalHeaderUtil {
+
+    private static final Pattern pattern = Pattern
+            .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+)[^\\]]+\\]");
+    private static final Pattern customHeaderPattern = Pattern
+            .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+);(?<sessionIdentifier>[a-z]+)[^\\]]+\\]");
+
+    public static AdditionalHeader fromString(String additionalHeader) {
+        additionalHeader = additionalHeader.trim();
+        Matcher matcher = pattern.matcher(additionalHeader);
+        Matcher matcher2 = customHeaderPattern.matcher(additionalHeader);
+        Preconditions.checkArgument(matcher.matches(), "Additional header in wrong format %s, expected %s",
+                additionalHeader, pattern);
+        String username = matcher.group("username");
+        String address = matcher.group("address");
+        String transport = matcher.group("transport");
+        String sessionIdentifier = "client";
+        if (matcher2.matches()) {
+            sessionIdentifier = matcher2.group("sessionIdentifier");
+        }
+        return new AdditionalHeader(username, address, transport, sessionIdentifier);
+    }
+
+}
index 2f8fac23f5beac0e2461d0348baef9e4395f0846..97d9a98b5777b01e37468c00a98e8ea54f4dc889 100644 (file)
@@ -8,14 +8,16 @@
 package org.opendaylight.controller.netconf.impl;
 
 import junit.framework.Assert;
+
 import org.junit.Test;
+import org.opendaylight.controller.netconf.impl.util.AdditionalHeaderUtil;
 
 public class AdditionalHeaderParserTest {
 
     @Test
     public void testParsing() throws Exception {
         String s = "[netconf;10.12.0.102:48528;ssh;;;;;;]";
-        NetconfServerSessionNegotiator.AdditionalHeader header = new NetconfServerSessionNegotiator.AdditionalHeader(s);
+        NetconfServerSessionNegotiator.AdditionalHeader header = AdditionalHeaderUtil.fromString(s);
         Assert.assertEquals("netconf", header.getUsername());
         Assert.assertEquals("10.12.0.102", header.getAddress());
         Assert.assertEquals("ssh", header.getTransport());
@@ -24,7 +26,7 @@ public class AdditionalHeaderParserTest {
     @Test
     public void testParsing2() throws Exception {
         String s = "[tomas;10.0.0.0/10000;tcp;1000;1000;;/home/tomas;;]";
-        NetconfServerSessionNegotiator.AdditionalHeader header = new NetconfServerSessionNegotiator.AdditionalHeader(s);
+        NetconfServerSessionNegotiator.AdditionalHeader header = AdditionalHeaderUtil.fromString(s);
         Assert.assertEquals("tomas", header.getUsername());
         Assert.assertEquals("10.0.0.0", header.getAddress());
         Assert.assertEquals("tcp", header.getTransport());
@@ -33,6 +35,6 @@ public class AdditionalHeaderParserTest {
     @Test(expected = IllegalArgumentException.class)
     public void testParsingNoUsername() throws Exception {
         String s = "[10.12.0.102:48528;ssh;;;;;;]";
-        new NetconfServerSessionNegotiator.AdditionalHeader(s);
+        AdditionalHeaderUtil.fromString(s);
     }
 }
index ce5233c494e6ddac78339709e9ae23dc5df05658..8d3476f4b8dfa9b08507cb0e29eb2a6393a972e9 100644 (file)
@@ -8,12 +8,31 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.fail;
+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 io.netty.channel.ChannelFuture;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
+
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.ObjectName;
+
 import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -44,31 +63,15 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import javax.management.ObjectName;
-import java.io.DataOutputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.junit.Assert.fail;
-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 com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 public class ConcurrentClientsTest {
 
     private static final int CONCURRENCY = 16;
     private static EventLoopGroup nettyGroup = new NioEventLoopGroup();
-    public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher( nettyGroup, nettyGroup);
+    public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER =
+            new NetconfClientDispatcher( nettyGroup, nettyGroup);
 
     @Mock
     private YangStoreService yangStoreService;
index f2de91ef46d2be313b7626262076463fa8cc687d..31248137e8fef8f741d9473b71322b777b00f3e5 100644 (file)
             <artifactId>netconf-ssh</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-ssh</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>netconf-util</artifactId>
index c61dab7f643ebd119544cb12d76c0b420435d6af..4818b5f0a3c7868be0a02dafd19e8c1657e0d777 100644 (file)
@@ -8,18 +8,14 @@
 
 package org.opendaylight.controller.netconf.it;
 
-import static java.util.Collections.emptyList;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import ch.ethz.ssh2.Connection;
+import ch.ethz.ssh2.Session;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.management.ManagementFactory;
@@ -31,12 +27,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
-
 import javax.management.ObjectName;
 import javax.xml.parsers.ParserConfigurationException;
-
 import junit.framework.Assert;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -51,6 +44,7 @@ import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactor
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
 import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
+import org.opendaylight.controller.netconf.StubUserManager;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.client.NetconfClient;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
@@ -68,6 +62,7 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFact
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
+import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.ExiParameters;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -79,12 +74,13 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
-
-import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import static java.util.Collections.emptyList;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
 public class NetconfITTest extends AbstractConfigTest {
 
@@ -435,7 +431,9 @@ public class NetconfITTest extends AbstractConfigTest {
 
     private void startSSHServer() throws Exception{
         logger.info("Creating SSH server");
-        Thread sshServerThread = new Thread(NetconfSSHServer.start(10830,tcpAddress));
+        StubUserManager um = new StubUserManager(USERNAME,PASSWORD);
+        AuthProvider ap = new AuthProvider(um);
+        Thread sshServerThread = new Thread(NetconfSSHServer.start(10830,tcpAddress,ap));
         sshServerThread.setDaemon(true);
         sshServerThread.start();
         logger.info("SSH server on");
index 244e4ba4a94330d0ac446bca6354cfbe8af38a62..3a7b7de7a0b2a589b410ddd76996556412e64434 100644 (file)
@@ -7,14 +7,27 @@
  */
 package org.opendaylight.controller.netconf.it;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
 import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.matchers.JUnitMatchers;
@@ -48,20 +61,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 public class NetconfMonitoringITTest extends AbstractConfigTest {
 
index 31e427191c4827771d25cb480f42749b41f2678d..8e1e599c719a6794d17b91b2792efbf27f85e458 100644 (file)
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924,
                             org.osgi.util.tracker,
+                            org.opendaylight.yangtools.yang.common,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004,
                             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas,
+                            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
+                            org.opendaylight.yangtools.yang.binding,
                         </Import-Package>
                     </instructions>
                 </configuration>
index 25fb5d44dcc3a15ee0b72282293292cf53fc529d..55aee72fda98af82b894a8f6be83a1d339d904ac 100644 (file)
@@ -7,13 +7,13 @@
  */
 package org.opendaylight.controller.netconf.monitoring.xml.model;
 
-import com.google.common.base.Preconditions;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
-
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlTransient;
 
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
+import org.opendaylight.yangtools.yang.common.QName;
+
 final class MonitoringSession {
 
     @XmlTransient
@@ -67,8 +67,17 @@ final class MonitoringSession {
 
     @XmlElement(name = "transport")
     public String getTransport() {
-        Preconditions.checkState(managementSession.getTransport() == NetconfSsh.class);
-        return "netconf-ssh";
+        try {
+            QName qName = (QName) managementSession.getTransport().getField("QNAME").get(null);
+            return qName.getLocalName();
+        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+            throw new IllegalArgumentException("Unknown transport type " + managementSession.getTransport(), e);
+        }
+    }
+
+    @XmlElement(name= "session-identifier")
+    public String getSessionType() {
+        return managementSession.getAugmentation(Session1.class).getSessionIdentifier();
     }
 
     @XmlElement(name = "username")
index cb6e59f83f2463d022971bc10ff6cfe26b9b4133..1e3f343624726e9ff0af80f98c3da32e9233f7c5 100644 (file)
@@ -7,13 +7,18 @@
 */
 package org.opendaylight.controller.netconf.monitoring.xml;
 
-import com.google.common.collect.Lists;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import java.util.Date;
+
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder;
@@ -25,10 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.ZeroBasedCounter32;
 import org.w3c.dom.Element;
 
-import java.util.Date;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.collect.Lists;
 
 public class JaxBSerializerTest {
 
@@ -54,6 +56,8 @@ public class JaxBSerializerTest {
 
     private Session getMockSession() {
         Session mocked = mock(Session.class);
+        Session1 mockedSession1 = mock(Session1.class);
+        doReturn("client").when(mockedSession1).getSessionIdentifier();
         doReturn(1L).when(mocked).getSessionId();
         doReturn(new DateAndTime(new Date().toString())).when(mocked).getLoginTime();
         doReturn(new Host(new DomainName("address/port"))).when(mocked).getSourceHost();
@@ -63,6 +67,7 @@ public class JaxBSerializerTest {
         doReturn(new ZeroBasedCounter32(0L)).when(mocked).getOutRpcErrors();
         doReturn(NetconfSsh.class).when(mocked).getTransport();
         doReturn("username").when(mocked).getUsername();
+        doReturn(mockedSession1).when(mocked).getAugmentation(Session1.class);
         return mocked;
     }
 }
index f60b4b02f5edb571c15313139ce32895fb4843a8..5dde0448bd03ac6b16b49aee77f5589969ea77d1 100644 (file)
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>usermanager</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.4</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                             org.apache.commons.io,
                             org.opendaylight.controller.netconf.util,
                             org.opendaylight.controller.netconf.util.osgi,
+                            org.opendaylight.controller.usermanager,
+                            org.opendaylight.controller.sal.authorization,
+                            org.opendaylight.controller.sal.utils,
                             org.opendaylight.protocol.framework,
                             org.osgi.framework,
-                            org.slf4j
+                            org.osgi.util.tracker,
+                            org.slf4j,
                         </Import-Package>
                     </instructions>
                 </configuration>
index b91824866a107ffef75290f3a52af53318dca7a5..3b513790bd128806a7ef1bec2561bd90fee6420a 100644 (file)
@@ -10,9 +10,14 @@ package org.opendaylight.controller.netconf.osgi;
 import com.google.common.base.Optional;
 import java.net.InetSocketAddress;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
+import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
+import org.opendaylight.controller.usermanager.IUserManager;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,18 +36,57 @@ public class NetconfSSHActivator implements BundleActivator{
     private NetconfSSHServer server;
     private static final Logger logger =  LoggerFactory.getLogger(NetconfSSHActivator.class);
     private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
+    private IUserManager iUserManager;
+    private BundleContext context = null;
+
+    ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
+        @Override
+        public IUserManager addingService(ServiceReference<IUserManager> reference) {
+            logger.info("Service IUserManager added, let there be SSH bridge.");
+            iUserManager =  context.getService(reference);
+            try {
+                onUserManagerFound(iUserManager);
+            } catch (Exception e) {
+                logger.trace("Can't start SSH server due to {}",e);
+            }
+            return iUserManager;
+        }
+        @Override
+        public void modifiedService(ServiceReference<IUserManager> reference, IUserManager service) {
+            logger.info("Replacing modified service IUserManager in netconf SSH.");
+            server.addUserManagerService(service);
+        }
+        @Override
+        public void removedService(ServiceReference<IUserManager> reference, IUserManager service) {
+            logger.info("Removing service IUserManager from netconf SSH. " +
+                    "SSH won't authenticate users until IUserManeger service will be started.");
+            removeUserManagerService();
+        }
+    };
+
 
     @Override
     public void start(BundleContext context) throws Exception {
+        this.context = context;
+        listenForManagerService();
+    }
 
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        if (server != null){
+            server.stop();
+            logger.trace("Netconf SSH bridge is down ...");
+        }
+    }
+    private void startSSHServer() throws Exception {
         logger.trace("Starting netconf SSH  bridge.");
-
-        Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context,EXCEPTION_MESSAGE);
+        Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
         InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
                 EXCEPTION_MESSAGE, true);
 
         if (sshSocketAddressOptional.isPresent()){
-            server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress);
+            AuthProvider authProvider = new AuthProvider(iUserManager);
+            this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
             Thread serverThread = new  Thread(server,"netconf SSH server thread");
             serverThread.setDaemon(true);
             serverThread.start();
@@ -52,13 +96,18 @@ public class NetconfSSHActivator implements BundleActivator{
             throw new Exception("No valid connection configuration for SSH bridge found.");
         }
     }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        if (server != null){
-            logger.trace("Netconf SSH bridge going down ...");
-            server.stop();
-            logger.trace("Netconf SSH bridge is down ...");
+    private void onUserManagerFound(IUserManager userManager) throws Exception{
+        if (server!=null && server.isUp()){
+           server.addUserManagerService(userManager);
+        } else {
+           startSSHServer();
         }
     }
+    private void removeUserManagerService(){
+        this.server.removeUserManagerService();
+    }
+    private void listenForManagerService(){
+        ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer);
+        listenerTracker.open();
+    }
 }
index 72135cc7dcdd39acddfd8d69d826f2683ee9b921..45807a83334f8e655b268c00bcb9c9e163ccf88f 100644 (file)
@@ -12,20 +12,23 @@ import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.util.concurrent.atomic.AtomicLong;
 import javax.annotation.concurrent.ThreadSafe;
+import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.threads.SocketThread;
+import org.opendaylight.controller.usermanager.IUserManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @ThreadSafe
 public class NetconfSSHServer implements Runnable {
 
-    private static boolean acceptMore = true;
     private ServerSocket ss = null;
     private static final Logger logger =  LoggerFactory.getLogger(NetconfSSHServer.class);
     private static final AtomicLong sesssionId = new AtomicLong();
     private final InetSocketAddress clientAddress;
+    private final AuthProvider authProvider;
+    private boolean up = false;
 
-    private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress) throws Exception{
+    private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws Exception{
 
         logger.trace("Creating SSH server socket on port {}",serverPort);
         this.ss = new ServerSocket(serverPort);
@@ -34,27 +37,37 @@ public class NetconfSSHServer implements Runnable {
         }
         logger.trace("Server socket created.");
         this.clientAddress = clientAddress;
-
+        this.authProvider = authProvider;
+        this.up = true;
     }
 
-
-    public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress) throws Exception {
-        return new NetconfSSHServer(serverPort, clientAddress);
+    public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress,AuthProvider authProvider) throws Exception {
+        return new NetconfSSHServer(serverPort, clientAddress,authProvider);
     }
 
     public void stop() throws Exception {
-        acceptMore = false;
+        up = false;
         logger.trace("Closing SSH server socket.");
         ss.close();
         logger.trace("SSH server socket closed.");
     }
 
+    public void removeUserManagerService(){
+        this.authProvider.removeUserManagerService();
+    }
+
+    public void addUserManagerService(IUserManager userManagerService){
+        this.authProvider.addUserManagerService(userManagerService);
+    }
+    public boolean isUp(){
+        return this.up;
+    }
     @Override
     public void run() {
-        while (acceptMore) {
+        while (up) {
             logger.trace("Starting new socket thread.");
             try {
-               SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet());
+               SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(),authProvider);
             } catch (IOException e) {
                 e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
             }
diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java
new file mode 100644 (file)
index 0000000..a73dfdf
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.netconf.ssh.authentication;
+
+import ch.ethz.ssh2.signature.RSAPrivateKey;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
+import org.opendaylight.controller.sal.authorization.AuthResultEnum;
+import org.opendaylight.controller.sal.authorization.UserLevel;
+import org.opendaylight.controller.usermanager.IUserManager;
+import org.opendaylight.controller.usermanager.UserConfig;
+
+public class AuthProvider implements AuthProviderInterface {
+
+    private static RSAPrivateKey hostkey = null;
+    private static IUserManager um;
+    private static final String DEAFULT_USER = "netconf";
+    private static final String DEAFULT_PASSWORD = "netconf";
+
+
+    public AuthProvider(IUserManager ium) throws Exception {
+
+        this.um = ium;
+
+        if (this.um  == null){
+            throw new Exception("No usermanager service available.");
+        }
+
+        List<String> roles = new ArrayList<String>(1);
+        roles.add(UserLevel.SYSTEMADMIN.toString());
+        this.um.addLocalUser(new UserConfig(DEAFULT_USER, DEAFULT_PASSWORD, roles));
+    }
+    @Override
+    public boolean authenticated(String username, String password)  throws Exception {
+        if (this.um  == null){
+            throw new Exception("No usermanager service available.");
+        }
+        AuthResultEnum authResult = this.um.authenticate(username,password);
+        if (authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC)){
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public char[] getPEMAsCharArray() {
+
+        InputStream is = getClass().getResourceAsStream("/RSA.pk");
+        try {
+            return IOUtils.toCharArray(is);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public void removeUserManagerService() {
+        this.um = null;
+    }
+
+    @Override
+    public void addUserManagerService(IUserManager userManagerService) {
+        this.um = userManagerService;
+    }
+
+
+}
diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderInterface.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProviderInterface.java
new file mode 100644 (file)
index 0000000..71f1cc3
--- /dev/null
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.netconf.ssh.authentication;
+
+import org.opendaylight.controller.usermanager.IUserManager;
+
+public interface AuthProviderInterface {
+
+    public boolean authenticated(String username, String password) throws Exception;
+    public char[] getPEMAsCharArray();
+    public void removeUserManagerService();
+    public void addUserManagerService(IUserManager userManagerService);
+}
diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/RSAKey.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/RSAKey.java
deleted file mode 100644 (file)
index b420b33..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.netconf.ssh.authentication;
-
-import ch.ethz.ssh2.signature.RSAPrivateKey;
-
-import java.math.BigInteger;
-
-public class RSAKey implements KeyStoreHandler {
-
-    private static RSAPrivateKey hostkey = null;
-    private static String user = "netconf";
-    private static String password = "netconf";
-    static {
-
-        BigInteger p = new BigInteger("2967886344240998436887630478678331145236162666668503940430852241825039192450179076148979094256007292741704260675085192441025058193581327559331546948442042987131728039318861235625879376246169858586459472691398815098207618446039");    //.BigInteger.probablePrime(N / 2, rnd);
-        BigInteger q = new BigInteger("4311534819291430017572425052029278681302539382618633848168923130451247487970187151403375389974616614405320169278870943605377518341666894603659873284783174749122655429409273983428000534304828056597676444751611433784228298909767"); //BigInteger.probablePrime(N / 2, rnd);
-        BigInteger phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
-
-        BigInteger n = p.multiply(q);
-        BigInteger e = new BigInteger("65537");
-        BigInteger d = e.modInverse(phi);
-
-        hostkey = new RSAPrivateKey(d, e, n);
-    }
-
-    @Override
-    public RSAPrivateKey getPrivateKey() {
-        return hostkey;
-    }
-}
index 15d99a44ee4db4a7b31bd0ee2fd6abd25476079c..e5da03b4cf4c9d97765ce098a8c2761b0eda8e39 100644 (file)
@@ -13,7 +13,7 @@ import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import javax.annotation.concurrent.ThreadSafe;
-import org.opendaylight.controller.netconf.ssh.authentication.RSAKey;
+import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,27 +30,38 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
     private long sessionId;
     private String currentUser;
     private final String remoteAddressWithPort;
+    private final AuthProvider authProvider;
 
 
-    public static void start(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException{
-        Thread netconf_ssh_socket_thread = new Thread(new SocketThread(socket,clientAddress,sessionId));
+    public static void start(Socket socket,
+                             InetSocketAddress clientAddress,
+                             long sessionId,
+                             AuthProvider authProvider) throws IOException{
+        Thread netconf_ssh_socket_thread = new Thread(new SocketThread(socket,clientAddress,sessionId,authProvider));
         netconf_ssh_socket_thread.setDaemon(true);
         netconf_ssh_socket_thread.start();
     }
-    private SocketThread(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException {
+    private SocketThread(Socket socket,
+                         InetSocketAddress clientAddress,
+                         long sessionId,
+                         AuthProvider authProvider) throws IOException {
 
         this.socket = socket;
         this.clientAddress = clientAddress;
         this.sessionId = sessionId;
         this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/","");
+        this.authProvider = authProvider;
 
     }
 
     @Override
     public void run() {
         conn = new ServerConnection(socket);
-        RSAKey keyStore = new RSAKey();
-        conn.setRsaHostKey(keyStore.getPrivateKey());
+        try {
+            conn.setPEMHostKey(authProvider.getPEMAsCharArray(),"netconf");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
         conn.setAuthenticationCallback(this);
         conn.setServerConnectionCallback(this);
         try {
@@ -90,7 +101,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
                                 netconf_ssh_output.start();
 
                             } catch (Throwable t){
-                                logger.error(t.getMessage(),t);
+                                logger.error("SSH bridge couldn't create echo socket",t.getMessage(),t);
 
                                 try {
                                     if (netconf_ssh_input!=null){
@@ -166,13 +177,16 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser
 
     public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
     {
-        if (USER.equals(username) && PASSWORD.equals(password)){
-            currentUser = username;
-            logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
-            return AuthenticationResult.SUCCESS;
-        }
-
 
+        try {
+            if (authProvider.authenticated(username,password)){
+                currentUser = username;
+                logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
+                return AuthenticationResult.SUCCESS;
+            }
+        } catch (Exception e){
+            logger.info("Authentication failed due to :" + e.getLocalizedMessage());
+        }
         return AuthenticationResult.FAILURE;
     }
 
diff --git a/opendaylight/netconf/netconf-ssh/src/main/resources/RSA.pk b/opendaylight/netconf/netconf-ssh/src/main/resources/RSA.pk
new file mode 100644 (file)
index 0000000..c0266c7
--- /dev/null
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAuC9hbEacpewvylI0mwFwjy3Wou2hpr/ncN9BBiFDSaG5yW2k
+3Oy+SCAcFCL+ZKWb6cc6Ch4gUeCwyEHRojZguuhliKtak9YQf6qbvpPLe00842Lx
+iqNAGurMpzizCDsGFq8ChaAkBZQI3TvcHuPoSUWSMJ+K8xHpRyUdVr6g2yEjezKJ
+sTXBtWaeCCh6YUafFujuDJk7fvYcPW7Je5KRBBStIKvxcMW0zB+7eq04deTHwGbJ
+gGjKWilQ72hsDDP3Hbp5CJMAYg1r4GlCmFx3KyHRGztgWgNgaD7nNpKCkTLjtmA6
+b4x7TA+jrzZ6Af2z5TMrI4dv5w1SrxHaZ+ziLQIDAQABAoIBAHTndeGgq/rQf8De
+Do+4CTaHtK0zQSAyu/azbXUzlZ7drKuCEVs8VMY4wzmwwGEnkF+A2YDkgEUX5X0l
+8aYQ97KKoS9u+43MGCrAIhyDeGrpqlT1TzRcy+qJz53v6gq2U/X/3QztiQ+VV078
+mIluxNgE9XYxPaNsYfGLSCTv1+9c8y/hjGVX2kwFK+u4ut0ZZETggNa8UxfaHVDS
+fIJQX9Gm3J3GSUV30fDGMBIUW6ESLc2L8b7u8Mp9TRP39ZeQSuEUjBe8MYKv0Rel
+oEpjZvcnniMTpFbLpndBYn7/AoIiEBvtCN8faVTuRRcvvLcsRm09IctzKQYnMh6M
+6PLKV+ECgYEA8HFRYaKHUzxpzE/fyon82GQbzqFFY0/bbWrfWICMfNbIgshJUie6
+FmH5iUFMfeqaT7v557HFM0GB9FeIeSbvd88YmiBAcRopZ3DfMkDH+DT73yJ+/TKG
+2nrQtdhyuTIs4bwHqeS2BBJYs7PK9R2rratF3l34Tf7mjlvyOgygHdUCgYEAxBo2
+8hEBlAVNcNb1hTYUxe1w1B6675/mFlmw98Xmj9dRYfICXNhahs8tX3/lsBEd+vBu
+fI0oyHaff8m5bPgGzD1ZMybfeROujNrgxaKVk7Ef0FDRRCop4bm18OroFlFAt9l8
+wMp++ToACbdvQvL/mjWMPYlIxhB/YxHswICZZvkCgYAexxKYwdo6sGAGlC7cWT9x
+X5cjowcjyEQZRHXkeUgCbufpvcOM7aLnXJE5nY8yCwbHsBM0MlBA2GDPKylAANjk
+aDEJAZneIHAuWodngl1Wi0m2bU7+ECqs6s2uiU9eH2sZVh1RBQK7kLGkBx6ys6KX
+L3ZZGYRAT6GplWFzRsx0JQKBgCeVlxPD5QqpC1nEumi6YvUVGdpnnZpzL3HBhxxs
+wT612wKnZFyze4qM1X7ahVXGDsQxtkvD/sCAWW/lG13orw6ZL6FIroF1PJ3ILOkY
+CZN3hJF7TtKwpCWhZB2OfWzL2AGEkE8mUP0j/Q/5DCd6f6f0OSvOw3bfq6cm3iB5
+lP2ZAoGAXsRN5TZTX4AQ2xTlrDQ8A5XgcvyWQpJOmEXMTyHV7VaJVzmNWFVAvndK
+5UIq8ALDwB2t7vjmMUW6euvIwqtXiop7G79UOb3e3NhzeyWFGQyBLqCRznGaXQTT
+dlFy73xhukZMhFnj006bjKCYvOPnwuGl3+0fuWil5Rq3jOuY5c8=
+-----END RSA PRIVATE KEY-----
similarity index 53%
rename from opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/ssh/SSHServerTest.java
rename to opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/SSHServerTest.java
index 54bc7bc4b686771279e5542bb7c29e4dabc0d8d2..62396ed87ac1f4db3dcaa7942f676012ab35ade8 100644 (file)
@@ -5,15 +5,14 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.ssh;
+package org.opendaylight.controller.netconf;
 
 import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-import java.io.IOException;
 import java.net.InetSocketAddress;
 import junit.framework.Assert;
-import org.apache.commons.io.IOUtils;
 import org.junit.Test;
+import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
+import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -26,36 +25,37 @@ public class SSHServerTest {
     private static final int PORT = 1830;
     private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 8383);
     private static final Logger logger =  LoggerFactory.getLogger(SSHServerTest.class);
+    private Thread sshServerThread;
+
+
+
 
-//    @Before
     public void startSSHServer() throws Exception{
-            logger.info("Creating SSH server");
-            NetconfSSHServer server = NetconfSSHServer.start(PORT,tcpAddress);
-            Thread sshServerThread = new Thread(server);
-            sshServerThread.setDaemon(true);
-            sshServerThread.start();
-            logger.info("SSH server on");
+        logger.info("Creating SSH server");
+        StubUserManager um = new StubUserManager(USER,PASSWORD);
+        AuthProvider ap = new AuthProvider(um);
+        NetconfSSHServer server = NetconfSSHServer.start(PORT,tcpAddress,ap);
+        sshServerThread = new Thread(server);
+        sshServerThread.setDaemon(true);
+        sshServerThread.start();
+        logger.info("SSH server on");
     }
 
     @Test
     public void connect(){
-        Connection conn = new Connection(HOST,PORT);
-        Assert.assertNotNull(conn);
         try {
+            this.startSSHServer();
+            Connection conn = new Connection(HOST,PORT);
+            Assert.assertNotNull(conn);
             logger.info("connecting to SSH server");
             conn.connect();
             logger.info("authenticating ...");
             boolean isAuthenticated = conn.authenticateWithPassword(USER,PASSWORD);
             Assert.assertTrue(isAuthenticated);
-            logger.info("opening session");
-            Session sess = conn.openSession();
-            logger.info("subsystem netconf");
-            sess.startSubSystem("netconf");
-            sess.getStdin().write("<?xml version=\"1.0\" encoding=\"UTF-8\"?><hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability></capabilities></hello>]]>]]>".getBytes());
-            IOUtils.copy(sess.getStdout(), System.out);
-        } catch (IOException e) {
-            e.printStackTrace();
+        } catch (Exception e) {
+            logger.error("Error while starting SSH server.", e);
         }
+
     }
 
 }
diff --git a/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/StubUserManager.java
new file mode 100644 (file)
index 0000000..4a3a650
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.netconf;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.controller.sal.authorization.AuthResultEnum;
+import org.opendaylight.controller.sal.authorization.UserLevel;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.usermanager.AuthorizationConfig;
+import org.opendaylight.controller.usermanager.ISessionManager;
+import org.opendaylight.controller.usermanager.IUserManager;
+import org.opendaylight.controller.usermanager.ServerConfig;
+import org.opendaylight.controller.usermanager.UserConfig;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.web.context.SecurityContextRepository;
+
+public class StubUserManager implements IUserManager{
+
+
+    private static String user;
+    private static String password;
+
+    public StubUserManager(String user, String password){
+        this.user = user;
+        this.password = password;
+    }
+    @Override
+    public List<String> getUserRoles(String userName) {
+        return null;
+    }
+
+    @Override
+    public AuthResultEnum authenticate(String username, String password) {
+        if (this.user.equals(username) && this.password.equals(password)){
+            return AuthResultEnum.AUTH_ACCEPT_LOC;
+        }
+        return AuthResultEnum.AUTH_REJECT_LOC;
+    }
+
+    @Override
+    public Status addAAAServer(ServerConfig configObject) {
+        return null;
+    }
+
+    @Override
+    public Status removeAAAServer(ServerConfig configObject) {
+        return null;
+    }
+
+    @Override
+    public Status addLocalUser(UserConfig configObject) {
+        return new Status(StatusCode.SUCCESS);
+    }
+
+    @Override
+    public Status modifyLocalUser(UserConfig configObject) {
+        return null;
+    }
+
+    @Override
+    public Status removeLocalUser(UserConfig configObject) {
+        return null;
+    }
+
+    @Override
+    public Status removeLocalUser(String userName) {
+        return null;
+    }
+
+    @Override
+    public Status addAuthInfo(AuthorizationConfig AAAconf) {
+        return null;
+    }
+
+    @Override
+    public Status removeAuthInfo(AuthorizationConfig AAAconf) {
+        return null;
+    }
+
+    @Override
+    public List<AuthorizationConfig> getAuthorizationList() {
+        return null;
+    }
+
+    @Override
+    public Set<String> getAAAProviderNames() {
+        return null;
+    }
+
+    @Override
+    public Status changeLocalUserPassword(String user, String curPassword, String newPassword) {
+        return null;
+    }
+
+    @Override
+    public List<ServerConfig> getAAAServerList() {
+        return null;
+    }
+
+    @Override
+    public List<UserConfig> getLocalUserList() {
+        return null;
+    }
+
+    @Override
+    public Status saveLocalUserList() {
+        return null;
+    }
+
+    @Override
+    public Status saveAAAServerList() {
+        return null;
+    }
+
+    @Override
+    public Status saveAuthorizationList() {
+        return null;
+    }
+
+    @Override
+    public void userLogout(String username) {
+
+    }
+
+    @Override
+    public void userTimedOut(String username) {
+
+    }
+
+    @Override
+    public Map<String, List<String>> getUserLoggedIn() {
+        return null;
+    }
+
+    @Override
+    public String getAccessDate(String user) {
+        return null;
+    }
+
+    @Override
+    public UserLevel getUserLevel(String userName) {
+        return null;
+    }
+
+    @Override
+    public List<UserLevel> getUserLevels(String userName) {
+        return null;
+    }
+
+    @Override
+    public SecurityContextRepository getSecurityContextRepo() {
+        return null;
+    }
+
+    @Override
+    public ISessionManager getSessionManager() {
+        return null;
+    }
+
+    @Override
+    public boolean isRoleInUse(String role) {
+        return false;
+    }
+
+    @Override
+    public String getPassword(String username) {
+        return null;
+    }
+
+    @Override
+    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
+        return null;
+    }
+
+}
index 95d2feb65c482ea564bce7794d61d6360e35f379..4fee930eff7db3c3ecfe5beb0bd113c9acfd5366 100644 (file)
@@ -10,8 +10,9 @@ package org.opendaylight.controller.netconf.util;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.ssl.SslHandler;
 import io.netty.util.Timeout;
 import io.netty.util.Timer;
@@ -19,9 +20,8 @@ import io.netty.util.TimerTask;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GenericFutureListener;
 import io.netty.util.concurrent.Promise;
-
-import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
 import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
 import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
@@ -44,11 +44,14 @@ public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionP
 
     // TODO what time ?
     private static final long INITIAL_HOLDTIMER = 1;
+
     private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSessionNegotiator.class);
+    public static final String NAME_OF_EXCEPTION_HANDLER = "lastExceptionHandler";
 
     protected final P sessionPreferences;
 
     private final SessionListener sessionListener;
+    private Timeout timeout;
 
     /**
      * Possible states for Finite State Machine
@@ -69,7 +72,7 @@ public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionP
     }
 
     @Override
-    protected void startNegotiation() throws Exception {
+    protected void startNegotiation() {
         final Optional<SslHandler> sslHandler = getSslHandler(channel);
         if (sslHandler.isPresent()) {
             Future<Channel> future = sslHandler.get().handshakeFuture();
@@ -94,10 +97,25 @@ public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionP
         final NetconfMessage helloMessage = this.sessionPreferences.getHelloMessage();
         logger.debug("Session negotiation started with hello message {}", XmlUtil.toString(helloMessage.getDocument()));
 
-        sendMessage(helloMessage);
-        changeState(State.OPEN_WAIT);
+        channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ChannelHandler() {
+            @Override
+            public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+            }
+
+            @Override
+            public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+            }
+
+            @Override
+            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+                logger.warn("An exception occurred during negotiation on channel {}", channel.localAddress(), cause);
+                cancelTimeout();
+                negotiationFailed(cause);
+                changeState(State.FAILED);
+            }
+        });
 
-        this.timer.newTimeout(new TimerTask() {
+        timeout = this.timer.newTimeout(new TimerTask() {
             @Override
             public void run(final Timeout timeout) throws Exception {
                 synchronized (this) {
@@ -106,10 +124,20 @@ public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionP
                                 "Session was not established after " + timeout);
                         negotiationFailed(cause);
                         changeState(State.FAILED);
+                    } else if(channel.isOpen()) {
+                        channel.pipeline().remove(NAME_OF_EXCEPTION_HANDLER);
                     }
                 }
             }
         }, INITIAL_HOLDTIMER, TimeUnit.MINUTES);
+
+        sendMessage(helloMessage);
+        changeState(State.OPEN_WAIT);
+    }
+
+    private void cancelTimeout() {
+        if(timeout!=null)
+            timeout.cancel();
     }
 
     private void sendMessage(NetconfMessage message) {
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageAdditionalHeader.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageAdditionalHeader.java
new file mode 100644 (file)
index 0000000..457e226
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.util.messages;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * Additional header can be used with hello message to carry information about
+ * session's connection. Provided information can be reported via netconf
+ * monitoring.
+ * <pre>
+ * It has pattern "[username; host-address:port; transport; session-identifier;]"
+ * username - name of account on a remote
+ * host-address - client's IP address
+ * port - port number
+ * transport - tcp, ssh
+ * session-identifier - persister, client
+ * Session-identifier is optional, others mandatory.
+ * </pre>
+ */
+public class NetconfMessageAdditionalHeader {
+
+    private static final String SC = ";";
+
+    public static String toString(String userName, String hostAddress, String port, String transport,
+            Optional<String> sessionIdentifier) {
+        Preconditions.checkNotNull(userName);
+        Preconditions.checkNotNull(hostAddress);
+        Preconditions.checkNotNull(port);
+        Preconditions.checkNotNull(transport);
+        String identifier = sessionIdentifier.isPresent() ? sessionIdentifier.get() : "";
+        return "[" + userName + SC + hostAddress + ":" + port + SC + transport + SC + identifier + SC + "]"
+                + System.lineSeparator();
+    }
+}
index 891d40cf74fa520be681aa73109765424f5ab8e8..526708ab580238e34ba26a1c70a1d89289571ca6 100644 (file)
@@ -8,9 +8,12 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+
 import org.opendaylight.controller.netconf.api.NetconfDeserializerException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -24,11 +27,9 @@ import org.w3c.dom.Comment;
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.List;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
 
 /**
  * NetconfMessageFactory for (de)serializing DOM documents.
@@ -114,7 +115,14 @@ public final class NetconfMessageFactory implements ProtocolMessageFactory<Netco
             Comment comment = netconfMessage.getDocument().createComment("clientId:" + clientId.get());
             netconfMessage.getDocument().appendChild(comment);
         }
-        final ByteBuffer msgBytes = Charsets.UTF_8.encode(xmlToString(netconfMessage.getDocument()));
+        ByteBuffer msgBytes;
+        if(netconfMessage.getAdditionalHeader().isPresent()) {
+            String header = netconfMessage.getAdditionalHeader().get();
+            logger.trace("Header of netconf message parsed \n{}", header);
+            msgBytes = Charsets.UTF_8.encode(header + xmlToString(netconfMessage.getDocument()));
+        } else {
+            msgBytes = Charsets.UTF_8.encode(xmlToString(netconfMessage.getDocument()));
+        }
         String content = xmlToString(netconfMessage.getDocument());
 
         logger.trace("Putting message \n{}", content);
index 52b7370e35fa51d97806a66062a280ca595ff80a..c4b146722004d6792303b0f0a3a423d2d89f91e6 100644 (file)
@@ -31,6 +31,7 @@
         <module>../../third-party/com.siemens.ct.exi</module>
         <module>netconf-monitoring</module>
         <module>ietf-netconf-monitoring</module>
+        <module>ietf-netconf-monitoring-extension</module>
     </modules>
 
     <profiles>
                 <artifactId>netconf-ssh</artifactId>
                 <version>${netconf.version}</version>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>netconf-ssh</artifactId>
+                <version>${netconf.version}</version>
+                <type>test-jar</type>
+            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>netconf-mapping-api</artifactId>
index e97a562620771ddf8d1a9bab0e873a89a58dc0b2..e164abaf95c0ccd3adb07e3bb55d32b8f9f22ec8 100644 (file)
@@ -46,9 +46,12 @@ public class NorthboundApplication extends Application {
     public NorthboundApplication() {
         _singletons = new HashSet<Object>();
         _singletons.add(new ContextResolver<JAXBContext>() {
-            JAXBContext jaxbContext = newJAXBContext();
+            JAXBContext jaxbContext;
             @Override
-            public JAXBContext getContext(Class<?> type) {
+            public synchronized JAXBContext getContext(Class<?> type) {
+                if (jaxbContext == null) {
+                    jaxbContext = newJAXBContext();
+                }
                 return jaxbContext;
             }
 
index 2300b8da400d6f15f46812f868c3e262b30b32df..7e0d465256fa63b5af631ce76e4fb078ef257c28 100644 (file)
@@ -25,7 +25,7 @@
           </init-param>
           <init-param>
             <param-name>cors.allowed.methods</param-name>
-            <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
+            <param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE</param-value>
           </init-param>
           <init-param>
             <param-name>cors.allowed.headers</param-name>
index bb5681b2dff0dbc988407885fa6b65599617617a..4e4e867fec637a30c3a0a26eedb128becbda84c7 100644 (file)
@@ -298,18 +298,18 @@ public class TopologyServiceShim implements IDiscoveryListener,
             // Compare bandwidth usage
             Long switchId = (Long) connector.getNode().getID();
             Short port = (Short) connector.getID();
-            float rate = statsMgr.getTransmitRate(switchId, port);
-            if (rate > bwThresholdFactor * bw) {
-                if (!connectorsOverUtilized.contains(connector)) {
-                    connectorsOverUtilized.add(connector);
-                    this.bwUtilNotifyQ.add(new UtilizationUpdate(connector,
-                            UpdateType.ADDED));
-                }
-            } else {
-                if (connectorsOverUtilized.contains(connector)) {
-                    connectorsOverUtilized.remove(connector);
-                    this.bwUtilNotifyQ.add(new UtilizationUpdate(connector,
-                            UpdateType.REMOVED));
+            if (statsMgr != null) {
+                float rate = statsMgr.getTransmitRate(switchId, port);
+                if (rate > bwThresholdFactor * bw) {
+                    if (!connectorsOverUtilized.contains(connector)) {
+                        connectorsOverUtilized.add(connector);
+                        this.bwUtilNotifyQ.add(new UtilizationUpdate(connector, UpdateType.ADDED));
+                    }
+                } else {
+                    if (connectorsOverUtilized.contains(connector)) {
+                        connectorsOverUtilized.remove(connector);
+                        this.bwUtilNotifyQ.add(new UtilizationUpdate(connector, UpdateType.REMOVED));
+                    }
                 }
             }
         }
index 0a00cda9afccd185a30785ab5296f3505ac3413c..56df8e26bd094b82bdd8d6ddb89cec4ab249e7a9 100644 (file)
@@ -161,15 +161,11 @@ public class Subnet implements Cloneable, Serializable {
         }
         InetAddress thisPrefix = getPrefixForAddress(this.networkAddress);
         InetAddress otherPrefix = getPrefixForAddress(ip);
-        if ((thisPrefix == null) || (otherPrefix == null)) {
-            return false;
-        }
-        if (thisPrefix.equals(otherPrefix)) {
-            return true;
-        }
-        else {
-            return false;
+        boolean isSubnetOf = true;
+        if (((thisPrefix == null) || (otherPrefix == null)) || (!thisPrefix.equals(otherPrefix)) ) {
+            isSubnetOf = false;
         }
+        return isSubnetOf;
     }
 
     public short getVlan() {
@@ -244,10 +240,7 @@ public class Subnet implements Cloneable, Serializable {
         if (p == null) {
             return false;
         }
-        if (this.isFlatLayer2()) {
-            return true;
-        }
-        return this.nodeConnectors.contains(p);
+        return isFlatLayer2() || nodeConnectors.contains(p);
     }
 
     public boolean isMutualExclusive(Subnet otherSubnet) {
index 41a1f1ab06d978a350002d7e52c5d0e5c755bbfd..8b6a149917602992c8f4360cceed2cc1c70cb54a 100644 (file)
@@ -8,8 +8,13 @@
 
 package org.opendaylight.controller.switchmanager;
 
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import java.net.Inet6Address;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -26,19 +31,19 @@ public class SubnetTest {
     public void testSubnet() throws Exception {
         InetAddress ipaddr = InetAddress.getByName("100.0.0.1");
         Subnet subnet = new Subnet(ipaddr, (short) 24, (short) 5);
-        Assert.assertTrue(subnet.equals(subnet));
-        Assert.assertFalse(subnet.equals(null));
-        Assert.assertFalse(subnet.equals(ipaddr));
+        assertTrue(subnet.equals(subnet));
+        assertFalse(subnet.equals(null));
+        assertFalse(subnet.equals(ipaddr));
         Subnet subnet2 = new Subnet(ipaddr, (short) 24, (short) 5);
         Inet6Address ipv6 = (Inet6Address) Inet6Address
                 .getByName("1111::2222:3333:4444:5555:6666");
         Subnet subnet3 = new Subnet(ipv6, (short) 24, (short) 5);
-        Assert.assertTrue(subnet.equals(subnet2));
-        Assert.assertFalse(subnet.isMutualExclusive(subnet2));
-        Assert.assertTrue(subnet.isMutualExclusive(subnet3));
+        assertTrue(subnet.equals(subnet2));
+        assertFalse(subnet.isMutualExclusive(subnet2));
+        assertTrue(subnet.isMutualExclusive(subnet3));
         InetAddress subnetAddr = InetAddress.getByName("200.0.0.100");
 
-        Assert.assertTrue(subnet.isFlatLayer2() == true);
+        assertTrue(subnet.isFlatLayer2() == true);
 
         Set<NodeConnector> ncSet = new HashSet<NodeConnector>();
         Node node = NodeCreator.createOFNode(((long) 10));
@@ -53,10 +58,10 @@ public class SubnetTest {
         ncSet.add(nc1);
         ncSet.add(nc2);
 
-        Assert.assertTrue(subnet.hasNodeConnector(nc0));
-        Assert.assertFalse(subnet.hasNodeConnector(null));
+        assertTrue(subnet.hasNodeConnector(nc0));
+        assertFalse(subnet.hasNodeConnector(null));
         subnet.addNodeConnectors(ncSet);
-        Assert.assertTrue(subnet.hasNodeConnector(nc0));
+        assertTrue(subnet.hasNodeConnector(nc0));
 
         Set<NodeConnector> resultncSet = subnet.getNodeConnectors();
         Assert.assertEquals(resultncSet, ncSet);
@@ -69,24 +74,61 @@ public class SubnetTest {
         Set<NodeConnector> ncSet2 = new HashSet<NodeConnector>();
         ncSet2.add(nc0);
         subnet.deleteNodeConnectors(ncSet2);
-        Assert.assertFalse(subnet.getNodeConnectors().contains(nc0));
-        Assert.assertFalse(subnet.hasNodeConnector(nc0));
-        Assert.assertTrue(subnet.getNodeConnectors().contains(nc1));
-        Assert.assertTrue(subnet.getNodeConnectors().contains(nc2));
+        assertFalse(subnet.getNodeConnectors().contains(nc0));
+        assertFalse(subnet.hasNodeConnector(nc0));
+        assertTrue(subnet.getNodeConnectors().contains(nc1));
+        assertTrue(subnet.getNodeConnectors().contains(nc2));
 
         subnet.deleteNodeConnectors(ncSet2);
 
         subnet.setNetworkAddress(subnetAddr);
-        Assert.assertTrue(subnet.isMutualExclusive(subnet2));
-        Assert.assertTrue(subnet.getNetworkAddress().equals(subnetAddr));
+        assertTrue(subnet.isMutualExclusive(subnet2));
+        assertTrue(subnet.getNetworkAddress().equals(subnetAddr));
 
         subnet.setSubnetMaskLength((short) 16);
-        Assert.assertTrue(subnet.getSubnetMaskLength() == 16);
+        assertTrue(subnet.getSubnetMaskLength() == 16);
 
         subnet.setVlan((short) 100);
-        Assert.assertTrue(subnet.getVlan() == 100);
+        assertTrue(subnet.getVlan() == 100);
+
+        assertTrue(subnet.isFlatLayer2() == false);
+    }
+
+    @Test
+    public void checkIsSubnetOfComparisonMatch() {
+        String host = "10.0.0.1";
+        InetAddress ipAddrForSubnetComparison = null;
+        try {
+            ipAddrForSubnetComparison = InetAddress.getByName(host);
+        } catch (UnknownHostException e) {
+            fail("Failed to create InetAddress object for" + host);
+        }
+        SubnetConfig subnetConf = new SubnetConfig("subnet", "10.0.0.254/24",null);
+        Subnet subnet = new Subnet(subnetConf);
+        assertTrue(subnet.isSubnetOf(ipAddrForSubnetComparison));
+    }
 
-        Assert.assertTrue(subnet.isFlatLayer2() == false);
+    @Test
+    public void checkIsSubnetOfComparisonNoMatch() {
+        String host = "100.0.0.1";
+        InetAddress ipAddrForSubnetComparison = null;
+        try {
+            ipAddrForSubnetComparison = InetAddress.getByName(host);
+        } catch (UnknownHostException e) {
+            fail("Failed to create InetAddress object for" + host);
+        }
+        SubnetConfig subnetConf = new SubnetConfig("subnet", "10.0.0.254/24",null);
+        Subnet subnet = new Subnet(subnetConf);
+        assertFalse(subnet.isSubnetOf(ipAddrForSubnetComparison));
+    }
+
+    @Test
+    public void checkIsSubnetOfComparisonIpEmpty() {
+        SubnetConfig subnetConf = new SubnetConfig("subnet", "10.0.0.254/24",null);
+        Subnet subnet = new Subnet(subnetConf);
+        assertFalse(subnet.isSubnetOf(null));
     }
 
+
+
 }
index 41c783618dfdee88cadd88e2cc6d84b8e6dd05ea..b5d0a48c28709e575f13646971e00ab1ddbc3ea0 100644 (file)
@@ -319,7 +319,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
     @Override
     public SubnetConfig getSubnetConfig(String subnet) {
         // if there are no subnets, return the default subnet
-        if(subnetsConfigList.size() == 0 && subnet == DEFAULT_SUBNET_NAME){
+        if(subnetsConfigList.isEmpty() && subnet.equalsIgnoreCase(DEFAULT_SUBNET_NAME)){
             return DEFAULT_SUBNETCONFIG;
         }else{
             return subnetsConfigList.get(subnet);
@@ -428,11 +428,11 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
     }
 
     private Status semanticCheck(SubnetConfig conf) {
-        Subnet newSubnet = new Subnet(conf);
         Set<InetAddress> IPs = subnets.keySet();
         if (IPs == null) {
             return new Status(StatusCode.SUCCESS);
         }
+        Subnet newSubnet = new Subnet(conf);
         for (InetAddress i : IPs) {
             Subnet existingSubnet = subnets.get(i);
             if ((existingSubnet != null) && !existingSubnet.isMutualExclusive(newSubnet)) {
@@ -462,7 +462,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
                 return status;
             }
         } else {
-            if (conf.getName().equals(DEFAULT_SUBNET_NAME)) {
+            if (conf.getName().equalsIgnoreCase(DEFAULT_SUBNET_NAME)) {
                 return new Status(StatusCode.NOTALLOWED, "The specified subnet gateway cannot be removed");
             }
         }
@@ -506,7 +506,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
 
     @Override
     public Status removeSubnet(String name) {
-        if (name.equals(DEFAULT_SUBNET_NAME)) {
+        if (name.equalsIgnoreCase(DEFAULT_SUBNET_NAME)) {
             return new Status(StatusCode.NOTALLOWED, "The specified subnet gateway cannot be removed");
         }
         SubnetConfig conf = subnetsConfigList.get(name);
@@ -691,12 +691,9 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
             return DEFAULT_SUBNET;
         }
 
-        Subnet sub;
-        Set<InetAddress> indices = subnets.keySet();
-        for (InetAddress i : indices) {
-            sub = subnets.get(i);
-            if (sub.isSubnetOf(networkAddress)) {
-                return sub;
+        for(Map.Entry<InetAddress,Subnet> subnetEntry : subnets.entrySet()) {
+            if(subnetEntry.getValue().isSubnetOf(networkAddress)) {
+                return subnetEntry.getValue();
             }
         }
         return null;
index 0c14dea38a4a9ff69993d1e6a88503ceb5db0792..83532a1012f6a9431cd4f75a3f1b201e653ec395 100644 (file)
@@ -9,10 +9,11 @@
 package org.opendaylight.controller.usermanager;
 
 import java.io.Serializable;
-import java.nio.charset.Charset;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -24,6 +25,7 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import org.opendaylight.controller.sal.authorization.AuthResultEnum;
+import org.opendaylight.controller.sal.packet.BitBufferHelper;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
@@ -46,6 +48,7 @@ public class UserConfig implements Serializable {
     protected static final String PASSWORD_REGEX = "(?=.*[^a-zA-Z0-9])(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,256}$";
     private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern.compile("([/\\s\\.\\?#%;\\\\]+)");
     private static MessageDigest oneWayFunction;
+    private static SecureRandom randomGenerator;
 
     static {
         try {
@@ -54,6 +57,7 @@ public class UserConfig implements Serializable {
             log.error(String.format("Implementation of %s digest algorithm not found: %s", DIGEST_ALGORITHM,
                     e.getMessage()));
         }
+        UserConfig.randomGenerator = new SecureRandom(BitBufferHelper.toByteArray(System.currentTimeMillis()));
     }
 
     /**
@@ -81,6 +85,8 @@ public class UserConfig implements Serializable {
     @XmlElement
     private String password;
 
+    private byte[] salt;
+
 
 
     public UserConfig() {
@@ -102,11 +108,19 @@ public class UserConfig implements Serializable {
         /*
          * Password validation to be done on clear text password. If fails, mark
          * the password with a well known label, so that object validation can
-         * report the proper error. Only if password is a valid one, hash it.
+         * report the proper error. Only if password is a valid one, generate
+         * salt, concatenate it with clear text password and hash the
+         * resulting string. Hash result is going to be our stored password.
          */
-        this.password = (validatePassword(password).isSuccess()) ? hash(password) : BAD_PASSWORD;
+        if (validateClearTextPassword(password).isSuccess()) {
+            this.salt = BitBufferHelper.toByteArray(randomGenerator.nextLong());
+            this.password = hash(salt, password);
+        } else {
+            this.salt = null;
+            this.password = BAD_PASSWORD;
+        }
 
-        this.roles = (roles == null) ? new ArrayList<String>() : new ArrayList<String>(roles);
+        this.roles = (roles == null) ? Collections.<String>emptyList() : new ArrayList<String>(roles);
     }
 
     public String getUser() {
@@ -176,6 +190,7 @@ public class UserConfig implements Serializable {
     public Status validate() {
         Status validCheck = validateUsername();
         if (validCheck.isSuccess()) {
+            // Password validation was run at object construction time
             validCheck = (!password.equals(BAD_PASSWORD)) ? new Status(StatusCode.SUCCESS) : new Status(
                     StatusCode.BADREQUEST,
                     "Password should be 8 to 256 characters long, contain both upper and lower case letters, "
@@ -203,7 +218,7 @@ public class UserConfig implements Serializable {
         return new Status(StatusCode.SUCCESS);
     }
 
-    private Status validatePassword(String password) {
+    private Status validateClearTextPassword(String password) {
         if (password == null || password.isEmpty()) {
             return new Status(StatusCode.BADREQUEST, "Password cannot be empty");
         }
@@ -227,14 +242,14 @@ public class UserConfig implements Serializable {
 
         // To make any changes to a user configured profile, current password
         // must always be provided
-        if (!this.password.equals(hash(currentPassword))) {
+        if (!this.password.equals(hash(this.salt, currentPassword))) {
             return new Status(StatusCode.BADREQUEST, "Current password is incorrect");
         }
 
         // Create a new object with the proposed modifications
         UserConfig proposed = new UserConfig();
         proposed.user = this.user;
-        proposed.password = (newPassword == null)? this.password : hash(newPassword);
+        proposed.password = (newPassword == null)? this.password : hash(this.salt, newPassword);
         proposed.roles = (newRoles == null)? this.roles : newRoles;
 
         // Validate it
@@ -251,9 +266,9 @@ public class UserConfig implements Serializable {
         return status;
     }
 
-    public AuthResponse authenticate(String clearTextPass) {
+    public AuthResponse authenticate(String clearTextPassword) {
         AuthResponse locResponse = new AuthResponse();
-        if (password.equals(hash(clearTextPass))) {
+        if (password.equals(hash(this.salt, clearTextPassword))) {
             locResponse.setStatus(AuthResultEnum.AUTH_ACCEPT_LOC);
             locResponse.addData(getRolesString());
         } else {
@@ -275,12 +290,32 @@ public class UserConfig implements Serializable {
         return buffer.toString();
     }
 
-    public static String hash(String message) {
+    private static byte[] concatenate(byte[] salt, String password) {
+        byte[] messageArray = password.getBytes();
+        byte[] concatenation = new byte[salt.length + password.length()];
+        System.arraycopy(salt, 0, concatenation, 0, salt.length);
+        System.arraycopy(messageArray, 0, concatenation, salt.length, messageArray.length);
+        return concatenation;
+    }
+
+    private static String hash(byte[] salt, String message) {
         if (message == null) {
+            log.warn("Password hash requested but empty or no password provided");
             return message;
         }
+        if (salt == null || salt.length == 0) {
+            log.warn("Password hash requested but empty or no salt provided");
+            return message;
+        }
+
+        // Concatenate salt and password
+        byte[] messageArray = message.getBytes();
+        byte[] concatenation = new byte[salt.length + message.length()];
+        System.arraycopy(salt, 0, concatenation, 0, salt.length);
+        System.arraycopy(messageArray, 0, concatenation, salt.length, messageArray.length);
+
         UserConfig.oneWayFunction.reset();
-        return HexEncode.bytesToHexString(UserConfig.oneWayFunction.digest(message.getBytes(Charset.defaultCharset())));
+        return HexEncode.bytesToHexString(UserConfig.oneWayFunction.digest(concatenate(salt, message)));
     }
 
     /**
@@ -299,7 +334,8 @@ public class UserConfig implements Serializable {
     public static UserConfig getUncheckedUserConfig(String userName, String password, List<String> roles) {
         UserConfig config = new UserConfig();
         config.user = userName;
-        config.password = hash(password);
+        config.salt = BitBufferHelper.toByteArray(randomGenerator.nextLong());
+        config.password = hash(config.salt, password);
         config.roles = roles;
         return config;
     }
index d225e5c76014bfc2e647ceeb0fbff756de4065ba..8fc7f07df1db2fc3283057c1f55caed85799d604 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.controller.usermanager;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -71,12 +70,12 @@ public class AuthorizationUserConfigTest {
                 .isSuccess());
 
         // New Password = null, No change in password
-        assertTrue(userConfig.getPassword().equals(UserConfig.hash("ciscocisco")));
+        assertTrue(userConfig.authenticate("ciscocisco").getStatus().equals(AuthResultEnum.AUTH_ACCEPT_LOC));
 
         // Password changed successfully, no change in user role
         assertTrue(userConfig.update("ciscocisco", "cisco123", roles)
                 .isSuccess());
-        assertTrue(userConfig.getPassword().equals(UserConfig.hash("cisco123")));
+        assertTrue(userConfig.authenticate("cisco123").getStatus().equals(AuthResultEnum.AUTH_ACCEPT_LOC));
         assertTrue(userConfig.getRoles().get(0).equals(
                 UserLevel.NETWORKOPERATOR.toString()));
 
@@ -85,14 +84,14 @@ public class AuthorizationUserConfigTest {
         roles.add(UserLevel.SYSTEMADMIN.toString());
         assertTrue(userConfig.update("cisco123", "cisco123", roles)
                 .isSuccess());
-        assertTrue(userConfig.getPassword().equals(UserConfig.hash("cisco123")));
+        assertTrue(userConfig.authenticate("cisco123").getStatus().equals(AuthResultEnum.AUTH_ACCEPT_LOC));
         assertTrue(userConfig.getRoles().get(0)
                 .equals(UserLevel.SYSTEMADMIN.toString()));
 
         // Password and role changed successfully
         assertTrue(userConfig.update("cisco123", "ciscocisco", roles)
                 .isSuccess());
-        assertTrue(userConfig.getPassword().equals(UserConfig.hash("ciscocisco")));
+        assertTrue(userConfig.authenticate("ciscocisco").getStatus().equals(AuthResultEnum.AUTH_ACCEPT_LOC));
         assertTrue(userConfig.getRoles().get(0)
                 .equals(UserLevel.SYSTEMADMIN.toString()));
 
@@ -104,14 +103,6 @@ public class AuthorizationUserConfigTest {
         assertTrue(authresp.getStatus().equals(AuthResultEnum.AUTH_ACCEPT_LOC));
         authresp = userConfig.authenticate("wrongPassword");
         assertTrue(authresp.getStatus().equals(AuthResultEnum.AUTH_REJECT_LOC));
-
-        // test equals()
-        roles.clear();
-        roles.add(UserLevel.NETWORKOPERATOR.toString());
-        userConfig = new UserConfig("uname", "ciscocisco", roles);
-        assertEquals(userConfig, userConfig);
-        UserConfig userConfig2 = new UserConfig("uname", "ciscocisco", roles);
-        assertEquals(userConfig, userConfig2);
     }
 
     @Test
index 4eedf7eda99f42bb70d011dd7daba2d81d2d4ae0..dcdc2f6d50447e942fe868c22bc69bc732bfe248 100644 (file)
               org.opendaylight.controller.usermanager
             </Import-Package>
             <Export-Package>
-<!--
+               <!--
               org.opendaylight.controller.usermanager,
               org.opendaylight.controller.usermanager.internal
- -->
             -->
              </Export-Package>
             <Bundle-Activator>
               org.opendaylight.controller.usermanager.internal.Activator
index 094562fac07252b182e601774e79209d0a473e20..6b4cfa00253ef4f36026a51f639fba6af02ed4b6 100644 (file)
@@ -390,8 +390,8 @@ one.f.flows = {
                     $tr = $(tr);
                     $span = $("td span", $tr);
                     var flowstatus = $span.data("flowstatus");
-                    if($span.data("installinhw") != null) {
-                        var installInHw = $span.data("installinhw").toString();
+                    if($span.data("installInHw") != null) {
+                        var installInHw = $span.data("installInHw").toString();
                         if(installInHw == "true" && flowstatus == "Success") {
                             $tr.addClass("success");
                         } else {