Initial code drop of netconf protocol implementation 76/1776/9
authorMaros Marsalek <mmarsale@cisco.com>
Tue, 8 Oct 2013 16:26:35 +0000 (18:26 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 14 Oct 2013 14:45:34 +0000 (14:45 +0000)
This implementation is based on infrastructure provided by the framework artifact
and contains server as well as client side code.

Netconf subsystem structure:
Netconf-api:
Api definition for client and server.

Netconf-impl:
Netconf server implementation. Server handles basic communication
and delegates handling of rpcs to an implementation of netconf-mapping-api.

Netconf-mapping-api:
Api definition for pluggable rpcs handler. Implementations of this api
are plugged dynamically into netconf-impl using OSGi apis.

Config-netconf-connector:
Implementation of netconf-mapping-api that handles netconf rpcs and delegates
requests to configuration subsystem

Netconf-util:
Utility classes used by client and server code.

Netconf-client:
Netconf client implementation.

Netconf-it:
Integration tests for netconf. These tests verify correct cooperation of netconf server,
config-netconf-connector, config subsystem and netconf client.

Config-persister-api:
Api definition for config persister. Config persister is a component that is responsible
for storing configuration snapshots after every change to the configuration via netconf rpcs.
(Pushed to config-subsystem)

Config-persister-impl:
Implementation of config persister that receives notifications from netconf-impl about changes
to the configuration and uses pluggable adapters to store received snapshots.

Config-persister-file-adapter:
Implementation of config persister adapter that stores and restores config snapshots from a file.
(Pushed to config-subsystem)

In order to run netconf in OSGi, some configuration issues had to be resolved
in config-subsystem bundles.

Change-Id: I8e0421c924b0714a4d49962c4bb5ca01ef68ac78
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
275 files changed:
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-api/pom.xml
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/stat/ConfigProvider.java [new file with mode: 0644]
opendaylight/config/config-persister-api/pom.xml [new file with mode: 0644]
opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java [new file with mode: 0644]
opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/storage/StorageAdapter.java [new file with mode: 0644]
opendaylight/config/config-persister-file-adapter/pom.xml [new file with mode: 0644]
opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java [new file with mode: 0644]
opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java [new file with mode: 0644]
opendaylight/config/pom.xml
opendaylight/config/yang-jmx-generator-plugin/pom.xml
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGenerator.java
opendaylight/config/yang-jmx-generator/pom.xml
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java
opendaylight/config/yang-store-impl/pom.xml
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked1.txt [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked2.txt [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked3.txt [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked4.txt [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked5.txt [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/databaseinteractions/jolokia_config_bean_response.txt [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/databaseinteractions/jolokia_lookupConfigBeans.txt [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_commit.xml [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_lock_candidate.xml [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_lock_running.xml [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_modify_candidate.xml [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_unlock_candidate.xml [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_unlock_running.xml [new file with mode: 0644]
opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/server_error_missing_attribute.xml [new file with mode: 0644]
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml
opendaylight/netconf/config-netconf-connector/pom.xml [new file with mode: 0755]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/AbstractAttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ArrayAttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/AttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/CompositeAttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/SimpleAttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/AbstractAttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ArrayAttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/AttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/SimpleAttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ArrayAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/AttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/CompositeAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectNameAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/RuntimeBeanEntryWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementResolved.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/Rpcs.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Datastore.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/NoneEditConfigStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/RemoveEditConfigStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/CandidateDatastoreQueryStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/DatastoreQueryStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/RunningDatastoreQueryStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpcElementResolved.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceFactoryImpl.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreServiceTracker.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/util/Util.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/ServiceTrackerTest.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategyTest.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/pom.xml [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/NoOpStorageAdapter.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PersisterImpl.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/Util.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/client_hello.xml [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/commit.xml [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/editConfig.xml [new file with mode: 0644]
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/PersisterImplTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDeserializerException.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDocumentedException.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfMessage.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfServerSessionPreferences.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSessionListener.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSessionPreferences.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfTerminationReason.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/jmx/CommitJMXNotification.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/jmx/DefaultCommitOperationMXBean.java [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/jmx/NetconfJMXNotification.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionListener.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiator.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SessionIdProvider.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/CapabilityProvider.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTracker.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshot.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/DeserializerExceptionHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/NetconfUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/resources/getConfig_candidate.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/MessageHeaderTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/MessageParserTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/chunked1.txt [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/chunked2.txt [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/chunked3.txt [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/chunked4.txt [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/chunked5.txt [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/listener/databaseinteractions/jolokia_config_bean_response.txt [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/listener/databaseinteractions/jolokia_lookupConfigBeans.txt [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/notused/client_commit.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/notused/client_lock_candidate.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/notused/client_lock_running.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/notused/client_modify_candidate.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/notused/client_unlock_candidate.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/notused/client_unlock_running.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/org/opendaylight/controller/netconf/impl/notused/server_error_missing_attribute.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/input.json [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/input.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/inputList.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/inputMap.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/inputMultiple.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/inputSetter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/inputSetterList.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/inputSetterMap.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/testConfigs/map.json [new file with mode: 0644]
opendaylight/netconf/netconf-it/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-it/src/test/resources/keystore.jks [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/Capability.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilterChain.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/pom.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/FramingMechanism.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/HardcodedNamespaceResolver.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfValidator.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/resources/org/opendaylight/controller/netconf/util/messages/server_error.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/resources/rfc4741.xsd [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/resources/xml.xsd [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/client_hello.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/client_hello_with_auth.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/close-session.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/closeSession.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/commit.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/communicationError/testClientSendsRpcReply_expectedResponse.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/communicationError/testClientSendsRpcReply_request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/communicationError/testRpcWithoutMessageId_expectedResponse.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/communicationError/testRpcWithoutMessageId_request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/databaseInteraction/client_get_request_ConfigRegistry.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/databaseInteraction/confg_subsystem_expected_reply.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/discardChanges.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_expectedResult.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_threadfactory.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_yang-test.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_remove.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_replace_default.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_replace_default_ex.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_replace_module.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_replace_module_ex.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/edit_config.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/get.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/getConfig.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/getConfig_candidate.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/get_schema-no-version.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/get_schema.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/handshake/client_hello_with_session_id.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/handshake/client_hello_with_wrong_namespace.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/mount/editConfig_merge_threadfactory.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/mount/mount12002.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/mount/mount12003.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/mount/unmount12002.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpc.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/threadpool-edit-config.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised1.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised2.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised3.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised4.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised5.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised6.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/validate.xml [new file with mode: 0644]
opendaylight/netconf/pom.xml [new file with mode: 0644]
pom.xml

index 223abcd..296250d 100644 (file)
@@ -54,7 +54,7 @@
     <geminiweb.version>2.2.0.RELEASE</geminiweb.version>
     <checkstyle.version>2.10</checkstyle.version>
     <testvm.argLine>-Xmx1024m -XX:MaxPermSize=256m</testvm.argLine>
-    <yang.version>0.5.8</yang.version>
+    <yang.version>0.5.9-SNAPSHOT</yang.version>
     <guava.version>14.0.1</guava.version>
     <osgi.core.version>5.0.0</osgi.core.version>
     <ietf-inet-types.version>2010.09.24.1</ietf-inet-types.version>
@@ -70,7 +70,8 @@
     <bundle.plugin.version>2.3.7</bundle.plugin.version>
     <junit.version>4.8.1</junit.version>
     <bgpcep.version>0.2.0-SNAPSHOT</bgpcep.version>
-    <yangtools.version>0.5.8</yangtools.version>
+    <yangtools.version>0.5.9-SNAPSHOT</yangtools.version>
+    <yangtools.binding.version>0.6.0-SNAPSHOT</yangtools.binding.version>
     <!--versions for bits of the controller -->
     <controller.version>0.4.1-SNAPSHOT</controller.version>
     <config.version>0.2.1-SNAPSHOT</config.version>
        <version>${bgpcep.version}</version>
       </dependency>
 
+        <dependency>
+            <groupId>org.opendaylight.bgpcep</groupId>
+            <artifactId>framework</artifactId>
+            <version>${bgpcep.version}</version>
+        </dependency>
+
+        <!--Netty-->
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-handler</artifactId>
+            <version>4.0.9.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec</artifactId>
+            <version>4.0.9.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-buffer</artifactId>
+            <version>4.0.9.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport</artifactId>
+            <version>4.0.9.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-common</artifactId>
+            <version>4.0.9.Final</version>
+        </dependency>
+
       <!-- yangtools dependencies -->
       <dependency>
        <groupId>org.opendaylight.yangtools</groupId>
        <artifactId>yang-binding</artifactId>
-       <version>${yangtools.version}</version>
+       <version>${yangtools.binding.version}</version>
       </dependency>
       <dependency>
        <groupId>org.opendaylight.yangtools</groupId>
index 858a802..4dbc31f 100644 (file)
             <artifactId>concepts</artifactId>
             <version>0.2.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
@@ -34,7 +38,8 @@
                     <instructions>
                         <Import-Package>
                             javax.management,
-                            org.opendaylight.protocol.concepts
+                            org.opendaylight.protocol.concepts,
+                            org.osgi.framework,
                         </Import-Package>
                         <Export-Package>
                             org.opendaylight.controller.config.api,
@@ -43,6 +48,7 @@
                             org.opendaylight.controller.config.api.jmx,
                             org.opendaylight.controller.config.api.jmx.constants,
                             org.opendaylight.controller.config.api.runtime,
+                            org.opendaylight.controller.config.stat,
                         </Export-Package>
                     </instructions>
                 </configuration>
diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/stat/ConfigProvider.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/stat/ConfigProvider.java
new file mode 100644 (file)
index 0000000..3a81061
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.stat;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * Subset of {@link org.osgi.framework.BundleContext}
+ */
+public interface ConfigProvider {
+    /**
+     * Returns the value of the specified property. If the key is not found in
+     * the Framework properties, the system properties are then searched. The
+     * method returns {@code null} if the property is not found.
+     *
+     * <p>
+     * All bundles must have permission to read properties whose names start
+     * with &quot;org.osgi.&quot;.
+     *
+     * @param key
+     *            The name of the requested property.
+     * @return The value of the requested property, or {@code null} if the
+     *         property is undefined.
+     * @throws SecurityException
+     *             If the caller does not have the appropriate
+     *             {@code PropertyPermission} to read the property, and the Java
+     *             Runtime Environment supports permissions.
+     */
+    String getProperty(String key);
+
+    public static class ConfigProviderImpl implements ConfigProvider {
+        private final BundleContext context;
+
+        public ConfigProviderImpl(BundleContext context) {
+            this.context = context;
+        }
+
+        @Override
+        public String getProperty(String key) {
+            return context.getProperty(key);
+        }
+
+        @Override
+        public String toString() {
+            return "ConfigProviderImpl{" + "context=" + context + '}';
+        }
+    }
+
+}
diff --git a/opendaylight/config/config-persister-api/pom.xml b/opendaylight/config/config-persister-api/pom.xml
new file mode 100644 (file)
index 0000000..867c12c
--- /dev/null
@@ -0,0 +1,48 @@
+<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>config-subsystem</artifactId>
+        <groupId>org.opendaylight.controller</groupId>
+        <version>0.2.1-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+    <artifactId>config-persister-api</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-util</artifactId>
+            <version>0.2.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            com.google.common.base,
+                            org.w3c.dom,
+                            org.osgi.framework,
+                            org.opendaylight.controller.config.stat
+                        </Import-Package>
+                        <Export-Package>
+                            org.opendaylight.controller.config.persist.api,
+                            org.opendaylight.controller.config.persist.api.storage,
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/Persister.java
new file mode 100644 (file)
index 0000000..f9c9301
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.persist.api;
+
+import com.google.common.base.Optional;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Base interface for persister implementation.
+ */
+public interface Persister extends Closeable {
+
+    void persistConfig(ConfigSnapshotHolder configSnapshotHolder) throws IOException;
+
+    Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException;
+
+    public static interface ConfigSnapshotHolder {
+
+        String getConfigSnapshot();
+
+        Set<String> getCapabilities();
+    }
+}
diff --git a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/storage/StorageAdapter.java b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/storage/StorageAdapter.java
new file mode 100644 (file)
index 0000000..4475040
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.persist.api.storage;
+
+import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.stat.ConfigProvider;
+
+/**
+ * Plugins for {@link org.opendaylight.controller.config.persist.api.Persister}
+ * must implement this interface.
+ */
+public interface StorageAdapter extends Persister {
+
+    void setProperties(ConfigProvider configProvider);
+
+}
diff --git a/opendaylight/config/config-persister-file-adapter/pom.xml b/opendaylight/config/config-persister-file-adapter/pom.xml
new file mode 100644 (file)
index 0000000..51fcf86
--- /dev/null
@@ -0,0 +1,97 @@
+<?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>config-subsystem</artifactId>
+        <groupId>org.opendaylight.controller</groupId>
+        <version>0.2.1-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+    <artifactId>config-persister-file-adapter</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <!-- compile dependencies -->
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-persister-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>org.opendaylight.bgpcep</groupId>
+            <artifactId>mockito-configuration</artifactId>
+            <version>0.2.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!-- workaround for creating version according to OSGi specification (major.minor.micro[.qualifier] -->
+            <plugin>
+                <groupId>org.codehaus.groovy.maven</groupId>
+                <artifactId>gmaven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>execute</goal>
+                        </goals>
+                        <configuration>
+                            <source>
+                                System.setProperty("osgiversion", "${project.version}".replace('-', '.'))
+                            </source>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Fragment-Host>${project.groupId}.config-persister-impl;bundle-version=${osgiversion}
+                        </Fragment-Host>
+                        <Provide-Capability>org.opendaylight.controller.config.persister.storage.adapter
+                        </Provide-Capability>
+                        <Import-Package>
+                            org.osgi.framework,
+                            com.google.common.base,
+                            com.google.common.collect,
+                            com.google.common.io,
+                            javax.xml.parsers,
+                            javax.xml.transform,
+                            javax.xml.transform.dom,
+                            javax.xml.transform.stream,
+                            org.apache.commons.lang3,
+                            org.opendaylight.controller.config.persist.api,
+                            org.opendaylight.controller.config.stat,
+                            org.opendaylight.controller.config.persist.api.storage,
+                            org.slf4j,
+                            org.w3c.dom,
+                            org.xml.sax,
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java b/opendaylight/config/config-persister-file-adapter/src/main/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapter.java
new file mode 100644 (file)
index 0000000..a866743
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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.persist.storage.file;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+import org.apache.commons.lang3.StringUtils;
+import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
+import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Set;
+
+/**
+ * StorageAdapter that stores configuration in a plan file.
+ */
+public class FileStorageAdapter implements StorageAdapter {
+    private static final Logger logger = LoggerFactory.getLogger(FileStorageAdapter.class);
+
+    // TODO prefix properties
+
+    private static final Charset ENCODING = Charsets.UTF_8;
+
+    public static final String FILE_STORAGE_PROP = "fileStorage";
+    public static final String NUMBER_OF_BACKUPS = "numberOfBackups";
+
+    private static final String SEPARATOR_E_PURE = "//END OF CONFIG";
+    private static final String SEPARATOR_E = newLine(SEPARATOR_E_PURE);
+
+    private static final String SEPARATOR_M_PURE = "//END OF SNAPSHOT";
+    private static final String SEPARATOR_M = newLine(SEPARATOR_M_PURE);
+
+    private static final String SEPARATOR_S = newLine("//START OF CONFIG");
+
+    private static final String SEPARATOR_SL_PURE = "//START OF CONFIG-LAST";
+    private static final String SEPARATOR_SL = newLine(SEPARATOR_SL_PURE);
+
+    private static Integer numberOfStoredBackups;
+    private File storage;
+
+    @Override
+    public void setProperties(ConfigProvider configProvider) {
+        File storage = extractStorageFileFromProperties(configProvider);
+        logger.debug("Using file {}", storage.getAbsolutePath());
+        // Create file if it does not exist
+        File parentFile = storage.getAbsoluteFile().getParentFile();
+        if (parentFile.exists() == false) {
+            logger.debug("Creating parent folders {}", parentFile);
+            parentFile.mkdirs();
+        }
+        if (storage.exists() == false) {
+            logger.debug("Storage file does not exist, creating empty file");
+            try {
+                boolean result = storage.createNewFile();
+                if (result == false)
+                    throw new RuntimeException("Unable to create storage file " + storage);
+            } catch (IOException e) {
+                throw new RuntimeException("Unable to create storage file " + storage, e);
+            }
+        }
+        if (numberOfStoredBackups == 0) {
+            throw new RuntimeException(NUMBER_OF_BACKUPS
+                    + " property should be either set to positive value, or ommited. Can not be set to 0.");
+        }
+        setFileStorage(storage);
+
+    }
+
+    @VisibleForTesting
+    void setFileStorage(File storage) {
+        this.storage = storage;
+    }
+
+    @VisibleForTesting
+    void setNumberOfBackups(Integer numberOfBackups) {
+        numberOfStoredBackups = numberOfBackups;
+    }
+
+    private static File extractStorageFileFromProperties(ConfigProvider configProvider) {
+        String fileStorageProperty = configProvider.getProperty(FILE_STORAGE_PROP);
+        Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + FILE_STORAGE_PROP
+                + " in received properties :" + configProvider);
+        File result = new File(fileStorageProperty);
+        String numberOfBAckupsAsString = configProvider.getProperty(NUMBER_OF_BACKUPS);
+        if (numberOfBAckupsAsString != null) {
+            numberOfStoredBackups = Integer.valueOf(numberOfBAckupsAsString);
+        } else {
+            numberOfStoredBackups = Integer.MAX_VALUE;
+        }
+
+        return result;
+    }
+
+    private static String newLine(String string) {
+        return string + "\n";
+    }
+
+    @Override
+    public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
+        Preconditions.checkNotNull(storage, "Storage file is null");
+
+        String content = Files.toString(storage, ENCODING);
+        if (numberOfStoredBackups == Integer.MAX_VALUE) {
+            resetLastConfig(content);
+            persistLastConfig(holder);
+        } else {
+            if (numberOfStoredBackups == 1) {
+                Files.write("", storage, ENCODING);
+                persistLastConfig(holder);
+            } else {
+                int count = StringUtils.countMatches(content, SEPARATOR_S);
+                if ((count + 1) < numberOfStoredBackups) {
+                    resetLastConfig(content);
+                    persistLastConfig(holder);
+                } else {
+                    String contentSubString = StringUtils.substringBefore(content, SEPARATOR_E);
+                    contentSubString = contentSubString.concat(SEPARATOR_E_PURE);
+                    content = StringUtils.substringAfter(content, contentSubString);
+                    resetLastConfig(content);
+                    persistLastConfig(holder);
+                }
+            }
+        }
+    }
+
+    private void resetLastConfig(String content) throws IOException {
+        content = content.replaceFirst(SEPARATOR_SL, SEPARATOR_S);
+        Files.write(content, storage, ENCODING);
+    }
+
+    private void persistLastConfig(ConfigSnapshotHolder holder) throws IOException {
+        Files.append(SEPARATOR_SL, storage, ENCODING);
+        String snapshotAsString = holder.getConfigSnapshot();
+        Files.append(newLine(snapshotAsString), storage, ENCODING);
+        Files.append(SEPARATOR_M, storage, ENCODING);
+        Files.append(toStringCaps(holder.getCapabilities()), storage, ENCODING);
+        Files.append(SEPARATOR_E, storage, ENCODING);
+    }
+
+    private CharSequence toStringCaps(Set<String> capabilities) {
+        StringBuilder b = new StringBuilder();
+        for (String capability : capabilities) {
+            b.append(newLine(capability));
+        }
+        return b.toString();
+    }
+
+    @Override
+    public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
+        Preconditions.checkNotNull(storage, "Storage file is null");
+
+        if (!storage.exists()) {
+            return Optional.absent();
+        }
+
+        final LineProcessor lineProcessor = new LineProcessor();
+        String result = Files.readLines(storage, ENCODING, lineProcessor);
+
+        try {
+            if (lineProcessor.getConfigSnapshot().isPresent() == false) {
+                return Optional.absent();
+            } else {
+                return Optional.<ConfigSnapshotHolder> of(new PersistedConfigImpl(lineProcessor.getConfigSnapshot(),
+                        lineProcessor.getCapabilities()));
+            }
+
+        } catch (ParserConfigurationException | SAXException e) {
+            throw new IOException("Unable to load last config ", e);
+        }
+    }
+
+    private static final class LineProcessor implements com.google.common.io.LineProcessor<String> {
+
+        private boolean inLastConfig, inLastSnapshot;
+        private final StringBuffer snapshotBuffer = new StringBuffer();
+        private final Set<String> caps = Sets.newHashSet();
+
+        @Override
+        public String getResult() {
+            return null;
+        }
+
+        @Override
+        public boolean processLine(String line) throws IOException {
+            if (inLastConfig && line.equals(SEPARATOR_E_PURE)) {
+                inLastConfig = false;
+                return false;
+            }
+
+            if (inLastConfig && line.equals(SEPARATOR_M_PURE)) {
+                inLastSnapshot = false;
+                return true;
+            }
+
+            if (inLastConfig) {
+                if (inLastSnapshot) {
+                    snapshotBuffer.append(line);
+                    snapshotBuffer.append(System.lineSeparator());
+                } else {
+                    caps.add(line);
+                }
+            }
+
+            if (line.equals(SEPARATOR_SL_PURE)) {
+                inLastConfig = true;
+                inLastSnapshot = true;
+            }
+
+            return true;
+        }
+
+        Optional<String> getConfigSnapshot() throws IOException, SAXException, ParserConfigurationException {
+            final String xmlContent = snapshotBuffer.toString();
+            if (xmlContent == null || xmlContent.equals("")) {
+                return Optional.absent();
+            } else
+                return Optional.of(xmlContent);
+        }
+
+        Set<String> getCapabilities() throws IOException, SAXException, ParserConfigurationException {
+            return caps;
+        }
+
+    }
+
+    @Override
+    public void close() throws IOException {
+
+    }
+
+    @Override
+    public String toString() {
+        return "FileStorageAdapter [storage=" + storage + "]";
+    }
+
+    private class PersistedConfigImpl implements ConfigSnapshotHolder {
+
+        private final String snapshot;
+        private final Set<String> caps;
+
+        public PersistedConfigImpl(Optional<String> configSnapshot, Set<String> capabilities) {
+            this.snapshot = configSnapshot.get();
+            this.caps = capabilities;
+        }
+
+        @Override
+        public String getConfigSnapshot() {
+            return snapshot;
+        }
+
+        @Override
+        public Set<String> getCapabilities() {
+            return caps;
+        }
+    }
+
+}
diff --git a/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java b/opendaylight/config/config-persister-file-adapter/src/test/java/org/opendaylight/controller/config/persist/storage/file/FileStorageAdapterTest.java
new file mode 100644 (file)
index 0000000..acb44ba
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * 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.persist.storage.file;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.config.persist.api.Persister;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
+public class FileStorageAdapterTest {
+
+    private static int i;
+    private File file;
+
+    @Before
+    public void setUp() throws Exception {
+        file = Files.createTempFile("testFilePersist", ".txt").toFile();
+        if (!file.exists())
+            return;
+        com.google.common.io.Files.write("", file, Charsets.UTF_8);
+        i = 1;
+    }
+
+    @Test
+    public void testFileAdapter() throws Exception {
+        FileStorageAdapter storage = new FileStorageAdapter();
+        storage.setFileStorage(file);
+        storage.setNumberOfBackups(Integer.MAX_VALUE);
+        final Persister.ConfigSnapshotHolder holder = new Persister.ConfigSnapshotHolder() {
+            @Override
+            public String getConfigSnapshot() {
+                return createConfig();
+            }
+
+            @Override
+            public Set<String> getCapabilities() {
+                return createCaps();
+            }
+        };
+        storage.persistConfig(holder);
+
+        storage.persistConfig(holder);
+
+        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
+                new Predicate<String>() {
+
+                    @Override
+                    public boolean apply(String input) {
+                        if (input.equals(""))
+                            return false;
+                        return true;
+                    }
+                });
+        assertEquals(14, readLines.size());
+
+        Optional<Persister.ConfigSnapshotHolder> lastConf = storage.loadLastConfig();
+        assertTrue(lastConf.isPresent());
+        assertEquals("<config>2</config>",
+                lastConf.get().getConfigSnapshot().replaceAll("\\s", ""));
+        assertEquals(createCaps(), lastConf.get().getCapabilities());
+    }
+
+    private Set<String> createCaps() {
+        Set<String> caps = Sets.newHashSet();
+
+        caps.add("cap1");
+        caps.add("cap2");
+        caps.add("capaaaa as dasfasdf s2");
+        return caps;
+    }
+
+    @Test
+    public void testFileAdapterOneBackup() throws Exception {
+        FileStorageAdapter storage = new FileStorageAdapter();
+        storage.setFileStorage(file);
+        storage.setNumberOfBackups(1);
+        final Persister.ConfigSnapshotHolder holder = new Persister.ConfigSnapshotHolder() {
+            @Override
+            public String getConfigSnapshot() {
+                return createConfig();
+            }
+
+            @Override
+            public Set<String> getCapabilities() {
+                return createCaps();
+            }
+        };
+        storage.persistConfig(holder);
+
+        storage.persistConfig(holder);
+
+        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
+                new Predicate<String>() {
+
+                    @Override
+                    public boolean apply(String input) {
+                        if (input.equals(""))
+                            return false;
+                        return true;
+                    }
+                });
+        assertEquals(7, readLines.size());
+
+        Optional<Persister.ConfigSnapshotHolder> lastConf = storage.loadLastConfig();
+        assertTrue(lastConf.isPresent());
+        assertEquals("<config>2</config>",
+                lastConf.get().getConfigSnapshot().replaceAll("\\s", ""));
+    }
+
+    @Test
+    public void testFileAdapterOnlyTwoBackups() throws Exception {
+        FileStorageAdapter storage = new FileStorageAdapter();
+        storage.setFileStorage(file);
+        storage.setNumberOfBackups(2);
+        final Persister.ConfigSnapshotHolder holder = new Persister.ConfigSnapshotHolder() {
+            @Override
+            public String getConfigSnapshot() {
+                return createConfig();
+            }
+
+            @Override
+            public Set<String> getCapabilities() {
+                return createCaps();
+            }
+        };
+        storage.persistConfig(holder);
+
+        storage.persistConfig(holder);
+        storage.persistConfig(holder);
+
+        Collection<String> readLines = Collections2.filter(com.google.common.io.Files.readLines(file, Charsets.UTF_8),
+                new Predicate<String>() {
+
+                    @Override
+                    public boolean apply(String input) {
+                        if (input.equals(""))
+                            return false;
+                        return true;
+                    }
+                });
+
+        assertEquals(14, readLines.size());
+
+        Optional<Persister.ConfigSnapshotHolder> lastConf = storage.loadLastConfig();
+        assertTrue(lastConf.isPresent());
+        assertEquals("<config>3</config>",
+               lastConf.get().getConfigSnapshot().replaceAll("\\s", ""));
+        assertFalse(readLines.contains(holder.getConfigSnapshot()));
+    }
+
+    @Test
+    public void testNoLastConfig() throws Exception {
+        File file = Files.createTempFile("testFilePersist", ".txt").toFile();
+        if (!file.exists())
+            return;
+        FileStorageAdapter storage = new FileStorageAdapter();
+        storage.setFileStorage(file);
+
+        Optional<Persister.ConfigSnapshotHolder> elementOptional = storage.loadLastConfig();
+        assertThat(elementOptional.isPresent(), is(false));
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNoProperties() throws Exception {
+        FileStorageAdapter storage = new FileStorageAdapter();
+        storage.loadLastConfig();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNoProperties2() throws Exception {
+        FileStorageAdapter storage = new FileStorageAdapter();
+        storage.persistConfig(new Persister.ConfigSnapshotHolder() {
+            @Override
+            public String getConfigSnapshot() {
+                return Mockito.mock(String.class);
+            }
+
+            @Override
+            public Set<String> getCapabilities() {
+                return Collections.<String> emptySet();
+            }
+        } );
+    }
+
+    static String createConfig() {
+        return "<config>" + i++ + "</config>";
+    }
+
+}
index 6484c30..1812fbb 100755 (executable)
@@ -22,6 +22,8 @@
         <module>config-api</module>
         <module>config-manager</module>
         <module>config-util</module>
+        <module>config-persister-api</module>
+        <module>config-persister-file-adapter</module>
         <module>yang-jmx-generator</module>
         <module>yang-jmx-generator-plugin</module>
         <module>yang-jmx-generator-it</module>
@@ -40,7 +42,6 @@
         <jacoco.version>0.6.2.201302030002</jacoco.version>
         <slf4j.version>1.7.2</slf4j.version>
         <jolokia.version>1.1.1</jolokia.version>
-        <osgi.core.version>5.0.0</osgi.core.version>
         <opendaylight.yang.version>0.5.9-SNAPSHOT</opendaylight.yang.version>
         <opendaylight.binding.version>0.6.0-SNAPSHOT</opendaylight.binding.version>
         <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
                     <artifactId>gmaven-plugin</artifactId>
                     <version>1.0</version>
                 </plugin>
+                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            org.opendaylight.yangtools
+                                        </groupId>
+                                        <artifactId>
+                                            yang-maven-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [0.5.7-SNAPSHOT,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>
+                                                generate-sources
+                                            </goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
             </plugins>
         </pluginManagement>
     </build>
     <pluginRepositories>
         <pluginRepository>
             <id>nexus.opendaylight.org</id>
-            <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot</url>
+            <url>http://nexus.opendaylight.org/content/repositories/opendaylight.release</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
index 1079ce9..81d55ef 100644 (file)
@@ -9,51 +9,61 @@
     </parent>
     <artifactId>yang-jmx-generator-plugin</artifactId>
     <dependencies>
+
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>yang-jmx-generator</artifactId>
             <version>0.2.1-SNAPSHOT</version>
         </dependency>
+
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-maven-plugin-spi</artifactId>
             <version>${opendaylight.yang.version}</version>
         </dependency>
+
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>binding-generator-impl</artifactId>
+            <artifactId>binding-type-provider</artifactId>
             <version>${opendaylight.binding.version}</version>
         </dependency>
+
         <dependency>
             <groupId>org.eclipse.jdt</groupId>
             <artifactId>core</artifactId>
             <version>3.3.0-v_771</version>
             <scope>test</scope>
         </dependency>
+
         <dependency>
             <groupId>org.freemarker</groupId>
             <artifactId>freemarker</artifactId>
             <version>2.3.20</version>
         </dependency>
+
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>config-api</artifactId>
             <version>0.2.1-SNAPSHOT</version>
         </dependency>
+
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
+
         <dependency>
             <!--FIXME two implementations of slf4j on classpath, logback classic from parent-->
             <groupId>com.googlecode.slf4j-maven-plugin-log</groupId>
             <artifactId>slf4j-maven-plugin-log</artifactId>
             <version>1.0.0</version>
         </dependency>
+
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <scope>test</scope>
             <type>test-jar</type>
         </dependency>
+
         <dependency>
             <groupId>org.eclipse</groupId>
             <artifactId>jdt</artifactId>
             <version>3.3.0-v20070607-1300</version>
             <scope>test</scope>
         </dependency>
+
         <dependency>
             <groupId>org.opendaylight.bgpcep</groupId>
             <artifactId>mockito-configuration</artifactId>
             <version>0.2.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
+
         <dependency>
-          <groupId>org.apache.commons</groupId>
-          <artifactId>commons-lang3</artifactId>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
         </dependency>
     </dependencies>
 
index 743ffba..e40ca8b 100644 (file)
@@ -7,17 +7,11 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.plugin;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import org.apache.commons.io.FileUtils;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
@@ -35,11 +29,12 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.impl.StaticLoggerBinder;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * This class interfaces with yang-maven-plugin. Gets parsed yang modules in
index dce382d..67a1c80 100644 (file)
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>binding-generator-util</artifactId>
+            <artifactId>binding-generator-spi</artifactId>
             <version>${opendaylight.binding.version}</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>binding-generator-spi</artifactId>
+            <artifactId>binding-generator-util</artifactId>
             <version>${opendaylight.binding.version}</version>
         </dependency>
+
+
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
index 6d1eca1..d07e20b 100644 (file)
@@ -7,20 +7,9 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
@@ -28,22 +17,12 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.api.*;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
+import java.util.*;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
 
 /**
  * Holds information about runtime bean to be generated. There are two kinds of
@@ -295,8 +274,8 @@ public class RuntimeBeanEntry {
                                         + "Error occured in " + rpcDefinition);
                     }
                     List<JavaAttribute> parameters = new ArrayList<>();
-                    for (DataSchemaNode childNode : rpcDefinition.getInput()
-                            .getChildNodes()) {
+                    for (DataSchemaNode childNode : sortAttributes(rpcDefinition.getInput()
+                            .getChildNodes())) {
                         if (childNode.isAddedByUses() == false) { // skip
                                                                   // refined
                                                                   // context-instance
@@ -318,6 +297,17 @@ public class RuntimeBeanEntry {
                 attributes, rpcs);
     }
 
+    private static Collection<DataSchemaNode> sortAttributes(Set<DataSchemaNode> childNodes) {
+        final TreeSet<DataSchemaNode> dataSchemaNodes = new TreeSet<>(new Comparator<DataSchemaNode>() {
+            @Override
+            public int compare(DataSchemaNode o1, DataSchemaNode o2) {
+                return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
+            }
+        });
+        dataSchemaNodes.addAll(childNodes);
+        return dataSchemaNodes;
+    }
+
     private static boolean isInnerStateBean(DataSchemaNode child) {
         for (UnknownSchemaNode unknownSchemaNode : child
                 .getUnknownSchemaNodes()) {
index 69531c6..97285c1 100644 (file)
@@ -32,7 +32,7 @@
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>binding-generator-impl</artifactId>
+            <artifactId>binding-type-provider</artifactId>
             <version>${opendaylight.binding.version}</version>
         </dependency>
         <dependency>
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked1.txt b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked1.txt
new file mode 100644 (file)
index 0000000..aad7239
--- /dev/null
@@ -0,0 +1,35 @@
+
+#24
+<rpc message-id="101" xm
+#28
+lns="urn:ietf:params:xml:ns:
+#2
+ne
+#33
+tconf:base:1.0">
+  <my-own-method
+#3
+ xm
+#13
+lns="http://e
+#34
+xample.net/me/my-own/1.0">
+    <my
+#8
+-first-p
+#21
+arameter>14</my-first
+#26
+-parameter>
+    <another-p
+#23
+arameter>fred</another-
+#31
+parameter>
+ </my-own-method>
+ <
+#2
+/r
+#3
+pc>
+##
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked2.txt b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked2.txt
new file mode 100644 (file)
index 0000000..a36a85e
--- /dev/null
@@ -0,0 +1,48 @@
+
+#22
+<rpc message-id="101" 
+#24
+xmlns="urn:ietf:params:x
+#15
+ml:ns:netconf:b
+#54
+ase:1.0">
+  <get-config>
+      <source>
+            <r
+#2
+un
+#9
+ning/>
+  
+#18
+  </source>    <fi
+#33
+lter type="subtree">
+      <top x
+#4
+mlns
+#31
+="http://example.com/schema/1.2
+#15
+/config">
+     
+#19
+   <users>
+        
+#8
+     <us
+#3
+er/
+#5
+>
+   
+#77
+     </users>
+           </top>
+               </filter>
+                 </g
+#17
+et-config>
+</rpc>
+##
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked3.txt b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked3.txt
new file mode 100644 (file)
index 0000000..d9dc43d
--- /dev/null
@@ -0,0 +1,43 @@
+
+#43
+<rpc message-id="101" xmlns="urn:ietf:param
+#14
+s:xml:ns:netco
+#14
+nf:base:1.0">
+
+#26
+<get-config>
+    <source>
+
+#35
+     <running/>
+         </source>
+
+#39
+    <filter type="subtree">
+          <
+#40
+top xmlns="http://example.com/schema/1.2
+#26
+/config">
+        <users>
+
+#36
+     <user>
+                 <name>f
+#56
+red</name>
+          </user>
+                  </users>
+
+#28
+      </top>
+          </fil
+#1
+t
+#28
+er>
+  </get-config>
+  </rpc>
+##
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked4.txt b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked4.txt
new file mode 100644 (file)
index 0000000..0b8a102
--- /dev/null
@@ -0,0 +1,40 @@
+
+#17
+<rpc message-id="
+#25
+101" xmlns="urn:ietf:para
+#19
+ms:xml:ns:netconf:b
+#3
+ase
+#19
+:1.0">
+  <get-confi
+#61
+g>
+    <source>
+          <running/>
+              </source>
+
+#43
+  <filter type="subtree">
+        <!-- requ
+#13
+est a text ve
+#22
+rsion of the configura
+#9
+tion -->
+
+#16
+   <config-text 
+#45
+xmlns="http://example.com/text/1.2/config"/>
+
+#22
+    </filter>
+      </
+#18
+get-config>
+</rpc>
+##
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked5.txt b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/chunked5.txt
new file mode 100644 (file)
index 0000000..f8f3c4d
--- /dev/null
@@ -0,0 +1,42 @@
+
+#43
+<rpc message-id="101" xmlns="urn:ietf:param
+#41
+s:xml:ns:netconf:base:1.0">
+  <edit-confi
+#29
+g>
+    <target>
+          <ru
+#13
+nning/>
+    <
+#4
+/tar
+#18
+get>
+    <config>
+
+#41
+  <top xmlns="http://example.com/schema/1
+#32
+.2/config">
+        <interface>
+
+#29
+        <name>Ethernet0/0</na
+#30
+me>
+          <mtu>1500</mtu>
+
+#61
+</interface>
+      </top>
+          </config>
+            </e
+#9
+dit-confi
+#9
+g>
+</rpc>
+##
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/databaseinteractions/jolokia_config_bean_response.txt b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/databaseinteractions/jolokia_config_bean_response.txt
new file mode 100644 (file)
index 0000000..2ae32ef
--- /dev/null
@@ -0,0 +1,18 @@
+curl http://localhost:17777/jolokia/read/org.opendaylight.controller:instanceName=fixed1,type=ConfigBean,interfaceName=testing-threadpool | jsonpp
+{
+    "request": {
+        "mbean": "org.opendaylight.controller:instanceName=fixed1,interfaceName=testing-threadpool,type=ConfigBean",
+        "type": "read"
+    },
+    "status": 200,
+    "timestamp": 1362416252,
+    "value": {
+        "ExportedInterfaces": [
+            "testing-threadpool",
+            "modifiable-threadpool"
+        ],
+        "ImplementationName": "fixed",
+        "ThreadCount": 10,
+        "TriggerNewInstanceCreation": false
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/databaseinteractions/jolokia_lookupConfigBeans.txt b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/databaseinteractions/jolokia_lookupConfigBeans.txt
new file mode 100644 (file)
index 0000000..2ae705a
--- /dev/null
@@ -0,0 +1,18 @@
+$ curl 'http://localhost:17777/jolokia/exec/org.opendaylight.controller:type=ConfigRegistry/lookupConfigBeans()' | jsonpp
+{
+    "request": {
+        "mbean": "org.opendaylight.controller:type=ConfigRegistry",
+        "operation": "lookupConfigBeans()",
+        "type": "exec"
+    },
+    "status": 200,
+    "timestamp": 1362417043,
+    "value": [
+        {
+            "objectName": "org.opendaylight.controller:instanceName=fixed1,interfaceName=modifiable-threadpool,type=ConfigBean"
+        },
+        {
+            "objectName": "org.opendaylight.controller:instanceName=fixed1,interfaceName=testing-threadpool,type=ConfigBean"
+        }
+    ]
+}
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_commit.xml b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_commit.xml
new file mode 100644 (file)
index 0000000..6eca609
--- /dev/null
@@ -0,0 +1,4 @@
+<rpc message-id="104"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <commit/>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_lock_candidate.xml b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_lock_candidate.xml
new file mode 100644 (file)
index 0000000..6a9ed63
--- /dev/null
@@ -0,0 +1,8 @@
+<rpc message-id="102"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <lock>
+        <target>
+            <candidate/>
+        </target>
+    </lock>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_lock_running.xml b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_lock_running.xml
new file mode 100644 (file)
index 0000000..2d66c45
--- /dev/null
@@ -0,0 +1,8 @@
+<rpc message-id="101"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <lock>
+        <target>
+            <running/>
+        </target>
+    </lock>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_modify_candidate.xml b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_modify_candidate.xml
new file mode 100644 (file)
index 0000000..ce67845
--- /dev/null
@@ -0,0 +1,20 @@
+<rpc message-id="103"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <default-operation>none</default-operation>
+        <test-option>test-then-set</test-option>
+        <error-option>stop-on-error</error-option>
+        <nc:config
+                xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+                xmlns="uri-for-my-data-model-namespace">
+            <some-existing-node>
+                <my-new-node nc:operation="create">
+                    <my-new-leaf>7</my-new-leaf>
+                </my-new-node>
+            </some-existing-node>
+        </nc:config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_unlock_candidate.xml b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_unlock_candidate.xml
new file mode 100644 (file)
index 0000000..dd6fe1b
--- /dev/null
@@ -0,0 +1,8 @@
+<rpc message-id="105"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <unlock>
+        <target>
+            <candidate/>
+        </target>
+    </unlock>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_unlock_running.xml b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/client_unlock_running.xml
new file mode 100644 (file)
index 0000000..f94af46
--- /dev/null
@@ -0,0 +1,8 @@
+<rpc message-id="106"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <unlock>
+        <target>
+            <running/>
+        </target>
+    </unlock>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/server_error_missing_attribute.xml b/opendaylight/controller/netconf/netconf-impl/src/test/resources/org/opendaylight/netconf/impl/listener/databaseinteractions/notused/server_error_missing_attribute.xml
new file mode 100644 (file)
index 0000000..c70184e
--- /dev/null
@@ -0,0 +1,11 @@
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <rpc-error>
+        <error-type>rpc</error-type>
+        <error-tag>missing-attribute</error-tag>
+        <error-severity>error</error-severity>
+        <error-info>
+            <bad-attribute>message-id</bad-attribute>
+            <bad-element>rpc</bad-element>
+        </error-info>
+    </rpc-error>
+</rpc-reply>
index a11f93b..1b747f6 100644 (file)
           <version>0.1.1-SNAPSHOT</version>
         </dependency>
 
-        <!-- config
+        <!-- config-->
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-api</artifactId>
           <artifactId>logback-config</artifactId>
           <version>${config.version}</version>
         </dependency>
-        -->
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>config-persister-api</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>config-persister-file-adapter</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+
+
+       <!-- Netconf -->
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-api</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-impl</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-util</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-client</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netconf-mapping-api</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>config-netconf-connector</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>config-persister-impl</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+
+
       </dependencies>
     </profile>
   </profiles>
      <groupId>org.opendaylight.bgpcep</groupId>
      <artifactId>util</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.bgpcep</groupId>
+      <artifactId>framework</artifactId>
+    </dependency>
 
-    <!-- testing dependencies I'm pretty sure we should trim -->
+    <!--Netty-->
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-handler</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-codec</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-buffer</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-transport</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-common</artifactId>
+    </dependency>
+
+
+      <!-- testing dependencies I'm pretty sure we should trim -->
     <dependency>
      <groupId>org.opendaylight.controller</groupId>
      <artifactId>clustering.test</artifactId>
      <artifactId>yang-binding</artifactId>
      <version>0.6.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools</groupId>
+     <artifactId>binding-type-provider</artifactId>
+     <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools</groupId>
+     <artifactId>binding-generator-util</artifactId>
+     <version>${yangtools.binding.version}</version>
+    </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools</groupId>
+     <artifactId>binding-model-api</artifactId>
+     <version>${yangtools.binding.version}</version>
+    </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools</groupId>
+     <artifactId>binding-generator-spi</artifactId>
+     <version>${yangtools.binding.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.4</version>
+    </dependency>
+
+      <dependency>
+     <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+     <artifactId>antlr-runtime-osgi</artifactId>
+     <version>4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+     <artifactId>xtend-lib-osgi</artifactId>
+     <version>2.4.2-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools</groupId>
+     <artifactId>yang-parser-api</artifactId>
+     <version>${yangtools.version}</version>
+    </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools</groupId>
+     <artifactId>yang-model-util</artifactId>
+     <version>${yangtools.version}</version>
+    </dependency>
+    <dependency>
+     <groupId>org.opendaylight.yangtools</groupId>
+     <artifactId>yang-parser-impl</artifactId>
+     <version>${yangtools.version}</version>
+    </dependency>
     <dependency>
      <groupId>org.opendaylight.yangtools</groupId>
      <artifactId>yang-common</artifactId>
index ac68652..4ad7cf1 100644 (file)
@@ -13,6 +13,17 @@ osgi.bundles=\
     reference\:file\:../lib/jersey-json-1.17.jar@2:start,\
     reference\:file\:../lib/jersey-server-1.17.jar@2:start
 
+# Netconf startup configuration
+netconf.tcp.address=127.0.0.1
+netconf.tcp.port=8383
+
+#netconf.tls.address=127.0.0.1
+#netconf.tls.port=8384
+#netconf.tls.keystore=
+#netconf.tls.keystore.password=
+
+netconf.config.persister.storageAdapterClass=org.opendaylight.controller.netconf.persist.impl.NoOpStorageAdapter
+
 # Set Default start level for framework
 osgi.bundles.defaultStartLevel=4
 # Extra packages to import from the boot class loader
index 50a87fb..7d04a12 100644 (file)
@@ -42,6 +42,9 @@
   <!-- OSGi logging bridge -->
   <logger name="org.opendaylight.controller.logging.bridge" level="WARN"/>
 
+  <!-- Netty -->
+  <logger name="io.netty" level="WARN"/>
+
   <!-- Openflow Protocol Plugin -->
   <logger name="org.opendaylight.controller.protocol_plugin.openflow" level="INFO"/>
   <logger name="org.opendaylight.controller.protocol_plugin.openflow.internal.DiscoveryService" level="INFO"/>
diff --git a/opendaylight/netconf/config-netconf-connector/pom.xml b/opendaylight/netconf/config-netconf-connector/pom.xml
new file mode 100755 (executable)
index 0000000..0386378
--- /dev/null
@@ -0,0 +1,157 @@
+<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>netconf-subsystem</artifactId>
+        <groupId>org.opendaylight.controller</groupId>
+        <version>0.2.1-SNAPSHOT</version>
+    </parent>
+    <artifactId>config-netconf-connector</artifactId>
+    <name>${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <!-- compile dependencies -->
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+
+            <artifactId>yang-jmx-generator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+
+            <artifactId>config-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+
+            <artifactId>yang-store-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-mapping-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-util</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+
+            <artifactId>yang-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+
+            <artifactId>config-manager</artifactId>
+            <version>${config.version}</version>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+
+            <artifactId>config-manager</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-impl</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+
+            <artifactId>yang-store-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.bgpcep</groupId>
+            <artifactId>mockito-configuration</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.controller.netconf.confignetconfconnector.osgi.Activator
+                        </Bundle-Activator>
+                        <Private-Package>
+                            org.opendaylight.controller.netconf.confignetconfconnector.mapping.*,
+                            org.opendaylight.controller.netconf.confignetconfconnector.operations.*,
+                            org.opendaylight.controller.netconf.confignetconfconnector.transactions,
+                            org.opendaylight.controller.netconf.confignetconfconnector.util,
+                            org.opendaylight.controller.netconf.confignetconfconnector.osgi,
+                            org.opendaylight.controller.config.util,
+                        </Private-Package>
+                        <Import-Package>
+                            com.google.common.base,
+                            com.google.common.collect,
+                            javax.annotation,
+                            javax.management,
+                            javax.management.openmbean,
+                            org.opendaylight.controller.config.api,
+                            org.opendaylight.controller.config.api.jmx,
+                            org.opendaylight.controller.config.yang.store.api,
+                            org.opendaylight.controller.config.yangjmxgenerator,
+                            org.opendaylight.controller.config.yangjmxgenerator.attribute,
+                            org.opendaylight.controller.netconf.api,
+                            org.opendaylight.controller.netconf.mapping.api,
+                            org.opendaylight.controller.netconf.util.mapping,
+                            org.opendaylight.controller.netconf.util.xml,
+                            org.opendaylight.yangtools.yang.common,
+                            org.opendaylight.yangtools.yang.model.api,
+                            org.osgi.framework,
+                            org.osgi.util.tracker,
+                            org.slf4j,
+                            org.w3c.dom
+                        </Import-Package>
+                        <Export-Package>
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java
new file mode 100644 (file)
index 0000000..5e3f542
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes;
+
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.*;
+
+public abstract class AttributeIfcSwitchStatement<T> {
+
+    public T switchAttribute(AttributeIfc attributeIfc) {
+
+        if (attributeIfc instanceof JavaAttribute) {
+            return caseJavaAttribute((JavaAttribute) attributeIfc);
+        } else if (attributeIfc instanceof DependencyAttribute) {
+            return caseDependencyAttribute((DependencyAttribute) attributeIfc);
+        } else if (attributeIfc instanceof ListAttribute) {
+            return caseListAttribute((ListAttribute) attributeIfc);
+        } else if (attributeIfc instanceof TOAttribute) {
+            return caseTOAttribute((TOAttribute) attributeIfc);
+        }
+
+        throw new IllegalArgumentException("Unknown attribute type " + attributeIfc.getClass() + ", " + attributeIfc);
+    }
+
+    protected abstract T caseJavaAttribute(JavaAttribute attributeIfc);
+
+    protected abstract T caseDependencyAttribute(DependencyAttribute attributeIfc);
+
+    protected abstract T caseTOAttribute(TOAttribute attributeIfc);
+
+    protected abstract T caseListAttribute(ListAttribute attributeIfc);
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..2ba1b61
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import java.util.List;
+
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+
+public abstract class AbstractAttributeReadingStrategy<A extends AttributeIfc> implements AttributeReadingStrategy {
+
+    private final A attributeIfc;
+
+    public AbstractAttributeReadingStrategy(A attributeIfc) {
+        this.attributeIfc = attributeIfc;
+    }
+
+    public A getAttributeIfc() {
+        return attributeIfc;
+    }
+
+    @Override
+    public AttributeConfigElement readElement(List<XmlElement> configNodes) {
+        if (configNodes.size() == 0)
+            return AttributeConfigElement.createNullValue(attributeIfc);
+
+        return readElementHook(configNodes);
+    }
+
+    abstract AttributeConfigElement readElementHook(List<XmlElement> configNodes);
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..f07e740
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.collect.Lists;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+
+import java.util.List;
+
+public class ArrayAttributeReadingStrategy extends AbstractAttributeReadingStrategy<AttributeIfc> {
+
+    private final AttributeReadingStrategy innerStrategy;
+
+    /**
+     * @param attributeIfc
+     * @param innerStrategy
+     */
+    public ArrayAttributeReadingStrategy(AttributeIfc attributeIfc, AttributeReadingStrategy innerStrategy) {
+        super(attributeIfc);
+        this.innerStrategy = innerStrategy;
+    }
+
+    @Override
+    AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+        List<Object> innerList = Lists.newArrayList();
+        for (int i = 0; i < configNodes.size(); i++) {
+            innerList.add(innerStrategy.readElement(Lists.newArrayList(configNodes.get(i))).getValue());
+        }
+        return AttributeConfigElement.create(getAttributeIfc(), innerList);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java
new file mode 100644 (file)
index 0000000..fa249da
--- /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.confignetconfconnector.mapping.attributes.fromxml;
+
+import javax.management.openmbean.OpenType;
+
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
+
+import com.google.common.base.Optional;
+
+/**
+ * Parsed xml element containing configuration for one attribute of an instance
+ * of some module. Contains default value extracted from yang file.
+ */
+public class AttributeConfigElement {
+    private final Object dafaultValue;
+    private final Object value;
+
+    private Optional<?> resolvedValue;
+    private Object resolvedDefaultValue;
+    private String jmxName;
+
+    public AttributeConfigElement(Object dafaultValue, Object value) {
+        this.dafaultValue = dafaultValue;
+        this.value = value;
+    }
+
+    public void setJmxName(String jmxName) {
+        this.jmxName = jmxName;
+    }
+
+    public String getJmxName() {
+        return jmxName;
+    }
+
+    public void resolveValue(AttributeResolvingStrategy<?, ? extends OpenType<?>> attributeResolvingStrategy,
+            String attrName) {
+        resolvedValue = attributeResolvingStrategy.parseAttribute(attrName, value);
+        Optional<?> resolvedDefault = attributeResolvingStrategy.parseAttribute(attrName, dafaultValue);
+        resolvedDefaultValue = resolvedDefault.isPresent() ? resolvedDefault.get() : null;
+
+    }
+
+    public static AttributeConfigElement create(AttributeIfc attributeIfc, Object value) {
+        return new AttributeConfigElement(attributeIfc.getNullableDefault(), value);
+    }
+
+    public static AttributeConfigElement createNullValue(AttributeIfc attributeIfc) {
+        return new AttributeConfigElement(attributeIfc.getNullableDefault(), null);
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public Optional<?> getResolvedValue() {
+        return resolvedValue;
+    }
+
+    public Object getResolvedDefaultValue() {
+        return resolvedDefaultValue;
+    }
+
+    @Override
+    public String toString() {
+        return "AttributeConfigElement [dafaultValue=" + dafaultValue + ", value=" + value + "]";
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..6dae839
--- /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.confignetconfconnector.mapping.attributes.fromxml;
+
+import java.util.List;
+
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+
+public interface AttributeReadingStrategy {
+
+    public abstract AttributeConfigElement readElement(List<XmlElement> element);
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..1cfb74d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class CompositeAttributeReadingStrategy extends AbstractAttributeReadingStrategy<TOAttribute> {
+
+    private final Map<String, AttributeReadingStrategy> innerStrategies;
+
+    public CompositeAttributeReadingStrategy(TOAttribute attributeIfc,
+            Map<String, AttributeReadingStrategy> innerStrategies) {
+        super(attributeIfc);
+        this.innerStrategies = innerStrategies;
+    }
+
+    @Override
+    AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+
+        Preconditions.checkState(configNodes.size() == 1, "This element should be present only once %s", configNodes);
+
+        XmlElement complexElement = configNodes.get(0);
+
+        Map<String, Object> innerMap = Maps.newHashMap();
+
+        Map<String, AttributeIfc> inner = getAttributeIfc().getYangPropertiesToTypesMap();
+
+        List<XmlElement> recognisedChildren = Lists.newArrayList();
+        for (Entry<String, AttributeIfc> innerAttrEntry : inner.entrySet()) {
+            List<XmlElement> childItem = complexElement.getChildElementsWithSameNamespace(innerAttrEntry.getKey());
+            recognisedChildren.addAll(childItem);
+
+            AttributeConfigElement resolvedInner = innerStrategies.get(innerAttrEntry.getKey()).readElement(childItem);
+
+            innerMap.put(innerAttrEntry.getKey(), resolvedInner.getValue());
+        }
+
+        complexElement.checkUnrecognisedElements(recognisedChildren);
+
+        return AttributeConfigElement.create(getAttributeIfc(), innerMap);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..bdb9391
--- /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.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+
+import java.util.List;
+
+public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReadingStrategy<AttributeIfc> {
+
+    public ObjectNameAttributeReadingStrategy(DependencyAttribute attributeIfc) {
+        super(attributeIfc);
+    }
+
+    @Override
+    AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+
+        XmlElement firstChild = configNodes.get(0);
+        Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + firstChild
+                + " but was " + configNodes.size());
+
+        Preconditions.checkNotNull(firstChild, "Element %s should be present", firstChild);
+        return AttributeConfigElement.create(getAttributeIfc(), resolve(firstChild));
+    }
+
+    private ObjectNameAttributeMappingStrategy.MappedDependency resolve(XmlElement firstChild) {
+        XmlElement typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+        String serviceName = typeElement.getTextContent();
+        XmlElement nameElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
+        String dependencyName = nameElement.getTextContent();
+
+        return new ObjectNameAttributeMappingStrategy.MappedDependency(serviceName, dependencyName);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java
new file mode 100644 (file)
index 0000000..8663de7
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.*;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.SimpleType;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadingStrategy> {
+
+    private String key;
+
+    public Map<String, AttributeReadingStrategy> prepareReading(Map<String, AttributeIfc> yangToAttrConfig) {
+        Map<String, AttributeReadingStrategy> strategies = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> attributeEntry : yangToAttrConfig.entrySet()) {
+            AttributeReadingStrategy strat = prepareReadingStrategy(attributeEntry.getKey(), attributeEntry.getValue());
+            strategies.put(attributeEntry.getKey(), strat);
+        }
+        return strategies;
+    }
+
+    private AttributeReadingStrategy prepareReadingStrategy(String key, AttributeIfc attributeIfc) {
+        this.key = key;
+        return switchAttribute(attributeIfc);
+    }
+
+    @Override
+    protected AttributeReadingStrategy caseJavaAttribute(JavaAttribute attributeIfc) {
+        if (attributeIfc.getOpenType() instanceof SimpleType<?>)
+            return new SimpleAttributeReadingStrategy(attributeIfc);
+        else if (attributeIfc.getOpenType() instanceof ArrayType<?>) {
+            SimpleAttributeReadingStrategy innerStrategy = new SimpleAttributeReadingStrategy(
+                    ((ArrayType<?>) attributeIfc.getOpenType()).getElementOpenType());
+            return new ArrayAttributeReadingStrategy(attributeIfc, innerStrategy);
+        }
+        throw new IllegalStateException(JavaAttribute.class + " can only provide open type " + SimpleType.class
+                + " or " + ArrayType.class);
+    }
+
+    @Override
+    protected AttributeReadingStrategy caseDependencyAttribute(DependencyAttribute attributeIfc) {
+        return new ObjectNameAttributeReadingStrategy(attributeIfc);
+    }
+
+    @Override
+    protected AttributeReadingStrategy caseTOAttribute(TOAttribute attributeIfc) {
+        Map<String, AttributeIfc> inner = attributeIfc.getYangPropertiesToTypesMap();
+        Map<String, AttributeReadingStrategy> innerStrategies = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> innerAttrEntry : inner.entrySet()) {
+            AttributeReadingStrategy innerStrat = prepareReadingStrategy(innerAttrEntry.getKey(),
+                    innerAttrEntry.getValue());
+            innerStrategies.put(innerAttrEntry.getKey(), innerStrat);
+        }
+
+        return new CompositeAttributeReadingStrategy(attributeIfc, innerStrategies);
+    }
+
+    @Override
+    protected AttributeReadingStrategy caseListAttribute(ListAttribute attributeIfc) {
+        AttributeIfc innerAttr = attributeIfc.getInnerAttribute();
+        AttributeReadingStrategy innerStrategy = prepareReadingStrategy(key, innerAttr);
+        return new ArrayAttributeReadingStrategy(attributeIfc, innerStrategy);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..c5c287f
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+
+import javax.management.openmbean.OpenType;
+import java.util.List;
+
+public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStrategy<AttributeIfc> {
+
+    public SimpleAttributeReadingStrategy(AttributeIfc attributeIfc) {
+        super(attributeIfc);
+    }
+
+    /**
+     * @param elementOpenType
+     */
+    public SimpleAttributeReadingStrategy(OpenType<?> elementOpenType) {
+        super(new AttributeIfcWrapper(elementOpenType));
+    }
+
+    @Override
+    AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+        XmlElement xmlElement = configNodes.get(0);
+        Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + xmlElement
+                + " but was " + configNodes.size());
+
+        String textContent = xmlElement.getTextContent();
+
+        Preconditions.checkNotNull(textContent, "This element should contain text %s", xmlElement);
+        return AttributeConfigElement.create(getAttributeIfc(), textContent);
+    }
+
+    /**
+     * Wrapper for JavaAttribute inner element attributes (in case JavaAttribute
+     * is array)
+     */
+    static class AttributeIfcWrapper implements AttributeIfc {
+
+        private final OpenType<?> elementOpenType;
+
+        public AttributeIfcWrapper(OpenType<?> elementOpenType) {
+            this.elementOpenType = elementOpenType;
+        }
+
+        @Override
+        public String getAttributeYangName() {
+            return null;
+        }
+
+        @Override
+        public String getNullableDescription() {
+            return null;
+        }
+
+        @Override
+        public String getNullableDefault() {
+            return null;
+        }
+
+        @Override
+        public String getUpperCaseCammelCase() {
+            return null;
+        }
+
+        @Override
+        public String getLowerCaseCammelCase() {
+            return null;
+        }
+
+        @Override
+        public OpenType<?> getOpenType() {
+            return elementOpenType;
+        }
+
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/AbstractAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/AbstractAttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..0d5fcb9
--- /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.netconf.confignetconfconnector.mapping.attributes.mapping;
+
+import javax.management.openmbean.OpenType;
+
+public abstract class AbstractAttributeMappingStrategy<T, O extends OpenType<?>> implements
+        AttributeMappingStrategy<T, O> {
+
+    private final O attrOpenType;
+
+    public AbstractAttributeMappingStrategy(O attributeIfc) {
+        this.attrOpenType = attributeIfc;
+    }
+
+    @Override
+    public O getOpenType() {
+        return attrOpenType;
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ArrayAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ArrayAttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..30436bb
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping;
+
+import java.lang.reflect.Array;
+import java.util.List;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.OpenType;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+public class ArrayAttributeMappingStrategy extends AbstractAttributeMappingStrategy<List<Object>, ArrayType<?>> {
+
+    private final AttributeMappingStrategy<?, ? extends OpenType<?>> innerElementStrategy;
+
+    public ArrayAttributeMappingStrategy(ArrayType<?> arrayType,
+            AttributeMappingStrategy<?, ? extends OpenType<?>> innerElementStrategy) {
+        super(arrayType);
+        this.innerElementStrategy = innerElementStrategy;
+    }
+
+    @Override
+    public Optional<List<Object>> mapAttribute(Object value) {
+        if (value == null)
+            return Optional.absent();
+
+        Preconditions.checkArgument(value.getClass().isArray(), "Value has to be instanceof Array ");
+
+        List<Object> retVal = Lists.newArrayList();
+
+        for (int i = 0; i < Array.getLength(value); i++) {
+            Object innerValue = Array.get(value, i);
+            // String expectedClassName =
+            // getOpenType().getElementOpenType().getClassName();
+            // String realClassName = value.getClass().getName();
+
+            // Preconditions.checkState(realClassName.contains(expectedClassName),
+            // "Element in collection/array should be of type " +
+            // expectedClassName + " but was "
+            // + realClassName + " for attribute: " + getOpenType());
+
+            Optional<?> mapAttribute = innerElementStrategy.mapAttribute(innerValue);
+
+            if (mapAttribute.isPresent())
+                retVal.add(mapAttribute.get());
+        }
+
+        return Optional.of(retVal);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/AttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/AttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..51dfc58
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping;
+
+import com.google.common.base.Optional;
+
+import javax.management.openmbean.OpenType;
+
+public interface AttributeMappingStrategy<T, O extends OpenType<?>> {
+
+    O getOpenType();
+
+    Optional<T> mapAttribute(Object o);
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/CompositeAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/CompositeAttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..252b13b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import java.util.Map;
+import java.util.Set;
+
+public class CompositeAttributeMappingStrategy extends
+        AbstractAttributeMappingStrategy<Map<String, Object>, CompositeType> {
+
+    private final Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies;
+    private final Map<String, String> jmxToJavaNameMapping;
+
+    public CompositeAttributeMappingStrategy(CompositeType compositeType,
+            Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies,
+            Map<String, String> jmxToJavaNameMapping) {
+        super(compositeType);
+        this.innerStrategies = innerStrategies;
+        this.jmxToJavaNameMapping = jmxToJavaNameMapping;
+    }
+
+    @Override
+    public Optional<Map<String, Object>> mapAttribute(Object value) {
+        if (value == null)
+            return Optional.absent();
+
+        Util.checkType(value, CompositeDataSupport.class);
+
+        CompositeDataSupport compositeData = (CompositeDataSupport) value;
+        CompositeType currentType = compositeData.getCompositeType();
+        CompositeType expectedType = getOpenType();
+
+        Set<String> expectedCompositeTypeKeys = expectedType.keySet();
+        Set<String> currentCompositeTypeKeys = currentType.keySet();
+        Preconditions.checkArgument(expectedCompositeTypeKeys.equals(currentCompositeTypeKeys),
+                "Composite type mismatch, expected composite type with attributes " + expectedCompositeTypeKeys
+                        + " but was " + currentCompositeTypeKeys);
+
+        Map<String, Object> retVal = Maps.newHashMap();
+
+        for (String jmxName : jmxToJavaNameMapping.keySet()) {
+            String innerAttrJmxName = jmxName;
+            Object innerValue = compositeData.get(innerAttrJmxName);
+
+            AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = innerStrategies
+                    .get(innerAttrJmxName);
+            Optional<?> mapAttribute = attributeMappingStrategy.mapAttribute(innerValue);
+            if (mapAttribute.isPresent())
+                retVal.put(jmxToJavaNameMapping.get(innerAttrJmxName), mapAttribute.get());
+        }
+
+        return Optional.of(retVal);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java
new file mode 100644 (file)
index 0000000..52b6801
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.*;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
+
+import com.google.common.collect.Maps;
+
+public class ObjectMapper extends AttributeIfcSwitchStatement<AttributeMappingStrategy<?, ? extends OpenType<?>>> {
+
+    private final Services dependencyTracker;
+
+    public ObjectMapper(Services depTracker) {
+        this.dependencyTracker = depTracker;
+    }
+
+    public Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> prepareMapping(
+            Map<String, AttributeIfc> configDefinition) {
+        Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> strategies = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> attrEntry : configDefinition.entrySet()) {
+            strategies.put(attrEntry.getKey(), prepareStrategy(attrEntry.getValue()));
+        }
+
+        return strategies;
+    }
+
+    private AttributeMappingStrategy<?, ? extends OpenType<?>> prepareStrategy(AttributeIfc attributeIfc) {
+        return switchAttribute(attributeIfc);
+    }
+
+    private Map<String, String> createJmxToYangMapping(TOAttribute attributeIfc) {
+        Map<String, String> retVal = Maps.newHashMap();
+        for (Entry<String, AttributeIfc> entry : attributeIfc.getJmxPropertiesToTypesMap().entrySet()) {
+            retVal.put(entry.getKey(), (entry.getValue()).getAttributeYangName());
+        }
+        return retVal;
+    }
+
+    @Override
+    protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseJavaAttribute(JavaAttribute attributeIfc) {
+
+        if (attributeIfc.getOpenType() instanceof SimpleType<?>)
+            return new SimpleAttributeMappingStrategy((SimpleType<?>) attributeIfc.getOpenType());
+        else if (attributeIfc.getOpenType() instanceof ArrayType<?>) {
+            ArrayType<?> arrayType = (ArrayType<?>) attributeIfc.getOpenType();
+            AttributeMappingStrategy<?, ? extends OpenType<?>> innerStrategy = new SimpleAttributeMappingStrategy(
+                    (SimpleType<?>) arrayType.getElementOpenType());
+            return new ArrayAttributeMappingStrategy(arrayType, innerStrategy);
+        }
+        throw new IllegalStateException(JavaAttribute.class + " can only provide open type " + SimpleType.class
+                + " or " + ArrayType.class);
+    }
+
+    @Override
+    protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseDependencyAttribute(
+            DependencyAttribute attributeIfc) {
+        String serviceName = attributeIfc.getDependency().getSie().getQName().getLocalName();
+        return new ObjectNameAttributeMappingStrategy((SimpleType<?>) attributeIfc.getOpenType(), dependencyTracker,
+                serviceName);
+    }
+
+    @Override
+    protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseTOAttribute(TOAttribute attributeIfc) {
+        Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> innerAttrEntry : attributeIfc.getJmxPropertiesToTypesMap().entrySet()) {
+            innerStrategies.put(innerAttrEntry.getKey(), prepareStrategy(innerAttrEntry.getValue()));
+        }
+
+        return new CompositeAttributeMappingStrategy((CompositeType) attributeIfc.getOpenType(), innerStrategies,
+                createJmxToYangMapping(attributeIfc));
+    }
+
+    @Override
+    protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseListAttribute(ListAttribute attributeIfc) {
+        return new ArrayAttributeMappingStrategy(attributeIfc.getOpenType(),
+                prepareStrategy(attributeIfc.getInnerAttribute()));
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..1febf02
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.SimpleType;
+
+public class ObjectNameAttributeMappingStrategy extends
+        AbstractAttributeMappingStrategy<ObjectNameAttributeMappingStrategy.MappedDependency, SimpleType<?>> {
+
+    private final Services tracker;
+    private final String serviceName;
+
+    public ObjectNameAttributeMappingStrategy(SimpleType<?> openType, Services dependencyTracker, String serviceName) {
+        super(openType);
+        this.tracker = dependencyTracker;
+        this.serviceName = serviceName;
+    }
+
+    @Override
+    public Optional<MappedDependency> mapAttribute(Object value) {
+        if (value == null)
+            return Optional.absent();
+
+        String expectedClass = getOpenType().getClassName();
+        String realClass = value.getClass().getName();
+        Preconditions.checkArgument(realClass.equals(expectedClass), "Type mismatch, expected " + expectedClass
+                + " but was " + realClass);
+        Util.checkType(value, ObjectName.class);
+
+        ObjectName on = (ObjectName) value;
+        String refName = tracker.addServiceEntry(serviceName, on);
+
+        return Optional.of(new MappedDependency(serviceName, refName));
+    }
+
+    public static class MappedDependency {
+        private final String serviceName, refName;
+
+        public MappedDependency(String serviceName, String refName) {
+            this.serviceName = serviceName;
+            this.refName = refName;
+        }
+
+        public String getServiceName() {
+            return serviceName;
+        }
+
+        public String getRefName() {
+            return refName;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("MappedDependency{");
+            sb.append("serviceName='").append(serviceName).append('\'');
+            sb.append(", refName='").append(refName).append('\'');
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/SimpleAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/SimpleAttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..d92b7c4
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+
+import javax.management.openmbean.SimpleType;
+import java.util.Date;
+import java.util.Map;
+
+public class SimpleAttributeMappingStrategy extends AbstractAttributeMappingStrategy<String, SimpleType<?>> {
+
+    public SimpleAttributeMappingStrategy(SimpleType<?> openType) {
+        super(openType);
+    }
+
+    @Override
+    public Optional<String> mapAttribute(Object value) {
+        if (value == null)
+            return Optional.absent();
+
+        String expectedClass = getOpenType().getClassName();
+        String realClass = value.getClass().getName();
+        Preconditions.checkArgument(realClass.equals(expectedClass), "Type mismatch, expected " + expectedClass
+                + " but was " + realClass);
+
+        WriterPlugin prefferedPlugin = writerPlugins.get(value.getClass().getCanonicalName());
+        prefferedPlugin = prefferedPlugin == null ? writerPlugins.get(DEFAULT_WRITER_PLUGIN) : prefferedPlugin;
+        return Optional.of(prefferedPlugin.writeObject(value));
+    }
+
+    private static final String DEFAULT_WRITER_PLUGIN = "default";
+    private static final Map<String, WriterPlugin> writerPlugins = Maps.newHashMap();
+    static {
+        writerPlugins.put(DEFAULT_WRITER_PLUGIN, new DefaultWriterPlugin());
+        writerPlugins.put(Date.class.getCanonicalName(), new DatePlugin());
+    }
+
+    /**
+     * Custom writer plugins must implement this interface.
+     */
+    static interface WriterPlugin {
+        String writeObject(Object value);
+    }
+
+    static class DefaultWriterPlugin implements WriterPlugin {
+
+        @Override
+        public String writeObject(Object value) {
+            return value.toString();
+        }
+    }
+
+    static class DatePlugin implements WriterPlugin {
+
+        @Override
+        public String writeObject(Object value) {
+            Preconditions.checkArgument(value instanceof Date, "Attribute must be Date");
+            return Util.writeDate((Date) value);
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/AbstractAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/AbstractAttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..2808d5d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
+
+import javax.management.openmbean.OpenType;
+
+abstract class AbstractAttributeResolvingStrategy<T, O extends OpenType<?>> implements AttributeResolvingStrategy<T, O> {
+    private final O openType;
+
+    public AbstractAttributeResolvingStrategy(O openType) {
+        this.openType = openType;
+    }
+
+    @Override
+    public O getOpenType() {
+        return openType;
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ArrayAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ArrayAttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..adee8be
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import java.lang.reflect.Array;
+import java.util.List;
+
+final class ArrayAttributeResolvingStrategy extends AbstractAttributeResolvingStrategy<Object, ArrayType<?>> {
+
+    private final AttributeResolvingStrategy<?, ? extends OpenType<?>> innerTypeResolvingStrategy;
+
+    private static final Logger logger = LoggerFactory.getLogger(ArrayAttributeResolvingStrategy.class);
+
+    public ArrayAttributeResolvingStrategy(AttributeResolvingStrategy<?, ? extends OpenType<?>> innerTypeResolved,
+            ArrayType<?> openType) {
+        super(openType);
+        this.innerTypeResolvingStrategy = innerTypeResolved;
+    }
+
+    @Override
+    public Optional<Object> parseAttribute(String attrName, Object value) {
+        if (value == null) {
+            return Optional.absent();
+        }
+
+        Util.checkType(value, List.class);
+        List<?> valueList = (List<?>) value;
+
+        Class<?> innerTypeClass = null;
+
+        if (innerTypeResolvingStrategy.getOpenType() instanceof CompositeType) {
+            innerTypeClass = CompositeDataSupport.class;
+        } else
+            try {
+                innerTypeClass = Class.forName(getOpenType().getElementOpenType().getClassName());
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException("Unable to locate class for "
+                        + getOpenType().getElementOpenType().getClassName(), e);
+            }
+
+        Object parsedArray = null;
+
+        if (getOpenType().isPrimitiveArray()) {
+            Class<?> primitiveType = getPrimitiveType(innerTypeClass);
+            parsedArray = Array.newInstance(primitiveType, valueList.size());
+        } else
+            parsedArray = Array.newInstance(innerTypeClass, valueList.size());
+
+        int i = 0;
+        for (Object innerValue : valueList) {
+            Optional<?> parsedElement = innerTypeResolvingStrategy.parseAttribute(attrName + "_" + i, innerValue);
+
+            if (!parsedElement.isPresent())
+                continue;
+
+            Array.set(parsedArray, i, parsedElement.get());
+            // parsedArray[i] = parsedElement.get();
+            i++;
+        }
+
+        logger.debug("Attribute {} : {} parsed to type {} as {}", attrName, value, getOpenType(),
+                toStringArray(parsedArray));
+
+        return Optional.of(parsedArray);
+    }
+
+    private static String toStringArray(Object array) {
+        StringBuilder build = new StringBuilder(array.toString());
+        build.append(" [");
+        for (int i = 0; i < Array.getLength(array); i++) {
+            build.append(Array.get(array, i).toString());
+            build.append(",");
+        }
+        build.append("]]");
+        return build.toString();
+    }
+
+    private static Class<?> getPrimitiveType(Class<?> innerTypeClass) {
+        try {
+            return (Class<?>) innerTypeClass.getField("TYPE").get(null);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to determine primitive type to " + innerTypeClass);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ResolvedArrayTypeAttributeType [innerTypeResolved=" + innerTypeResolvingStrategy + "]";
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/AttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/AttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..0bb274a
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
+
+import com.google.common.base.Optional;
+
+import javax.management.openmbean.OpenType;
+
+/**
+ * Create real object from String or Map that corresponds to given opentype.
+ */
+public interface AttributeResolvingStrategy<T, O extends OpenType<?>> {
+    O getOpenType();
+
+    Optional<T> parseAttribute(String attrName, Object value);
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..a85f306
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import java.util.Map;
+
+final class CompositeAttributeResolvingStrategy extends
+        AbstractAttributeResolvingStrategy<CompositeDataSupport, CompositeType> {
+    private final Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerTypes;
+    private final Map<String, String> yangToJavaAttrMapping;
+
+    private static final Logger logger = LoggerFactory.getLogger(CompositeAttributeResolvingStrategy.class);
+
+    CompositeAttributeResolvingStrategy(Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerTypes,
+            CompositeType openType, Map<String, String> yangToJavaAttrMapping) {
+        super(openType);
+        this.innerTypes = innerTypes;
+        this.yangToJavaAttrMapping = yangToJavaAttrMapping;
+    }
+
+    @Override
+    public String toString() {
+        return "ResolvedCompositeAttribute [" + innerTypes + "]";
+    }
+
+    @Override
+    public Optional<CompositeDataSupport> parseAttribute(String attrName, Object value) {
+
+        if (value == null) {
+            return Optional.absent();
+        }
+
+        Util.checkType(value, Map.class);
+        Map<?, ?> valueMap = (Map<?, ?>) value;
+
+        Map<String, Object> items = Maps.newHashMap();
+        Map<String, OpenType<?>> openTypes = Maps.newHashMap();
+
+        for (Object innerAttrName : innerTypes.keySet()) {
+            Preconditions.checkState(innerAttrName instanceof String, "Attribute name must be string");
+            String innerAttrNameStr = (String) innerAttrName;
+
+            AttributeResolvingStrategy<?, ? extends OpenType<?>> attributeResolvingStrategy = innerTypes
+                    .get(innerAttrName);
+
+            Object valueToParse = valueMap.get(innerAttrName);
+
+            Optional<?> parsedInnerValue = attributeResolvingStrategy.parseAttribute(innerAttrNameStr, valueToParse);
+
+            openTypes.put(innerAttrNameStr, attributeResolvingStrategy.getOpenType());
+
+            items.put(yangToJavaAttrMapping.get(innerAttrNameStr),
+                    parsedInnerValue.isPresent() ? parsedInnerValue.get() : null);
+        }
+
+        CompositeDataSupport parsedValue = null;
+        try {
+            parsedValue = new CompositeDataSupport(getOpenType(), items);
+        } catch (OpenDataException e) {
+            throw new RuntimeException("An error occured during restoration of composite type " + this
+                    + " for attribute " + attrName + " from value " + value, e);
+        }
+
+        logger.debug("Attribute {} : {} parsed to type {} as {}", attrName, value, getOpenType(), parsedValue);
+
+        return Optional.of(parsedValue);
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..5469015
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services.ServiceInstance;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.SimpleType;
+
+public class ObjectNameAttributeResolvingStrategy extends AbstractAttributeResolvingStrategy<ObjectName, SimpleType<?>> {
+
+    private final Services serviceTracker;
+    private static final Logger logger = LoggerFactory.getLogger(ObjectNameAttributeResolvingStrategy.class);
+
+    ObjectNameAttributeResolvingStrategy(Services serviceTracker) {
+        super(SimpleType.OBJECTNAME);
+        this.serviceTracker = serviceTracker;
+    }
+
+    @Override
+    public Optional<ObjectName> parseAttribute(String attrName, Object value) {
+        if (value == null) {
+            return Optional.absent();
+        }
+
+        Util.checkType(value, ObjectNameAttributeMappingStrategy.MappedDependency.class);
+
+        ObjectNameAttributeMappingStrategy.MappedDependency mappedDep = (ObjectNameAttributeMappingStrategy.MappedDependency) value;
+        ServiceInstance byRefName = serviceTracker.getByServiceAndRefName(mappedDep.getServiceName(),
+                mappedDep.getRefName());
+        ObjectName on = ObjectNameUtil.createReadOnlyModuleON(byRefName.getModuleName(), byRefName.getInstanceName());
+        logger.debug("Attribute {} : {} parsed to type {}", attrName, value, getOpenType());
+        return Optional.of(on);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java
new file mode 100644 (file)
index 0000000..3860471
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.*;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+
+public class ObjectResolver extends AttributeIfcSwitchStatement<AttributeResolvingStrategy<?, ? extends OpenType<?>>> {
+
+    private final Services serviceTracker;
+    private OpenType<?> openType;
+
+    public ObjectResolver(Services serviceTracker) {
+        this.serviceTracker = serviceTracker;
+    }
+
+    public Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> prepareResolving(
+            Map<String, AttributeIfc> configDefinition) {
+        Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> strategies = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> attrEntry : configDefinition.entrySet()) {
+            strategies.put(attrEntry.getKey(),
+                    prepareStrategy(attrEntry.getValue(), attrEntry.getValue().getOpenType()));
+        }
+
+        return strategies;
+    }
+
+    private AttributeResolvingStrategy<?, ? extends OpenType<?>> prepareStrategy(AttributeIfc attributeIfc,
+            OpenType<?> openType) {
+
+        this.openType = openType;
+        return switchAttribute(attributeIfc);
+    }
+
+    private Map<String, String> createYangToJmxMapping(TOAttribute attributeIfc) {
+        Map<String, String> retVal = Maps.newHashMap();
+        for (Entry<String, AttributeIfc> entry : attributeIfc.getYangPropertiesToTypesMap().entrySet()) {
+            retVal.put(entry.getKey(), (entry.getValue()).getLowerCaseCammelCase());
+        }
+        return retVal;
+    }
+
+    @Override
+    protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseJavaAttribute(JavaAttribute attributeIfc) {
+        if (attributeIfc.getOpenType() instanceof SimpleType<?>)
+            return new SimpleAttributeResolvingStrategy((SimpleType<?>) openType);
+        else if (attributeIfc.getOpenType() instanceof ArrayType<?>) {
+            ArrayType<?> arrayType = (ArrayType<?>) openType;
+            SimpleType<?> innerType = (SimpleType<?>) arrayType.getElementOpenType();
+            AttributeResolvingStrategy<?, ? extends OpenType<?>> strat = new SimpleAttributeResolvingStrategy(innerType);
+            return new ArrayAttributeResolvingStrategy(strat, arrayType);
+        }
+        throw new IllegalStateException(JavaAttribute.class + " can only provide open type " + SimpleType.class
+                + " or " + ArrayType.class);
+    }
+
+    @Override
+    protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseDependencyAttribute(
+            DependencyAttribute attributeIfc) {
+        return new ObjectNameAttributeResolvingStrategy(serviceTracker);
+    }
+
+    @Override
+    protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseTOAttribute(TOAttribute attributeIfc) {
+        CompositeType compositeType = (CompositeType) openType;
+        Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap = Maps.newHashMap();
+        for (String innerName : compositeType.keySet()) {
+            Preconditions.checkState(attributeIfc instanceof TOAttribute, "Unexpected state, " + attributeIfc
+                    + " should be instance of " + TOAttribute.class.getName());
+            AttributeIfc innerAttributeIfc = attributeIfc.getJmxPropertiesToTypesMap().get(innerName);
+            innerMap.put(innerAttributeIfc.getAttributeYangName(),
+                    prepareStrategy(innerAttributeIfc, compositeType.getType(innerName)));
+        }
+        return new CompositeAttributeResolvingStrategy(innerMap, compositeType, createYangToJmxMapping(attributeIfc));
+    }
+
+    @Override
+    protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseListAttribute(ListAttribute attributeIfc) {
+        ArrayType<?> arrayType = (ArrayType<?>) openType;
+        OpenType<?> innerType = arrayType.getElementOpenType();
+        AttributeIfc inner = attributeIfc.getInnerAttribute();
+        return new ArrayAttributeResolvingStrategy(prepareStrategy(inner, innerType), arrayType);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/SimpleAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/SimpleAttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..3b88157
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.openmbean.SimpleType;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Map;
+
+final class SimpleAttributeResolvingStrategy extends AbstractAttributeResolvingStrategy<Object, SimpleType<?>> {
+
+    private static final Logger logger = LoggerFactory.getLogger(SimpleAttributeResolvingStrategy.class);
+
+    SimpleAttributeResolvingStrategy(SimpleType<?> simpleType) {
+        super(simpleType);
+    }
+
+    @Override
+    public String toString() {
+        return "ResolvedSimpleAttribute [" + getOpenType().getClassName() + "]";
+    }
+
+    @Override
+    public Optional<Object> parseAttribute(String attrName, Object value) {
+        if (value == null) {
+            return Optional.absent();
+        }
+
+        Class<?> cls;
+        try {
+            cls = Class.forName(getOpenType().getClassName());
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException("Unable to locate class for " + getOpenType().getClassName(), e);
+        }
+
+        Util.checkType(value, String.class);
+
+        Resolver prefferedPlugin = resolverPlugins.get(cls.getCanonicalName());
+        prefferedPlugin = prefferedPlugin == null ? resolverPlugins.get(DEFAULT_RESOLVERS) : prefferedPlugin;
+
+        Object parsedValue = prefferedPlugin.resolveObject(cls, attrName, (String) value);
+        logger.debug("Attribute {} : {} parsed to type {} with value {}", attrName, value, getOpenType(), parsedValue);
+        return Optional.of(parsedValue);
+    }
+
+    private static final String DEFAULT_RESOLVERS = "default";
+    private static final Map<String, Resolver> resolverPlugins = Maps.newHashMap();
+
+    static {
+        resolverPlugins.put(DEFAULT_RESOLVERS, new DefaultResolver());
+        resolverPlugins.put(String.class.getCanonicalName(), new StringResolver());
+        resolverPlugins.put(Date.class.getCanonicalName(), new DateResolver());
+        resolverPlugins.put(Character.class.getCanonicalName(), new CharResolver());
+        resolverPlugins.put(BigInteger.class.getCanonicalName(), new BigIntegerResolver());
+    }
+
+    static interface Resolver {
+        Object resolveObject(Class<?> type, String attrName, String value);
+    }
+
+    static class DefaultResolver implements Resolver {
+
+        @Override
+        public Object resolveObject(Class<?> type, String attrName, String value) {
+            try {
+                Object parsedValue = parseObject(type, value);
+                return parsedValue;
+            } catch (Exception e) {
+                throw new RuntimeException("Unable to resolve attribute " + attrName + " from " + value, e);
+            }
+        }
+
+        protected Object parseObject(Class<?> type, String value) throws Exception {
+            Method method = type.getMethod("valueOf", String.class);
+            Object parsedValue = method.invoke(null, value);
+            return parsedValue;
+        }
+    }
+
+    static class StringResolver extends DefaultResolver {
+
+        @Override
+        protected Object parseObject(Class<?> type, String value) throws Exception {
+            return value;
+        }
+    }
+
+    static class BigIntegerResolver extends DefaultResolver {
+
+        @Override
+        protected Object parseObject(Class<?> type, String value) throws Exception {
+            return new BigInteger(value);
+        }
+    }
+
+    static class CharResolver extends DefaultResolver {
+
+        @Override
+        protected Object parseObject(Class<?> type, String value) throws Exception {
+            return new Character(value.charAt(0));
+        }
+    }
+
+    static class DateResolver extends DefaultResolver {
+
+        @Override
+        protected Object parseObject(Class<?> type, String value) throws Exception {
+            return Util.readDate(value);
+        }
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ArrayAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ArrayAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..89dc251
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import java.util.List;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.w3c.dom.Element;
+
+public class ArrayAttributeWritingStrategy implements AttributeWritingStrategy {
+
+    private final AttributeWritingStrategy innnerStrategy;
+
+    public ArrayAttributeWritingStrategy(AttributeWritingStrategy innerStrategy) {
+        this.innnerStrategy = innerStrategy;
+    }
+
+    @Override
+    public void writeElement(Element parentElement, String namespace, Object value) {
+        Util.checkType(value, List.class);
+
+        for (Object innerObject : ((List<?>) value)) {
+            innnerStrategy.writeElement(parentElement, namespace, innerObject);
+        }
+
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/AttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/AttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..d0c2b88
--- /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.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import org.w3c.dom.Element;
+
+public interface AttributeWritingStrategy {
+
+    void writeElement(Element parentElement, String namespace, Object value);
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/CompositeAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/CompositeAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..d1326bd
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class CompositeAttributeWritingStrategy implements AttributeWritingStrategy {
+
+    protected final String key;
+    protected final Document document;
+    protected final Map<String, AttributeWritingStrategy> innerStrats;
+
+    public CompositeAttributeWritingStrategy(Document document, String key,
+            Map<String, AttributeWritingStrategy> innerStrats) {
+        this.document = document;
+        this.key = key;
+        this.innerStrats = innerStrats;
+    }
+
+    @Override
+    public void writeElement(Element parentElement, String namespace, Object value) {
+        Util.checkType(value, Map.class);
+
+        Element innerNode = document.createElement(key);
+        XmlUtil.addNamespaceAttr(innerNode, namespace);
+
+        Map<?, ?> map = (Map<?, ?>) value;
+
+        for (Entry<?, ?> innerObjectEntry : map.entrySet()) {
+            Util.checkType(innerObjectEntry.getKey(), String.class);
+
+            String innerKey = (String) innerObjectEntry.getKey();
+            Object innerValue = innerObjectEntry.getValue();
+
+            innerStrats.get(innerKey).writeElement(innerNode, namespace, innerValue);
+        }
+        parentElement.appendChild(innerNode);
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectNameAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectNameAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..b88b672
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class ObjectNameAttributeWritingStrategy implements AttributeWritingStrategy {
+
+    private final Document document;
+    private final String key;
+
+    /**
+     * @param document
+     * @param key
+     */
+    public ObjectNameAttributeWritingStrategy(Document document, String key) {
+        this.document = document;
+        this.key = key;
+    }
+
+    @Override
+    public void writeElement(Element parentElement, String namespace, Object value) {
+        Util.checkType(value, ObjectNameAttributeMappingStrategy.MappedDependency.class);
+        Element innerNode = document.createElement(key);
+        XmlUtil.addNamespaceAttr(innerNode, namespace);
+
+        String moduleName = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getServiceName();
+        String refName = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getRefName();
+
+        final Element typeElement = XmlUtil.createTextElement(document, XmlNetconfConstants.TYPE_KEY, moduleName);
+        innerNode.appendChild(typeElement);
+
+        final Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, refName);
+        innerNode.appendChild(nameElement);
+
+        parentElement.appendChild(innerNode);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java
new file mode 100644 (file)
index 0000000..b49d20e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.*;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
+import org.w3c.dom.Document;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.SimpleType;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class ObjectXmlWriter extends AttributeIfcSwitchStatement<AttributeWritingStrategy> {
+
+    private Document document;
+    private String key;
+
+    public Map<String, AttributeWritingStrategy> prepareWriting(Map<String, AttributeIfc> yangToAttrConfig,
+            Document document) {
+
+        Map<String, AttributeWritingStrategy> preparedWriting = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> mappedAttributeEntry : yangToAttrConfig.entrySet()) {
+            String key = mappedAttributeEntry.getKey();
+            AttributeIfc value = mappedAttributeEntry.getValue();
+            AttributeWritingStrategy strat = prepareWritingStrategy(key, value, document);
+            preparedWriting.put(key, strat);
+        }
+
+        return preparedWriting;
+    }
+
+    private AttributeWritingStrategy prepareWritingStrategy(String key, AttributeIfc expectedAttr, Document document) {
+        Preconditions.checkNotNull(expectedAttr, "Mbean attributes mismatch, unable to find expected attribute for %s",
+                key);
+        this.document = document;
+        this.key = key;
+        return switchAttribute(expectedAttr);
+    }
+
+    @Override
+    protected AttributeWritingStrategy caseJavaAttribute(JavaAttribute attributeIfc) {
+
+        if (attributeIfc.getOpenType() instanceof SimpleType<?>)
+            return new SimpleAttributeWritingStrategy(document, key);
+        else if (attributeIfc.getOpenType() instanceof ArrayType<?>) {
+            AttributeWritingStrategy innerStrategy = new SimpleAttributeWritingStrategy(document, key);
+            return new ArrayAttributeWritingStrategy(innerStrategy);
+        }
+        throw new IllegalStateException(JavaAttribute.class + " can only provide open type " + SimpleType.class
+                + " or " + ArrayType.class);
+    }
+
+    @Override
+    protected AttributeWritingStrategy caseDependencyAttribute(DependencyAttribute attributeIfc) {
+        return new ObjectNameAttributeWritingStrategy(document, key);
+    }
+
+    @Override
+    protected AttributeWritingStrategy caseTOAttribute(TOAttribute attributeIfc) {
+        Map<String, AttributeWritingStrategy> innerStrats = Maps.newHashMap();
+        String currentKey = key;
+        for (Entry<String, AttributeIfc> innerAttrEntry : attributeIfc.getYangPropertiesToTypesMap().entrySet()) {
+
+            AttributeWritingStrategy innerStrategy = prepareWritingStrategy(innerAttrEntry.getKey(),
+                    innerAttrEntry.getValue(), document);
+            innerStrats.put(innerAttrEntry.getKey(), innerStrategy);
+        }
+
+        return new CompositeAttributeWritingStrategy(document, currentKey, innerStrats);
+    }
+
+    @Override
+    protected AttributeWritingStrategy caseListAttribute(ListAttribute attributeIfc) {
+        AttributeIfc inner = attributeIfc.getInnerAttribute();
+        AttributeWritingStrategy innerStrategy = prepareWritingStrategy(key, inner, document);
+        return new ArrayAttributeWritingStrategy(innerStrategy);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/RuntimeBeanEntryWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/RuntimeBeanEntryWritingStrategy.java
new file mode 100644 (file)
index 0000000..a67b348
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class RuntimeBeanEntryWritingStrategy extends CompositeAttributeWritingStrategy {
+
+    public RuntimeBeanEntryWritingStrategy(Document document, String key,
+            Map<String, AttributeWritingStrategy> innerStrats) {
+        super(document, key, innerStrats);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.controller.config.netconf.mapping.attributes.toxml.
+     * AttributeWritingStrategy#writeElement(org.w3c.dom.Element,
+     * java.lang.Object)
+     */
+    @Override
+    public void writeElement(Element parentElement, String namespace, Object value) {
+        Util.checkType(value, Map.class);
+
+        Element innerNode = document.createElement(key);
+
+        Map<?, ?> map = (Map<?, ?>) value;
+
+        for (Entry<?, ?> runtimeBeanInstanceMappingEntry : map.entrySet()) {
+
+            // wrap runtime attributes with number assigned to current runtime
+            // bean
+            Util.checkType(runtimeBeanInstanceMappingEntry.getValue(), Map.class);
+            Map<?, ?> innerMap = (Map<?, ?>) runtimeBeanInstanceMappingEntry.getValue();
+            Element runtimeInstanceNode = document.createElement("_"
+                    + (String) runtimeBeanInstanceMappingEntry.getKey());
+            innerNode.appendChild(runtimeInstanceNode);
+
+            for (Entry<?, ?> innerObjectEntry : innerMap.entrySet()) {
+
+                Util.checkType(innerObjectEntry.getKey(), String.class);
+
+                String innerKey = (String) innerObjectEntry.getKey();
+                Object innerValue = innerObjectEntry.getValue();
+
+                innerStrats.get(innerKey).writeElement(runtimeInstanceNode, namespace, innerValue);
+            }
+        }
+        parentElement.appendChild(innerNode);
+
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..514183b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class SimpleAttributeWritingStrategy implements AttributeWritingStrategy {
+
+    private final Document document;
+    private final String key;
+
+    /**
+     * @param document
+     * @param key
+     */
+    public SimpleAttributeWritingStrategy(Document document, String key) {
+        this.document = document;
+        this.key = key;
+    }
+
+    @Override
+    public void writeElement(Element parentElement, String namespace, Object value) {
+        Util.checkType(value, String.class);
+        Element innerNode = XmlUtil.createTextElement(document, key, (String) value);
+        XmlUtil.addNamespaceAttr(innerNode, namespace);
+        parentElement.appendChild(innerNode);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java
new file mode 100644 (file)
index 0000000..b17a8a8
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.management.ObjectName;
+import java.util.*;
+import java.util.Map.Entry;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+
+public class Config {
+
+    private final Map<String, Map<String, ModuleConfig>> moduleConfigs;
+
+    public Config(Map<String, Map<String, ModuleConfig>> moduleConfigs) {
+        this.moduleConfigs = moduleConfigs;
+    }
+
+    private Map<String, Map<String, Collection<ObjectName>>> getMappedInstances(Set<ObjectName> instancesToMap,
+            Services serviceTracker) {
+        Multimap<String, ObjectName> moduleToInstances = mapInstancesToModules(instancesToMap);
+
+        Map<String, Map<String, Collection<ObjectName>>> retVal = Maps.newLinkedHashMap();
+
+        for (String namespace : moduleConfigs.keySet()) {
+
+            Map<String, Collection<ObjectName>> innerRetVal = Maps.newHashMap();
+
+            for (Entry<String, ModuleConfig> mbeEntry : moduleConfigs.get(namespace).entrySet()) {
+
+                String moduleName = mbeEntry.getKey();
+                Collection<ObjectName> instances = moduleToInstances.get(moduleName);
+
+                if (instances == null)
+                    continue;
+
+                innerRetVal.put(moduleName, instances);
+
+                // All found instances add to service tracker in advance
+                // This way all instances will be serialized as all available
+                // services when get-config is triggered
+                // (even if they are not used as services by other onstances)
+                // = more user friendly
+                addServices(serviceTracker, instances, mbeEntry.getValue().getProvidedServices());
+
+            }
+
+            retVal.put(namespace, innerRetVal);
+        }
+        return retVal;
+    }
+
+    private void addServices(Services serviceTracker, Collection<ObjectName> instances,
+            Collection<String> providedServices) {
+        for (ObjectName instanceOn : instances) {
+            for (String serviceName : providedServices) {
+                serviceTracker.addServiceEntry(serviceName, instanceOn);
+            }
+        }
+    }
+
+    private static Multimap<String, ObjectName> mapInstancesToModules(Set<ObjectName> instancesToMap) {
+        Multimap<String, ObjectName> retVal = HashMultimap.create();
+
+        for (ObjectName objectName : instancesToMap) {
+            String factoryName = ObjectNameUtil.getFactoryName(objectName);
+            retVal.put(factoryName, objectName);
+        }
+        return retVal;
+    }
+
+    // public Element toXml(Set<ObjectName> instancesToMap, String namespace,
+    // Document document) {
+    // return toXml(instancesToMap, Optional.of(namespace), document);
+    // }
+
+    public Element toXml(Set<ObjectName> instancesToMap, Optional<String> maybeNamespace, Document document,
+            Element dataElement) {
+        Services serviceTracker = new Services();
+
+        Map<String, Map<String, Collection<ObjectName>>> moduleToInstances = getMappedInstances(instancesToMap,
+                serviceTracker);
+
+        Element root = dataElement;
+        if (maybeNamespace.isPresent()) {
+            XmlUtil.addNamespaceAttr(root, maybeNamespace.get());
+        }
+
+        Element modulesElement = document.createElement(XmlNetconfConstants.MODULES_KEY);
+        XmlUtil.addNamespaceAttr(modulesElement,
+                XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+        root.appendChild(modulesElement);
+        for (String moduleNamespace : moduleToInstances.keySet()) {
+            for (Entry<String, Collection<ObjectName>> moduleMappingEntry : moduleToInstances.get(moduleNamespace)
+                    .entrySet()) {
+
+                ModuleConfig mapping = moduleConfigs.get(moduleNamespace).get(moduleMappingEntry.getKey());
+
+                if (moduleMappingEntry.getValue().isEmpty()) {
+                    addEmptyModulesCommented(document, modulesElement, moduleNamespace, moduleMappingEntry);
+                } else {
+                    for (ObjectName objectName : moduleMappingEntry.getValue()) {
+                        modulesElement
+                                .appendChild(mapping.toXml(objectName, serviceTracker, document, moduleNamespace));
+                    }
+                }
+
+            }
+        }
+
+        root.appendChild(serviceTracker.toXml(serviceTracker.getMappedServices(), document));
+
+        return root;
+    }
+
+    private void addEmptyModulesCommented(Document document, Element root, String moduleNamespace,
+            Entry<String, Collection<ObjectName>> moduleMappingEntry) {
+        Element emptyModule = document.createElement(XmlNetconfConstants.MODULE_KEY);
+
+        Element typeElement = XmlUtil.createTextElement(document, XmlNetconfConstants.TYPE_KEY,
+                moduleMappingEntry.getKey());
+        emptyModule.appendChild(typeElement);
+
+        root.appendChild(document.createComment(XmlUtil.toString(emptyModule, false)));
+    }
+
+    // TODO refactor, replace string representing namespace with namespace class
+    // TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved
+    // class
+    public Map<String, Multimap<String, ModuleElementResolved>> fromXml(XmlElement xml) {
+        Map<String, Multimap<String, ModuleElementResolved>> retVal = Maps.newHashMap();
+
+        List<XmlElement> recognisedChildren = Lists.newArrayList();
+
+        Services serviceTracker = fromXmlServices(xml, recognisedChildren);
+        List<XmlElement> moduleElements = fromXmlModules(xml, recognisedChildren);
+
+        xml.checkUnrecognisedElements(recognisedChildren);
+
+        for (XmlElement moduleElement : moduleElements) {
+            resolveModule(retVal, serviceTracker, moduleElement);
+        }
+
+        return retVal;
+    }
+
+    private List<XmlElement> fromXmlModules(XmlElement xml, List<XmlElement> recognisedChildren) {
+        Optional<XmlElement> modulesElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.MODULES_KEY,
+                XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+        List<XmlElement> moduleElements;
+        if (modulesElement.isPresent()) {
+            moduleElements = modulesElement.get().getChildElementsWithSameNamespace(XmlNetconfConstants.MODULE_KEY);
+            recognisedChildren.add(modulesElement.get());
+            modulesElement.get().checkUnrecognisedElements(moduleElements);
+        } else {
+            moduleElements = Lists.newArrayList();
+        }
+        return moduleElements;
+    }
+
+    private void resolveModule(Map<String, Multimap<String, ModuleElementResolved>> retVal, Services serviceTracker,
+            XmlElement moduleElement) {
+        XmlElement typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+        Entry<String, String> prefixToNamespace = typeElement.findNamespaceOfTextContent();
+        String moduleNamespace = prefixToNamespace.getValue();
+        XmlElement nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
+        String instanceName = nameElement.getTextContent();
+        String factoryNameWithPrefix = typeElement.getTextContent();
+        String prefixOrEmptyString = prefixToNamespace.getKey();
+        String factoryName = getFactoryName(factoryNameWithPrefix, prefixOrEmptyString);
+
+        ModuleConfig moduleMapping = getModuleMapping(moduleNamespace, instanceName, factoryName);
+
+        Multimap<String, ModuleElementResolved> innerMap = retVal.get(moduleNamespace);
+        if (innerMap == null) {
+            innerMap = HashMultimap.create();
+            retVal.put(moduleNamespace, innerMap);
+        }
+
+        ModuleElementResolved moduleElementResolved = moduleMapping.fromXml(moduleElement, serviceTracker,
+                instanceName, moduleNamespace);
+
+        innerMap.put(factoryName, moduleElementResolved);
+    }
+
+    private Services fromXmlServices(XmlElement xml, List<XmlElement> recognisedChildren) {
+        Optional<XmlElement> servicesElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.SERVICES_KEY,
+                XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+
+        Map<String, Map<String, String>> mappedServices;
+        if (servicesElement.isPresent()) {
+            mappedServices = Services.fromXml(servicesElement.get());
+            recognisedChildren.add(servicesElement.get());
+        } else {
+            mappedServices = new HashMap<>();
+        }
+
+        return Services.resolveServices(mappedServices);
+    }
+
+    private String getFactoryName(String factoryNameWithPrefix, String prefixOrEmptyString) {
+        checkState(
+                factoryNameWithPrefix.startsWith(prefixOrEmptyString),
+                format("Internal error: text " + "content '%s' of type node does not start with prefix '%s'",
+                        factoryNameWithPrefix, prefixOrEmptyString));
+
+        int factoryNameAfterPrefixIndex;
+        if (prefixOrEmptyString.isEmpty()) {
+            factoryNameAfterPrefixIndex = 0;
+        } else {
+            factoryNameAfterPrefixIndex = prefixOrEmptyString.length() + 1;
+        }
+        return factoryNameWithPrefix.substring(factoryNameAfterPrefixIndex);
+    }
+
+    private ModuleConfig getModuleMapping(String moduleNamespace, String instanceName, String factoryName) {
+        Map<String, ModuleConfig> mappingsFromNamespace = moduleConfigs.get(moduleNamespace);
+
+        Preconditions.checkNotNull(mappingsFromNamespace,
+                "Namespace %s, defined in: module %s of type %s not found, available namespaces: %s", moduleNamespace,
+                instanceName, factoryName, moduleConfigs.keySet());
+
+        ModuleConfig moduleMapping = mappingsFromNamespace.get(factoryName);
+        checkState(moduleMapping != null, "Cannot find mapping for module type " + factoryName);
+        return moduleMapping;
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java
new file mode 100644 (file)
index 0000000..d1ba0b0
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.AttributeMappingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectMapper;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.ObjectResolver;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.AttributeWritingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.ObjectXmlWriter;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenType;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public final class InstanceConfig {
+    private static final Logger logger = LoggerFactory.getLogger(InstanceConfig.class);
+
+    private final Map<String, AttributeIfc> yangToAttrConfig;
+    private final Map<String, AttributeIfc> jmxToAttrConfig;
+    private final ConfigRegistryClient configRegistryClient;
+
+    public InstanceConfig(ConfigRegistryClient configRegistryClient, Map<String, AttributeIfc> yangNamesToAttributes) {
+        this.yangToAttrConfig = yangNamesToAttributes;
+        this.jmxToAttrConfig = reverseMap(yangNamesToAttributes);
+        this.configRegistryClient = configRegistryClient;
+    }
+
+    private Map<String, Object> getMappedConfiguration(ObjectName on, Services depTracker) {
+
+        // TODO make field, mappingStrategies can be instantiated only once
+        Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> mappingStrategies = new ObjectMapper(depTracker)
+                .prepareMapping(jmxToAttrConfig);
+
+        Map<String, Object> toXml = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> configDefEntry : jmxToAttrConfig.entrySet()) {
+
+            // Skip children runtime beans as they are mapped by InstanceRuntime
+            if (configDefEntry.getValue() instanceof RuntimeBeanEntry)
+                continue;
+
+            Object value = configRegistryClient.getAttributeCurrentValue(on, configDefEntry.getKey());
+            try {
+                AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = mappingStrategies
+                        .get(configDefEntry.getKey());
+                Optional<?> a = attributeMappingStrategy.mapAttribute(value);
+                if (a.isPresent() == false)
+                    continue;
+
+                toXml.put(configDefEntry.getValue().getAttributeYangName(), a.get());
+            } catch (Exception e) {
+                throw new IllegalStateException("Unable to map value " + value + " to attribute "
+                        + configDefEntry.getKey(), e);
+            }
+        }
+
+        return toXml;
+    }
+
+    public Element toXml(ObjectName on, Services depTracker, String namespace, Document document, Element rootElement) {
+
+        Element cfgElement = rootElement;
+
+        Map<String, AttributeWritingStrategy> strats = new ObjectXmlWriter().prepareWriting(yangToAttrConfig, document);
+
+        Map<String, Object> mappedConfig = getMappedConfiguration(on, depTracker);
+
+        for (Entry<String, ?> mappingEntry : mappedConfig.entrySet()) {
+            try {
+                strats.get(mappingEntry.getKey()).writeElement(cfgElement, namespace, mappingEntry.getValue());
+            } catch (Exception e) {
+                throw new IllegalStateException("Unable to write value " + mappingEntry.getValue() + " for attribute "
+                        + mappingEntry.getValue(), e);
+            }
+        }
+
+        return cfgElement;
+    }
+
+    private void resolveConfiguration(InstanceConfigElementResolved mappedConfig, Services depTracker) {
+
+        // TODO make field, resolvingStrategies can be instantiated only once
+        Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> resolvingStrategies = new ObjectResolver(
+                depTracker).prepareResolving(yangToAttrConfig);
+
+        for (Entry<String, AttributeConfigElement> configDefEntry : mappedConfig.getConfiguration().entrySet()) {
+            try {
+
+                AttributeResolvingStrategy<?, ? extends OpenType<?>> attributeResolvingStrategy = resolvingStrategies
+                        .get(configDefEntry.getKey());
+
+                configDefEntry.getValue().resolveValue(attributeResolvingStrategy, configDefEntry.getKey());
+                configDefEntry.getValue().setJmxName(
+                        yangToAttrConfig.get(configDefEntry.getKey()).getUpperCaseCammelCase());
+            } catch (Exception e) {
+                throw new IllegalStateException("Unable to resolve value " + configDefEntry.getValue()
+                        + " to attribute " + configDefEntry.getKey(), e);
+            }
+        }
+    }
+
+    public InstanceConfigElementResolved fromXml(XmlElement moduleElement, Services services, String moduleNamespace) {
+        Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
+
+        Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
+        List<XmlElement> recognisedChildren = Lists.newArrayList();
+
+        XmlElement type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+        XmlElement name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
+        List<XmlElement> typeAndName = Lists.newArrayList(type, name);
+
+        for (Entry<String, AttributeReadingStrategy> readStratEntry : strats.entrySet()) {
+            List<XmlElement> configNodes = getConfigNodes(moduleElement, moduleNamespace, readStratEntry.getKey(),
+                    recognisedChildren, typeAndName);
+            AttributeConfigElement readElement = readStratEntry.getValue().readElement(configNodes);
+            retVal.put(readStratEntry.getKey(), readElement);
+        }
+
+        recognisedChildren.addAll(typeAndName);
+        moduleElement.checkUnrecognisedElements(recognisedChildren);
+
+        // TODO: add check for conflicts between global and local edit strategy
+        String perInstanceEditStrategy = moduleElement.getAttribute(XmlNetconfConstants.OPERATION_ATTR_KEY,
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+
+        InstanceConfigElementResolved instanceConfigElementResolved = perInstanceEditStrategy.equals("") ? new InstanceConfigElementResolved(
+                retVal) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal);
+
+        resolveConfiguration(instanceConfigElementResolved, services);
+        return instanceConfigElementResolved;
+    }
+
+    private List<XmlElement> getConfigNodes(XmlElement moduleElement, String moduleNamespace, String name,
+            List<XmlElement> recognisedChildren, List<XmlElement> typeAndName) {
+        List<XmlElement> foundConfigNodes = moduleElement.getChildElementsWithinNamespace(name, moduleNamespace);
+        if (foundConfigNodes.isEmpty()) {
+            logger.debug("No config nodes {}:{} found in {}", moduleNamespace, name, moduleElement);
+            logger.debug("Trying lookup of config nodes without specified namespace");
+            foundConfigNodes = moduleElement.getChildElementsWithinNamespace(name,
+                    XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+            // In case module type or name element is not present in config it
+            // would be matched with config type or name
+            // We need to remove config type and name from available module
+            // config elements
+            foundConfigNodes.removeAll(typeAndName);
+            logger.debug("Found {} config nodes {} without specified namespace in {}", foundConfigNodes.size(), name,
+                    moduleElement);
+        } else {
+            List<XmlElement> foundWithoutNamespaceNodes = moduleElement.getChildElementsWithinNamespace(name,
+                    XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+            foundWithoutNamespaceNodes.removeAll(typeAndName);
+            Preconditions.checkState(foundWithoutNamespaceNodes.isEmpty(),
+                    "Element %s present multiple times with different namespaces: %s, %s", name, foundConfigNodes,
+                    foundWithoutNamespaceNodes);
+        }
+
+        recognisedChildren.addAll(foundConfigNodes);
+        return foundConfigNodes;
+    }
+
+    private static Map<String, AttributeIfc> reverseMap(Map<String, AttributeIfc> yangNameToAttr) {
+        Map<String, AttributeIfc> reversednameToAtr = Maps.newHashMap();
+
+        for (Entry<String, AttributeIfc> entry : yangNameToAttr.entrySet()) {
+            reversednameToAtr.put(entry.getValue().getUpperCaseCammelCase(), entry.getValue());
+        }
+
+        return reversednameToAtr;
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java
new file mode 100644 (file)
index 0000000..6624fc1
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
+
+import java.util.Map;
+
+/**
+ * Parsed xml element containing whole configuration for an instance of some
+ * module. Contains preferred edit strategy type.
+ */
+public class InstanceConfigElementResolved {
+
+    private final EditStrategyType editStrategy;
+    private final Map<String, AttributeConfigElement> configuration;
+
+    public InstanceConfigElementResolved(String strat, Map<String, AttributeConfigElement> configuration) {
+        EditStrategyType valueOf = checkStrategy(strat);
+        this.editStrategy = valueOf;
+        this.configuration = configuration;
+    }
+
+    EditStrategyType checkStrategy(String strat) {
+        EditStrategyType valueOf = EditStrategyType.valueOf(strat);
+        if (EditStrategyType.defaultStrategy().isEnforcing()) {
+            Preconditions
+                    .checkArgument(
+                            valueOf == EditStrategyType.defaultStrategy(),
+                            "With "
+                                    + EditStrategyType.defaultStrategy()
+                                    + " as "
+                                    + EditConfigXmlParser.DEFAULT_OPERATION_KEY
+                                    + " operations on module elements are not permitted since the default option is restrictive");
+        }
+        return valueOf;
+    }
+
+    public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration) {
+        editStrategy = EditStrategyType.defaultStrategy();
+        this.configuration = configuration;
+    }
+
+    public EditConfigStrategy getEditStrategy() {
+        return editStrategy.getFittingStrategy();
+    }
+
+    public Map<String, AttributeConfigElement> getConfiguration() {
+        return configuration;
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java
new file mode 100644 (file)
index 0000000..3a0c547
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.management.ObjectName;
+import java.util.Collection;
+import java.util.Collections;
+
+public class ModuleConfig {
+
+    private final String moduleName;
+    private final InstanceConfig instanceConfig;
+    private final Collection<String> providedServices;
+
+    public ModuleConfig(String moduleName, InstanceConfig mbeanMapping, Collection<String> providedServices) {
+        this.moduleName = moduleName;
+        this.instanceConfig = mbeanMapping;
+        this.providedServices = providedServices;
+    }
+
+    public ModuleConfig(String key, InstanceConfig instanceConfig) {
+        this(key, instanceConfig, Collections.<String> emptyList());
+    }
+
+    public InstanceConfig getMbeanMapping() {
+        return instanceConfig;
+    }
+
+    public Collection<String> getProvidedServices() {
+        return providedServices;
+    }
+
+    public Element toXml(ObjectName instanceON, Services depTracker, Document document, String namespace) {
+        Element root = document.createElement(XmlNetconfConstants.MODULE_KEY);
+        // Xml.addNamespaceAttr(document, root, namespace);
+
+        final String prefix = getPrefix(namespace);
+        Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlNetconfConstants.TYPE_KEY, prefix,
+                moduleName);
+        XmlUtil.addPrefixedNamespaceAttr(typeElement, prefix, namespace);
+        // Xml.addNamespaceAttr(document, typeElement,
+        // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+        root.appendChild(typeElement);
+
+        Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY,
+                ObjectNameUtil.getInstanceName(instanceON));
+        // Xml.addNamespaceAttr(document, nameElement,
+        // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+        root.appendChild(nameElement);
+
+        root = instanceConfig.toXml(instanceON, depTracker, namespace, document, root);
+
+        return root;
+    }
+
+    private String getPrefix(String namespace) {
+        // if(namespace.contains(":")==false)
+        return "prefix";
+        // return namespace.substring(namespace.lastIndexOf(':') + 1,
+        // namespace.length());
+
+    }
+
+    public ModuleElementResolved fromXml(XmlElement moduleElement, Services depTracker, String instanceName,
+            String moduleNamespace) {
+
+        InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace);
+        return new ModuleElementResolved(instanceName, ice);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementResolved.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleElementResolved.java
new file mode 100644 (file)
index 0000000..6d2936c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+
+public class ModuleElementResolved {
+
+    private final String instanceName;
+    private final InstanceConfigElementResolved instanceConfigElementResolved;
+
+    public ModuleElementResolved(String instanceName, InstanceConfigElementResolved instanceConfigElementResolved) {
+        this.instanceName = instanceName;
+        this.instanceConfigElementResolved = instanceConfigElementResolved;
+    }
+
+    public String getInstanceName() {
+        return instanceName;
+    }
+
+    public InstanceConfigElementResolved getInstanceConfigElementResolved() {
+        return instanceConfigElementResolved;
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java
new file mode 100644 (file)
index 0000000..7e4b6c2
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.annotation.Nullable;
+import javax.management.ObjectName;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class Services {
+
+    private static final String PROVIDER_KEY = "provider";
+    private static final String NAME_KEY = "name";
+    public static final String TYPE_KEY = "type";
+    public static final String SERVICE_KEY = "service";
+
+    private long suffix = 1;
+
+    private final Map<ServiceInstance, String> instanceToRef = Maps.newHashMap();
+    private final Map<String/* ServiceName */, Map<String/* refName */, ServiceInstance>> serviceNameToRefNameToInstance = Maps
+            .newHashMap();
+
+    public String addServiceEntry(String serviceName, ObjectName on) {
+
+        String moduleName = on.getKeyProperty("moduleFactoryName");
+        String instanceName = on.getKeyProperty("instanceName");
+
+        return addServiceEntry(serviceName, moduleName, instanceName);
+    }
+
+    public String addServiceEntry(String serviceName, String moduleName, String instanceName) {
+        ServiceInstance serviceInstance = new ServiceInstance(moduleName, instanceName);
+        serviceInstance.setServiceName(serviceName);
+
+        String refName = instanceToRef.get(serviceInstance);
+
+        Map<String, ServiceInstance> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
+        if (refNameToInstance == null) {
+            refNameToInstance = Maps.newHashMap();
+            serviceNameToRefNameToInstance.put(serviceName, refNameToInstance);
+        }
+
+        if (refName != null) {
+            if (serviceNameToRefNameToInstance.get(serviceName).containsKey(moduleName) == false) {
+                refNameToInstance.put(refName, serviceInstance);
+            }
+            return refName;
+        } else {
+            refName = "ref_" + instanceName;
+
+            final Set<String> refNamesAsSet = toSet(instanceToRef.values());
+            if (refNamesAsSet.contains(refName)) {
+                refName = findAvailableRefName(refName, refNamesAsSet);
+            }
+
+            instanceToRef.put(serviceInstance, refName);
+            refNameToInstance.put(refName, serviceInstance);
+
+            return refName;
+        }
+    }
+
+    private Set<String> toSet(Collection<String> values) {
+        Set<String> refNamesAsSet = Sets.newHashSet();
+
+        for (String refName : values) {
+            boolean resultAdd = refNamesAsSet.add(refName);
+            Preconditions.checkState(resultAdd,
+                    "Error occurred building services element, reference name {} was present twice", refName);
+        }
+
+        return refNamesAsSet;
+    }
+
+    public ServiceInstance getByServiceAndRefName(String serviceName, String refName) {
+        Map<String, ServiceInstance> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
+        Preconditions.checkArgument(refNameToInstance != null, "No serviceInstances mapped to " + serviceName + " , "
+                + serviceNameToRefNameToInstance.keySet());
+
+        ServiceInstance serviceInstance = refNameToInstance.get(refName);
+        Preconditions.checkArgument(serviceInstance != null, "No serviceInstance mapped to " + refName
+                + " under service name " + serviceName + " , " + refNameToInstance.keySet());
+        return serviceInstance;
+    }
+
+    // TODO hide getMappedServices, call it explicitly in toXml
+
+    public Map<String, Map<String, String>> getMappedServices() {
+        Map<String, Map<String, String>> retVal = Maps.newHashMap();
+
+        for (String serviceName : serviceNameToRefNameToInstance.keySet()) {
+
+            Map<String, String> innerRetVal = Maps.transformValues(serviceNameToRefNameToInstance.get(serviceName),
+                    new Function<ServiceInstance, String>() {
+                        @Nullable
+                        @Override
+                        public String apply(@Nullable ServiceInstance serviceInstance) {
+                            return serviceInstance.toString();
+                        }
+                    });
+            retVal.put(serviceName, innerRetVal);
+        }
+
+        return retVal;
+    }
+
+    // TODO hide resolveServices, call it explicitly in fromXml
+
+    public static Services resolveServices(Map<String, Map<String, String>> mappedServices) {
+        Services tracker = new Services();
+
+        for (Entry<String, Map<String, String>> serviceEntry : mappedServices.entrySet()) {
+
+            String serviceName = serviceEntry.getKey();
+            for (Entry<String, String> refEntry : serviceEntry.getValue().entrySet()) {
+
+                Map<String, ServiceInstance> refNameToInstance = tracker.serviceNameToRefNameToInstance
+                        .get(serviceName);
+                if (refNameToInstance == null) {
+                    refNameToInstance = Maps.newHashMap();
+                    tracker.serviceNameToRefNameToInstance.put(serviceName, refNameToInstance);
+                }
+
+                String refName = refEntry.getKey();
+                Preconditions.checkState(false == refNameToInstance.containsKey(refName),
+                        "Duplicate reference name to service " + refName + " under service " + serviceName);
+                ServiceInstance serviceInstance = ServiceInstance.fromString(refEntry.getValue());
+                refNameToInstance.put(refName, serviceInstance);
+
+                tracker.instanceToRef.put(serviceInstance, refEntry.getKey());
+            }
+        }
+        return tracker;
+    }
+
+    public static Map<String, Map<String, String>> fromXml(XmlElement xml) {
+        Map<String, Map<String, String>> retVal = Maps.newHashMap();
+
+        List<XmlElement> services = xml.getChildElements(SERVICE_KEY);
+        xml.checkUnrecognisedElements(services);
+
+        for (XmlElement service : services) {
+
+            XmlElement typeElement = service.getOnlyChildElement(TYPE_KEY);
+            String serviceName = typeElement.getTextContent();
+
+            Map<String, String> innerMap = Maps.newHashMap();
+            retVal.put(serviceName, innerMap);
+
+            List<XmlElement> instances = service.getChildElements(XmlNetconfConstants.INSTANCE_KEY);
+            service.checkUnrecognisedElements(instances, typeElement);
+
+            for (XmlElement instance : instances) {
+                XmlElement nameElement = instance.getOnlyChildElement(NAME_KEY);
+                String refName = nameElement.getTextContent();
+
+                XmlElement providerElement = instance.getOnlyChildElement(PROVIDER_KEY);
+                String providerName = providerElement.getTextContent();
+
+                instance.checkUnrecognisedElements(nameElement, providerElement);
+
+                innerMap.put(refName, providerName);
+            }
+        }
+
+        return retVal;
+    }
+
+    private String findAvailableRefName(String refName, Set<String> refNamesAsSet) {
+        String intitialRefName = refName;
+
+        while (true) {
+            refName = intitialRefName + "_" + suffix++;
+            if (refNamesAsSet.contains(refName) == false)
+                return refName;
+        }
+    }
+
+    public Element toXml(Map<String, Map<String, String>> mappedServices, Document document) {
+        Element root = document.createElement(XmlNetconfConstants.SERVICES_KEY);
+        XmlUtil.addNamespaceAttr(root, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+
+        for (Entry<String, Map<String, String>> serviceEntry : mappedServices.entrySet()) {
+            Element serviceElement = document.createElement(SERVICE_KEY);
+            root.appendChild(serviceElement);
+
+            Element typeElement = XmlUtil.createTextElement(document, TYPE_KEY, serviceEntry.getKey());
+            serviceElement.appendChild(typeElement);
+
+            for (Entry<String, String> instanceEntry : serviceEntry.getValue().entrySet()) {
+                Element instanceElement = document.createElement(XmlNetconfConstants.INSTANCE_KEY);
+                serviceElement.appendChild(instanceElement);
+
+                Element nameElement = XmlUtil.createTextElement(document, NAME_KEY, instanceEntry.getKey());
+                instanceElement.appendChild(nameElement);
+
+                Element providerElement = XmlUtil.createTextElement(document, PROVIDER_KEY, instanceEntry.getValue());
+                instanceElement.appendChild(providerElement);
+            }
+        }
+
+        return root;
+    }
+
+    public static final class ServiceInstance {
+        public ServiceInstance(String moduleName, String instanceName) {
+            this.moduleName = moduleName;
+            this.instanceName = instanceName;
+        }
+
+        public static ServiceInstance fromString(String instanceId) {
+            instanceId = instanceId.trim();
+            Matcher matcher = p.matcher(instanceId);
+            Preconditions.checkArgument(matcher.matches(), "Unexpected format for provider, expected " + p.toString()
+                    + " but was " + instanceId);
+            String factoryName = matcher.group(1);
+            String instanceName = matcher.group(2);
+            return new ServiceInstance(factoryName, instanceName);
+        }
+
+        private final String moduleName, instanceName;
+        private String serviceName;
+
+        public String getServiceName() {
+            return serviceName;
+        }
+
+        public void setServiceName(String serviceName) {
+            this.serviceName = serviceName;
+        }
+
+        public String getModuleName() {
+            return moduleName;
+        }
+
+        public String getInstanceName() {
+            return instanceName;
+        }
+
+        private static final String blueprint = "/" + XmlNetconfConstants.CONFIG_KEY + "/"
+                + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "["
+                + XmlNetconfConstants.NAME_KEY + "='%s']/" + XmlNetconfConstants.INSTANCE_KEY + "["
+                + XmlNetconfConstants.NAME_KEY + "='%s']";
+
+        private static final String blueprintR = "/" + XmlNetconfConstants.CONFIG_KEY + "/"
+                + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "\\["
+                + XmlNetconfConstants.NAME_KEY + "='%s'\\]/" + XmlNetconfConstants.INSTANCE_KEY + "\\["
+                + XmlNetconfConstants.NAME_KEY + "='%s'\\]";
+
+        private static final Pattern p = Pattern.compile(String.format(blueprintR, "(.+)", "(.+)"));
+
+        @Override
+        public String toString() {
+            return String.format(blueprint, moduleName, instanceName);
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((instanceName == null) ? 0 : instanceName.hashCode());
+            result = prime * result + ((moduleName == null) ? 0 : moduleName.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;
+            ServiceInstance other = (ServiceInstance) obj;
+            if (instanceName == null) {
+                if (other.instanceName != null)
+                    return false;
+            } else if (!instanceName.equals(other.instanceName))
+                return false;
+            if (moduleName == null) {
+                if (other.moduleName != null)
+                    return false;
+            } else if (!moduleName.equals(other.moduleName))
+                return false;
+            return true;
+        }
+
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java
new file mode 100644 (file)
index 0000000..e91357e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc;
+
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.ObjectResolver;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+
+import javax.management.openmbean.OpenType;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public final class InstanceRuntimeRpc {
+
+    private final Map<String, AttributeIfc> yangToAttrConfig;
+    private final Rpc rpc;
+
+    public InstanceRuntimeRpc(Rpc rpc) {
+        this.yangToAttrConfig = map(rpc.getParameters());
+        this.rpc = rpc;
+    }
+
+    private Map<String, AttributeIfc> map(List<JavaAttribute> parameters) {
+        Map<String, AttributeIfc> mapped = Maps.newHashMap();
+        for (JavaAttribute javaAttribute : parameters) {
+            mapped.put(javaAttribute.getAttributeYangName(), javaAttribute);
+        }
+        return mapped;
+    }
+
+    private void resolveConfiguration(Map<String, AttributeConfigElement> mappedConfig) {
+
+        // TODO make field, resolvingStrategies can be instantiated only once
+        Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> resolvingStrategies = new ObjectResolver(null)
+                .prepareResolving(yangToAttrConfig);
+        // TODO make constructor for object resolver without service tracker
+        for (Entry<String, AttributeConfigElement> configDefEntry : mappedConfig.entrySet()) {
+            try {
+
+                AttributeResolvingStrategy<?, ? extends OpenType<?>> attributeResolvingStrategy = resolvingStrategies
+                        .get(configDefEntry.getKey());
+
+                configDefEntry.getValue().resolveValue(attributeResolvingStrategy, configDefEntry.getKey());
+                configDefEntry.getValue().setJmxName(
+                        yangToAttrConfig.get(configDefEntry.getKey()).getUpperCaseCammelCase());
+            } catch (Exception e) {
+                throw new IllegalStateException("Unable to resolve value " + configDefEntry.getValue()
+                        + " to attribute " + configDefEntry.getKey(), e);
+            }
+        }
+    }
+
+    public Map<String, AttributeConfigElement> fromXml(XmlElement configRootNode) {
+        Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
+
+        Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
+
+        for (Entry<String, AttributeReadingStrategy> readStratEntry : strats.entrySet()) {
+            List<XmlElement> configNodes = configRootNode.getChildElements(readStratEntry.getKey());
+            AttributeConfigElement readElement = readStratEntry.getValue().readElement(configNodes);
+            retVal.put(readStratEntry.getKey(), readElement);
+        }
+
+        resolveConfiguration(retVal);
+        return retVal;
+    }
+
+    public String getName() {
+        return rpc.getName();
+    }
+
+    public String getReturnType() {
+        return rpc.getReturnType();
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java
new file mode 100644 (file)
index 0000000..a081890
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
+import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
+
+import java.util.Map;
+
+public final class ModuleRpcs {
+
+    Map<String, String> yangToJavaNames = Maps.newHashMap();
+    Map<String, Map<String, InstanceRuntimeRpc>> rpcMapping = Maps.newHashMap();
+
+    public void addNameMapping(RuntimeBeanEntry runtimeEntry) {
+        String yangName = runtimeEntry.getYangName();
+        Preconditions.checkState(yangToJavaNames.containsKey(yangName) == false,
+                "RuntimeBean %s found twice in same namespace", yangName);
+        yangToJavaNames.put(yangName, runtimeEntry.getJavaNamePrefix());
+    }
+
+    public void addRpc(RuntimeBeanEntry runtimeEntry, Rpc rpc) {
+        String yangName = runtimeEntry.getYangName();
+        Map<String, InstanceRuntimeRpc> map = rpcMapping.get(yangName);
+        if (map == null) {
+            map = Maps.newHashMap();
+            rpcMapping.put(yangName, map);
+        }
+
+        Preconditions.checkState(map.containsKey(rpc.getYangName()) == false, "Rpc %s for runtime bean %s added twice",
+                rpc.getYangName(), yangName);
+        map.put(rpc.getYangName(), new InstanceRuntimeRpc(rpc));
+    }
+
+    public String getRbeJavaName(String yangName) {
+        String javaName = yangToJavaNames.get(yangName);
+        Preconditions.checkState(javaName != null,
+                "No runtime bean entry found under yang name %s, available yang names %s", yangName,
+                yangToJavaNames.keySet());
+        return javaName;
+    }
+
+    public InstanceRuntimeRpc getRpc(String rbeName, String rpcName) {
+        Map<String, InstanceRuntimeRpc> rpcs = rpcMapping.get(rbeName);
+        Preconditions.checkState(rpcs != null, "No rpcs found for runtime bean %s", rbeName);
+        InstanceRuntimeRpc rpc = rpcs.get(rpcName);
+        Preconditions.checkState(rpc != null, "No rpc found for runtime bean %s with name %s", rbeName, rpcName);
+        return rpc;
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/Rpcs.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/Rpcs.java
new file mode 100644 (file)
index 0000000..556541a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpcElementResolved;
+
+import java.util.Map;
+
+public class Rpcs {
+    private final Map<String, Map<String, ModuleRpcs>> mappedRpcs;
+
+    public Rpcs(Map<String, Map<String, ModuleRpcs>> mappedRpcs) {
+        super();
+        this.mappedRpcs = mappedRpcs;
+    }
+
+    public ModuleRpcs getRpcMapping(RuntimeRpcElementResolved id) {
+        Map<String, ModuleRpcs> modules = mappedRpcs.get(id.getNamespace());
+        Preconditions.checkState(modules != null, "No modules found for namespace %s", id.getNamespace());
+        ModuleRpcs rpcMapping = modules.get(id.getModuleName());
+        Preconditions.checkState(modules != null, "No module %s found for namespace %s", id.getModuleName(),
+                id.getNamespace());
+
+        return rpcMapping;
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java
new file mode 100644 (file)
index 0000000..9d348d0
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.management.ObjectName;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class InstanceRuntime {
+
+    /**
+     *
+     */
+    private static final String KEY_ATTRIBUTE_KEY = "key";
+
+    private final InstanceConfig instanceMapping;
+    private final Map<String, InstanceRuntime> childrenMappings;
+    private final Map<String, String> jmxToYangChildRbeMapping;
+
+    public InstanceRuntime(InstanceConfig instanceMapping, Map<String, InstanceRuntime> childrenMappings,
+            Map<String, String> jmxToYangChildRbeMapping) {
+        this.instanceMapping = instanceMapping;
+        this.childrenMappings = childrenMappings;
+        this.jmxToYangChildRbeMapping = jmxToYangChildRbeMapping;
+    }
+
+    /**
+     * Finds all children runtime beans, same properties and values as current
+     * root + any number of additional properties
+     */
+    private Set<ObjectName> findChildren(ObjectName innerRootBean, Set<ObjectName> childRbeOns) {
+        final Hashtable<String, String> wantedProperties = innerRootBean.getKeyPropertyList();
+
+        return Sets.newHashSet(Collections2.filter(childRbeOns, new Predicate<ObjectName>() {
+
+            @Override
+            public boolean apply(ObjectName on) {
+                Hashtable<String, String> localProperties = on.getKeyPropertyList();
+                for (Entry<String, String> propertyEntry : wantedProperties.entrySet()) {
+                    if (!localProperties.containsKey(propertyEntry.getKey()))
+                        return false;
+                    if (!localProperties.get(propertyEntry.getKey()).equals(propertyEntry.getValue()))
+                        return false;
+                    if (localProperties.size() <= wantedProperties.size())
+                        return false;
+                }
+                return true;
+            }
+        }));
+    }
+
+    /**
+     * Finds next level root runtime beans, beans that have the same properties
+     * as current root + one additional
+     */
+    private Set<ObjectName> getRootBeans(Set<ObjectName> childRbeOns, final String string, final int keyListSize) {
+        return Sets.newHashSet(Collections2.filter(childRbeOns, new Predicate<ObjectName>() {
+
+            @Override
+            public boolean apply(ObjectName on) {
+                if (on.getKeyPropertyList().size() != keyListSize + 1)
+                    return false;
+                if (!on.getKeyPropertyList().containsKey(string))
+                    return false;
+                return true;
+            }
+        }));
+    }
+
+    public Element toXml(ObjectName rootOn, Set<ObjectName> childRbeOns, Document document) {
+        return toXml(rootOn, childRbeOns, document, null, null);
+    }
+
+    public Element toXml(ObjectName rootOn, Set<ObjectName> childRbeOns, Document document, String instanceIndex,
+            String keyName) {
+        Element xml = document.createElement(keyName == null ? XmlNetconfConstants.DATA_KEY : keyName);
+        // TODO namespace
+        xml = instanceMapping.toXml(rootOn, null, "namespace", document, xml);
+
+        if (instanceIndex != null) {
+            xml.setAttribute(KEY_ATTRIBUTE_KEY, instanceIndex);
+        }
+
+        for (Entry<String, InstanceRuntime> childMappingEntry : childrenMappings.entrySet()) {
+            Set<ObjectName> innerRootBeans = getRootBeans(childRbeOns, childMappingEntry.getKey(), rootOn
+                    .getKeyPropertyList().size());
+
+            for (ObjectName objectName : innerRootBeans) {
+                Set<ObjectName> innerChildRbeOns = findChildren(objectName, childRbeOns);
+                String runtimeInstanceIndex = objectName.getKeyProperty(childMappingEntry.getKey());
+
+                String elementName = jmxToYangChildRbeMapping.get(childMappingEntry.getKey());
+                xml.appendChild(childMappingEntry.getValue().toXml(objectName, innerChildRbeOns, document,
+                        runtimeInstanceIndex, elementName));
+            }
+        }
+
+        return xml;
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java
new file mode 100644 (file)
index 0000000..07da65e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.management.ObjectName;
+import java.util.Collection;
+import java.util.Set;
+
+public class ModuleRuntime {
+
+    private final String moduleName;
+    private final InstanceRuntime instanceRuntime;
+
+    public ModuleRuntime(String moduleName, InstanceRuntime instanceRuntime) {
+        this.moduleName = moduleName;
+        this.instanceRuntime = instanceRuntime;
+    }
+
+    public InstanceRuntime getMbeanMapping() {
+        return instanceRuntime;
+    }
+
+    private ObjectName findRoot(Collection<ObjectName> runtimeBeanOns) {
+        for (ObjectName objectName : runtimeBeanOns) {
+            if (objectName.getKeyPropertyList().size() == 3)
+                return objectName;
+        }
+        throw new IllegalStateException("Root runtime bean not found among " + runtimeBeanOns);
+    }
+
+    public Element toXml(String namespace, Multimap<String, ObjectName> instances, Document document) {
+        Element root = document.createElement(XmlNetconfConstants.MODULE_KEY);
+        XmlUtil.addNamespaceAttr(root, namespace);
+
+        Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, moduleName);
+        root.appendChild(nameElement);
+
+        for (String instanceName : instances.keySet()) {
+            Element instance = document.createElement(XmlNetconfConstants.INSTANCE_KEY);
+
+            Element innerNameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, instanceName);
+            instance.appendChild(innerNameElement);
+
+            Collection<ObjectName> runtimeBeanOns = instances.get(instanceName);
+            ObjectName rootName = findRoot(runtimeBeanOns);
+
+            Set<ObjectName> childrenRuntimeBeans = Sets.newHashSet(runtimeBeanOns);
+            childrenRuntimeBeans.remove(rootName);
+
+            instance.appendChild(instanceRuntime.toXml(rootName, childrenRuntimeBeans, document));
+
+            root.appendChild(instance);
+        }
+
+        return root;
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java
new file mode 100644 (file)
index 0000000..da28126
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.management.ObjectName;
+import java.util.Map;
+import java.util.Set;
+
+public class Runtime {
+
+    private final Map<String, Map<String, ModuleRuntime>> moduleRuntimes;
+
+    public Runtime(Map<String, Map<String, ModuleRuntime>> moduleRuntimes) {
+        this.moduleRuntimes = moduleRuntimes;
+    }
+
+    private Map<String, Multimap<String, ObjectName>> mapInstancesToModules(Set<ObjectName> instancesToMap) {
+        Map<String, Multimap<String, ObjectName>> retVal = Maps.newHashMap();
+
+        for (ObjectName objectName : instancesToMap) {
+            String moduleName = ObjectNameUtil.getFactoryName(objectName);
+
+            Multimap<String, ObjectName> multimap = retVal.get(moduleName);
+            if (multimap == null) {
+                multimap = HashMultimap.create();
+                retVal.put(moduleName, multimap);
+            }
+
+            String instanceName = ObjectNameUtil.getInstanceName(objectName);
+
+            multimap.put(instanceName, objectName);
+        }
+
+        return retVal;
+    }
+
+    public Element toXml(Set<ObjectName> instancesToMap, Document document) {
+        Element root = document.createElement(XmlNetconfConstants.DATA_KEY);
+
+        Element modulesElement = document.createElement(XmlNetconfConstants.MODULES_KEY);
+        XmlUtil.addNamespaceAttr(modulesElement,
+                XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
+        root.appendChild(modulesElement);
+
+        Map<String, Multimap<String, ObjectName>> moduleToInstances = mapInstancesToModules(instancesToMap);
+
+        for (String localNamespace : moduleRuntimes.keySet()) {
+            for (String moduleName : moduleRuntimes.get(localNamespace).keySet()) {
+                Multimap<String, ObjectName> instanceToRbe = moduleToInstances.get(moduleName);
+
+                if (instanceToRbe == null)
+                    continue;
+
+                ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName);
+                Element innerXml = moduleRuntime.toXml(localNamespace, instanceToRbe, document);
+                modulesElement.appendChild(innerXml);
+            }
+        }
+
+        return root;
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java
new file mode 100644 (file)
index 0000000..6689759
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.operations;
+
+import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public abstract class AbstractConfigNetconfOperation extends AbstractNetconfOperation {
+
+    protected final ConfigRegistryClient configRegistryClient;
+
+    protected AbstractConfigNetconfOperation(ConfigRegistryClient configRegistryClient,
+            String netconfSessionIdForReporting) {
+        super(netconfSessionIdForReporting);
+        this.configRegistryClient = configRegistryClient;
+    }
+
+    @Override
+    protected HandlingPriority canHandle(String operationName, String operationNamespace) {
+        // TODO check namespace
+        return operationName.equals(getOperationName()) ? HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY
+                : HandlingPriority.CANNOT_HANDLE;
+    }
+
+    protected abstract String getOperationName();
+
+    @Override
+    protected Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter)
+            throws NetconfDocumentedException {
+        return handle(document, operationElement);
+    }
+
+    protected abstract Element handle(Document document, XmlElement operationElement) throws NetconfDocumentedException;
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java
new file mode 100644 (file)
index 0000000..8820d58
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.operations;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class Commit extends AbstractConfigNetconfOperation {
+
+    private static final Logger logger = LoggerFactory.getLogger(Commit.class);
+
+    private final TransactionProvider transactionProvider;
+
+    public Commit(TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient,
+            String netconfSessionIdForReporting) {
+        super(configRegistryClient, netconfSessionIdForReporting);
+        this.transactionProvider = transactionProvider;
+    }
+
+    private static void checkXml(XmlElement xml) {
+        xml.checkName(XmlNetconfConstants.COMMIT);
+        xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+    }
+
+    @Override
+    protected String getOperationName() {
+        return XmlNetconfConstants.COMMIT;
+    }
+
+    @Override
+    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+        checkXml(xml);
+
+        CommitStatus status;
+        try {
+            status = this.transactionProvider.commitTransaction();
+        } catch (final IllegalStateException e) {
+            logger.warn("Commit failed: ", e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.operation_failed.name(),
+                    "Operation failed. Use 'get-config' or 'edit-config' before triggering 'commit' operation");
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed,
+                    ErrorSeverity.error, errorInfo);
+        } catch (final NetconfDocumentedException e) {
+            throw new NetconfDocumentedException(
+                    "Unable to retrieve config snapshot after commit for persister, details: " + e.getMessage(),
+                    ErrorType.application, ErrorTag.operation_failed, ErrorSeverity.error, e.getErrorInfo());
+        }
+        logger.info("Datastore {} committed successfully: {}", Datastore.candidate, status);
+
+        return document.createElement(XmlNetconfConstants.OK);
+    }
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Datastore.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Datastore.java
new file mode 100644 (file)
index 0000000..d736595
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.operations;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.CandidateDatastoreQueryStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.DatastoreQueryStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.RunningDatastoreQueryStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+
+public enum Datastore {
+
+    running, candidate;
+
+    /**
+     * @param source
+     * @param transactionProvider
+     * @return
+     */
+    public static DatastoreQueryStrategy getInstanceQueryStrategy(Datastore source,
+            TransactionProvider transactionProvider) {
+        switch (source) {
+        case running:
+            return new RunningDatastoreQueryStrategy();
+        case candidate:
+            return new CandidateDatastoreQueryStrategy(transactionProvider);
+        default:
+            throw new UnsupportedOperationException("Unimplemented datastore query strategy for " + source);
+        }
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java
new file mode 100644 (file)
index 0000000..b8fa5dd
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.operations;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class DiscardChanges extends AbstractConfigNetconfOperation {
+
+    public static final String DISCARD = "discard-changes";
+
+    private static final Logger logger = LoggerFactory.getLogger(DiscardChanges.class);
+
+    private final TransactionProvider transactionProvider;
+
+    public DiscardChanges(final TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient,
+            String netconfSessionIdForReporting) {
+        super(configRegistryClient, netconfSessionIdForReporting);
+        this.transactionProvider = transactionProvider;
+    }
+
+    private static void fromXml(XmlElement xml) {
+        xml.checkName(DISCARD);
+        xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+    }
+
+    @Override
+    protected String getOperationName() {
+        return DISCARD;
+    }
+
+    @Override
+    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+        try {
+            fromXml(xml);
+        } catch (final IllegalArgumentException e) {
+            logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage());
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute,
+                    ErrorSeverity.error, errorInfo);
+        }
+
+        try {
+            this.transactionProvider.abortTransaction();
+        } catch (final IllegalStateException e) {
+            logger.warn("Abort failed: ", e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo
+                    .put(ErrorTag.operation_failed.name(),
+                            "Operation failed. Use 'get-config' or 'edit-config' before triggering 'discard-changes' operation");
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed,
+                    ErrorSeverity.error, errorInfo);
+        }
+        logger.info("Changes discarded successfully from datastore {}", Datastore.candidate);
+
+        return document.createElement(XmlNetconfConstants.OK);
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java
new file mode 100644 (file)
index 0000000..b8cae43
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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.operations;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Validate extends AbstractConfigNetconfOperation {
+
+    public static final String VALIDATE = "validate";
+
+    private static final Logger logger = LoggerFactory.getLogger(Validate.class);
+
+    private final TransactionProvider transactionProvider;
+
+    public Validate(final TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient,
+            String netconfSessionIdForReporting) {
+        super(configRegistryClient, netconfSessionIdForReporting);
+        this.transactionProvider = transactionProvider;
+    }
+
+    private void checkXml(XmlElement xml) {
+        xml.checkName(VALIDATE);
+        xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+
+        XmlElement sourceElement = xml.getOnlyChildElement(XmlNetconfConstants.SOURCE_KEY,
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+        XmlElement sourceChildNode = sourceElement.getOnlyChildElement();
+
+        sourceChildNode.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+        String datastoreValue = sourceChildNode.getName();
+        Datastore sourceDatastore = Datastore.valueOf(datastoreValue);
+
+        Preconditions.checkState(sourceDatastore == Datastore.candidate, "Only " + Datastore.candidate
+                + " is supported as source for " + VALIDATE + " but was " + datastoreValue);
+    }
+
+    @Override
+    protected String getOperationName() {
+        return VALIDATE;
+    }
+
+    @Override
+    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+        try {
+            checkXml(xml);
+        } catch (IllegalStateException e) {
+            logger.warn("Rpc error: {}", ErrorTag.missing_attribute, e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.missing_attribute.name(), "Missing value of datastore attribute");
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.missing_attribute,
+                    ErrorSeverity.error, errorInfo);
+        } catch (final IllegalArgumentException e) {
+            logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage());
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute,
+                    ErrorSeverity.error, errorInfo);
+        }
+
+        try {
+            transactionProvider.validateTransaction();
+        } catch (ValidationException e) {
+            logger.warn("Validation failed", e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.operation_failed.name(), "Validation failed");
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed,
+                    ErrorSeverity.error, errorInfo);
+        } catch (IllegalStateException e) {
+            logger.warn("Validation failed", e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo
+                    .put(ErrorTag.operation_failed.name(),
+                            "Datastore is not present. Use 'get-config' or 'edit-config' before triggering 'operations' operation");
+            throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed,
+                    ErrorSeverity.error, errorInfo);
+
+        }
+
+        logger.info("Datastore {} validated successfully", Datastore.candidate);
+
+        return document.createElement(XmlNetconfConstants.OK);
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java
new file mode 100644 (file)
index 0000000..d8ea7d7
--- /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.netconf.confignetconfconnector.operations.editconfig;
+
+import java.util.Map;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractEditConfigStrategy implements EditConfigStrategy {
+
+    private static final Logger logger = LoggerFactory.getLogger(AbstractEditConfigStrategy.class);
+
+    @Override
+    public void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
+            ConfigTransactionClient ta) {
+
+        try {
+            ObjectName on = ta.lookupConfigBean(module, instance);
+            logger.debug("ServiceInstance for {} {} located successfully under {}", module, instance, on);
+            executeStrategy(configuration, ta, on);
+        } catch (InstanceNotFoundException e) {
+            handleMissingInstance(configuration, ta, module, instance);
+        }
+
+    }
+
+    abstract void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
+            String module, String instance);
+
+    abstract void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
+            ObjectName objectName);
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java
new file mode 100644 (file)
index 0000000..ffe107f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.operations.editconfig;
+
+import java.util.Map;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DeleteEditConfigStrategy extends AbstractEditConfigStrategy {
+
+    private static final Logger logger = LoggerFactory.getLogger(DeleteEditConfigStrategy.class);
+
+    @Override
+    void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
+            String module, String instance) {
+        throw new IllegalStateException("Unable to delete " + module + ":" + instance + " , ServiceInstance not found");
+    }
+
+    @Override
+    void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on) {
+        try {
+            ta.destroyModule(on);
+            logger.debug("ServiceInstance {} deleted successfully", on);
+        } catch (InstanceNotFoundException e) {
+            throw new IllegalStateException("Unable to delete " + on, e);
+        }
+    }
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java
new file mode 100644 (file)
index 0000000..de21f31
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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.operations.editconfig;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
+import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.*;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.management.ObjectName;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class EditConfig extends AbstractConfigNetconfOperation {
+
+    private static final Logger logger = LoggerFactory.getLogger(EditConfig.class);
+
+    private final YangStoreSnapshot yangStoreSnapshot;
+
+    private final TransactionProvider transactionProvider;
+    private EditConfigXmlParser editConfigXmlParser;
+
+    public EditConfig(YangStoreSnapshot yangStoreSnapshot, TransactionProvider transactionProvider,
+            ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) {
+        super(configRegistryClient, netconfSessionIdForReporting);
+        this.yangStoreSnapshot = yangStoreSnapshot;
+        this.transactionProvider = transactionProvider;
+        this.editConfigXmlParser = new EditConfigXmlParser();
+    }
+
+    @VisibleForTesting
+    Element getResponseInternal(final Document document,
+            final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+        if (editConfigExecution.shouldTest()) {
+            executeTests(configRegistryClient, editConfigExecution);
+        }
+
+        if (editConfigExecution.shouldSet()) {
+            executeSet(configRegistryClient, editConfigExecution);
+        }
+
+        logger.info("Operation {} successful", EditConfigXmlParser.EDIT_CONFIG);
+
+        return document.createElement(XmlNetconfConstants.OK);
+    }
+
+    private void executeSet(ConfigRegistryClient configRegistryClient,
+            EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+        try {
+            set(configRegistryClient, editConfigExecution);
+        } catch (IllegalStateException | JmxAttributeValidationException | ValidationException e) {
+            logger.warn("Set phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.operation_failed.name(), e.getMessage());
+            throw new NetconfDocumentedException("Test phase: " + e.getMessage(), e, ErrorType.application,
+                    ErrorTag.operation_failed, ErrorSeverity.error, errorInfo);
+        }
+        logger.debug("Set phase for {} operation successful", EditConfigXmlParser.EDIT_CONFIG);
+    }
+
+    private void executeTests(ConfigRegistryClient configRegistryClient,
+            EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+        try {
+            test(configRegistryClient, editConfigExecution.resolvedXmlElements);
+        } catch (IllegalStateException | JmxAttributeValidationException | ValidationException e) {
+            logger.warn("Test phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.operation_failed.name(), e.getMessage());
+            throw new NetconfDocumentedException("Test phase: " + e.getMessage(), e, ErrorType.application,
+                    ErrorTag.operation_failed, ErrorSeverity.error, errorInfo);
+        }
+        logger.debug("Test phase for {} operation successful", EditConfigXmlParser.EDIT_CONFIG);
+    }
+
+    private void test(ConfigRegistryClient configRegistryClient,
+            Map<String, Multimap<String, ModuleElementResolved>> resolvedModules) {
+        ObjectName taON = transactionProvider.getTestTransaction();
+        try {
+
+            // default strategy = replace wipes config
+            if (EditStrategyType.defaultStrategy() == EditStrategyType.replace) {
+                transactionProvider.wipeTestTransaction(taON);
+            }
+            setOnTransaction(configRegistryClient, resolvedModules, taON);
+            transactionProvider.validateTestTransaction(taON);
+        } finally {
+            transactionProvider.abortTestTransaction(taON);
+        }
+    }
+
+    private void set(ConfigRegistryClient configRegistryClient,
+            EditConfigXmlParser.EditConfigExecution editConfigExecution) {
+        ObjectName taON = transactionProvider.getOrCreateTransaction();
+
+        // default strategy = replace wipes config
+        if (EditStrategyType.defaultStrategy() == EditStrategyType.replace) {
+            transactionProvider.wipeTransaction();
+        }
+        setOnTransaction(configRegistryClient, editConfigExecution.resolvedXmlElements, taON);
+    }
+
+    private void setOnTransaction(ConfigRegistryClient configRegistryClient,
+            Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements, ObjectName taON) {
+        ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON);
+
+        for (Multimap<String, ModuleElementResolved> modulesToResolved : resolvedXmlElements.values()) {
+            for (Entry<String, ModuleElementResolved> moduleToResolved : modulesToResolved.entries()) {
+                String moduleName = moduleToResolved.getKey();
+
+                ModuleElementResolved moduleElementResolved = moduleToResolved.getValue();
+                String instanceName = moduleElementResolved.getInstanceName();
+
+                InstanceConfigElementResolved ice = moduleElementResolved.getInstanceConfigElementResolved();
+                EditConfigStrategy strategy = ice.getEditStrategy();
+                strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta);
+            }
+        }
+    }
+
+    public static Config getConfigMapping(ConfigRegistryClient configRegistryClient,
+            Map<String, Map<String, ModuleMXBeanEntry>> mBeanEntries) {
+        Map<String, Map<String, ModuleConfig>> factories = transform(configRegistryClient, mBeanEntries);
+        return new Config(factories);
+    }
+
+    // TODO refactor
+    private static Map<String, Map<String, ModuleConfig>> transform(final ConfigRegistryClient configRegistryClient,
+            Map<String, Map<String, ModuleMXBeanEntry>> mBeanEntries) {
+        return Maps.transformEntries(mBeanEntries,
+                new Maps.EntryTransformer<String, Map<String, ModuleMXBeanEntry>, Map<String, ModuleConfig>>() {
+
+                    @Override
+                    public Map<String, ModuleConfig> transformEntry(String arg0, Map<String, ModuleMXBeanEntry> arg1) {
+                        return Maps.transformEntries(arg1,
+                                new Maps.EntryTransformer<String, ModuleMXBeanEntry, ModuleConfig>() {
+
+                                    @Override
+                                    public ModuleConfig transformEntry(String key, ModuleMXBeanEntry value) {
+                                        return new ModuleConfig(key, new InstanceConfig(configRegistryClient, value
+                                                .getAttributes()));
+                                    }
+                                });
+                    }
+                });
+    }
+
+    @Override
+    protected String getOperationName() {
+        return EditConfigXmlParser.EDIT_CONFIG;
+    }
+
+    @Override
+    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+
+        EditConfigXmlParser.EditConfigExecution editConfigExecution;
+        Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
+        try {
+            editConfigExecution = editConfigXmlParser.fromXml(xml, cfg);
+        } catch (IllegalStateException e) {
+            logger.warn("Error parsing xml", e);
+            final Map<String, String> errorInfo = new HashMap<>();
+            errorInfo.put(ErrorTag.missing_attribute.name(), "Missing value for 'target' attribute");
+            throw new Ne