Merge "Table features : modified yang model. Patch set 2: Modified match types as...
authorEd Warnicke <eaw@cisco.com>
Thu, 28 Nov 2013 09:45:10 +0000 (09:45 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 28 Nov 2013 09:45:10 +0000 (09:45 +0000)
115 files changed:
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/factoriesresolver/HierarchicalConfigMBeanFactoriesHolder.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/factoriesresolver/ModuleFactoriesResolver.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolver.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ConfigManagerActivator.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/ConfigRegistryImplTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/factoriesresolver/HardcodedModuleFactoriesResolver.java
opendaylight/config/logback-config/src/main/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleFactory.java
opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleTest.java
opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleWithInitialConfigurationTest.java
opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackWithXmlConfigModuleTest.java
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/ExtenderYangTracker.java
opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerConfig.java
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/controller.config
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMUtil.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FlowConsumerImpl.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/GroupConsumerImpl.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/MeterConsumerImpl.java
opendaylight/md-sal/model/model-flow-base/src/main/yang/flow-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/queue-types.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-base/src/main/yang/table-types.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/queue-config.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/queue-service.yang [new file with mode: 0644]
opendaylight/md-sal/model/pom.xml
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DeserializationException.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/AbstractLockableDelegator.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataStore.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModuleFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend [deleted file]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java [deleted file]
opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft01.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/MediaTypes.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ResponseException.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/StructuredData.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromJsonToCompositeNodeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNodeTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonBasicDataTypesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonWithAugmentTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container-yang/data-container.yang
opendaylight/md-sal/sal-rest-connector/src/test/resources/xml-to-composite-node/data-container.xml
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-container.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaf.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaflist.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-list.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/xml/data.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/yang.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-data-types/simple-data-types.yang
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-data-types/xml/data.xml
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java
opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java
opendaylight/md-sal/topology-manager/pom.xml [new file with mode: 0644]
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableNodeMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableTopologyExporter.xtend [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/Rpcs.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpcElementResolved.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpc.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner_complex_output.xml
opendaylight/northbound/containermanager/src/main/java/org/opendaylight/controller/containermanager/northbound/ContainerConfigs.java
opendaylight/northbound/containermanager/src/main/java/org/opendaylight/controller/containermanager/northbound/ContainerManagerNorthbound.java

index 84c2c6dd4dd46b57372d1fbf14a46f43ed225181..0fd6c5279409e3412de86a33735c3dc4daddf058 100644 (file)
@@ -114,8 +114,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             BundleContext bundleContext, MBeanServer configMBeanServer,
             BaseJMXRegistrator baseJMXRegistrator) {
         this.resolver = resolver;
-        this.beanToOsgiServiceManager = new BeanToOsgiServiceManager(
-                bundleContext);
+        this.beanToOsgiServiceManager = new BeanToOsgiServiceManager();
         this.bundleContext = bundleContext;
         this.configMBeanServer = configMBeanServer;
         this.baseJMXRegistrator = baseJMXRegistrator;
@@ -138,7 +137,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
         String transactionName = "ConfigTransaction-" + version + "-" + versionCounter;
         TransactionJMXRegistrator transactionRegistrator = baseJMXRegistrator
                 .createTransactionJMXRegistrator(transactionName);
-        List<ModuleFactory> allCurrentFactories = Collections.unmodifiableList(resolver.getAllFactories());
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = Collections.unmodifiableMap(resolver.getAllFactories());
         ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
                 transactionName, transactionRegistrator, version,
                 versionCounter, allCurrentFactories, transactionsMBeanServer, configMBeanServer, bundleContext);
@@ -320,8 +319,16 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
             // register to OSGi
             if (osgiRegistration == null) {
-                osgiRegistration = beanToOsgiServiceManager.registerToOsgi(module.getClass(),
-                        newReadableConfigBean.getInstance(), entry.getName());
+                ModuleFactory moduleFactory = entry.getModuleFactory();
+                if(moduleFactory != null) {
+                    BundleContext bc = configTransactionController.
+                            getModuleFactoryBundleContext(moduleFactory.getImplementationName());
+                    osgiRegistration = beanToOsgiServiceManager.registerToOsgi(module.getClass(),
+                            newReadableConfigBean.getInstance(), entry.getName(), bc);
+                } else {
+                    throw new NullPointerException(entry.getIdentifier().getFactoryName() + " ModuleFactory not found.");
+                }
+
             }
 
             RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators
index 3f569ae324ebebe51cf0550aa74b21bbcc8d58b8..a9ab664fd6d44cd19a4b38c02248a96d938b41b9 100644 (file)
@@ -34,12 +34,13 @@ import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static java.lang.String.format;
@@ -64,7 +65,7 @@ class ConfigTransactionControllerImpl implements
     private final DependencyResolverManager dependencyResolverManager;
     private final TransactionStatus transactionStatus;
     private final MBeanServer transactionsMBeanServer;
-    private final List<ModuleFactory> currentlyRegisteredFactories;
+    private final Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories;
 
     /**
      * Disables ability of {@link DynamicWritableWrapper} to change attributes
@@ -82,7 +83,7 @@ class ConfigTransactionControllerImpl implements
     public ConfigTransactionControllerImpl(String transactionName,
                                            TransactionJMXRegistrator transactionRegistrator,
                                            long parentVersion, long currentVersion,
-                                           List<ModuleFactory> currentlyRegisteredFactories,
+                                           Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
                                            MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, BundleContext bundleContext) {
 
         this.transactionIdentifier = new TransactionIdentifier(transactionName);
@@ -120,11 +121,11 @@ class ConfigTransactionControllerImpl implements
         transactionStatus.checkNotAborted();
 
         Set<ModuleFactory> oldSet = new HashSet<>(lastListOfFactories);
-        Set<ModuleFactory> newSet = new HashSet<>(currentlyRegisteredFactories);
+        Set<ModuleFactory> newSet = new HashSet<>(factoriesHolder.getModuleFactories());
 
         List<ModuleFactory> toBeAdded = new ArrayList<>();
         List<ModuleFactory> toBeRemoved = new ArrayList<>();
-        for(ModuleFactory moduleFactory: currentlyRegisteredFactories) {
+        for(ModuleFactory moduleFactory: factoriesHolder.getModuleFactories()) {
             if (oldSet.contains(moduleFactory) == false){
                 toBeAdded.add(moduleFactory);
             }
@@ -136,7 +137,8 @@ class ConfigTransactionControllerImpl implements
         }
         // add default modules
         for (ModuleFactory moduleFactory : toBeAdded) {
-            Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
+            Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager,
+                    getModuleFactoryBundleContext(moduleFactory.getImplementationName()));
             for (Module module : defaultModules) {
                 // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
                 DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
@@ -173,9 +175,10 @@ class ConfigTransactionControllerImpl implements
         DependencyResolver dependencyResolver = dependencyResolverManager
                 .getOrCreate(moduleIdentifier);
         try {
+            BundleContext bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
             module = moduleFactory.createModule(
                     moduleIdentifier.getInstanceName(), dependencyResolver,
-                    oldConfigBeanInfo.getReadableModule(), bundleContext);
+                    oldConfigBeanInfo.getReadableModule(), bc);
         } catch (Exception e) {
             throw new IllegalStateException(format(
                     "Error while copying old configuration from %s to %s",
@@ -196,7 +199,8 @@ class ConfigTransactionControllerImpl implements
         // find factory
         ModuleFactory moduleFactory = factoriesHolder.findByModuleName(factoryName);
         DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
-        Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext);
+        Module module = moduleFactory.createModule(instanceName, dependencyResolver,
+                getModuleFactoryBundleContext(moduleFactory.getImplementationName()));
         return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
                 moduleFactory, null, dependencyResolver);
     }
@@ -466,11 +470,20 @@ class ConfigTransactionControllerImpl implements
 
     @Override
     public List<ModuleFactory> getCurrentlyRegisteredFactories() {
-        return currentlyRegisteredFactories;
+        return new ArrayList<>(factoriesHolder.getModuleFactories());
     }
 
     @Override
     public TransactionIdentifier getIdentifier() {
         return transactionIdentifier;
     }
+
+    @Override
+    public BundleContext getModuleFactoryBundleContext(String factoryName) {
+        Map.Entry<ModuleFactory, BundleContext> factoryBundleContextEntry = this.currentlyRegisteredFactories.get(factoryName);
+        if (factoryBundleContextEntry == null || factoryBundleContextEntry.getValue() == null) {
+            throw new NullPointerException("Bundle context of " + factoryName + " ModuleFactory not found.");
+        }
+        return factoryBundleContextEntry.getValue();
+    }
 }
index 556639c3abb4fa88296aef5195fe6d67a6078b2d..4dc877c62b339bebad0a55848c6debc25b96300a 100644 (file)
@@ -15,6 +15,7 @@ import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
 
 /**
  * Defines contract between {@link ConfigTransactionControllerImpl} (producer)
@@ -68,4 +69,6 @@ interface ConfigTransactionControllerInternal extends
     boolean isClosed();
 
     List<ModuleFactory> getCurrentlyRegisteredFactories();
+
+    BundleContext getModuleFactoryBundleContext(String factoryName);
 }
index 8f1c69eee3ce0f8a9eecb10de53c74ae832a3f65..f82a7295aaeaa47e4e7169e86dd5452666a7fd16 100644 (file)
@@ -7,17 +7,20 @@
  */
 package org.opendaylight.controller.config.manager.impl.factoriesresolver;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
 
 import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Set;
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
+import java.util.TreeSet;
+import java.util.Collection;
+import java.util.ArrayList;
+
 /**
  * Hold sorted ConfigMBeanFactories by their module names. Check that module
  * names are globally unique.
@@ -26,8 +29,9 @@ public class HierarchicalConfigMBeanFactoriesHolder {
     private static final Logger logger = LoggerFactory
             .getLogger(HierarchicalConfigMBeanFactoriesHolder.class);
 
-    private final Map<String, ModuleFactory> moduleNamesToConfigBeanFactories;
+    private final Map<String, Map.Entry<ModuleFactory, BundleContext>> moduleNamesToConfigBeanFactories;
     private final Set<String> moduleNames;
+    private final List<ModuleFactory> moduleFactories;
 
     /**
      * Create instance.
@@ -36,40 +40,17 @@ public class HierarchicalConfigMBeanFactoriesHolder {
      *             if unique constraint on module names is violated
      */
     public HierarchicalConfigMBeanFactoriesHolder(
-            List<? extends ModuleFactory> list) {
-        Map<String, ModuleFactory> moduleNamesToConfigBeanFactories = new HashMap<>();
-        StringBuffer errors = new StringBuffer();
-        for (ModuleFactory factory : list) {
-            String moduleName = factory.getImplementationName();
-            if (moduleName == null || moduleName.isEmpty()) {
-                throw new IllegalStateException(
-                        "Invalid implementation name for " + factory);
-            }
-            logger.debug("Reading factory {} {}", moduleName, factory);
-            String error = null;
-            ModuleFactory conflicting = moduleNamesToConfigBeanFactories
-                    .get(moduleName);
-            if (conflicting != null) {
-                error = String
-                        .format("Module name is not unique. Found two conflicting factories with same name '%s': " +
-                                "\n\t%s\n\t%s\n", moduleName, conflicting, factory);
-
-            }
-
-            if (error == null) {
-                moduleNamesToConfigBeanFactories.put(moduleName, factory);
-            } else {
-                errors.append(error);
-            }
-
-        }
-        if (errors.length() > 0) {
-            throw new IllegalArgumentException(errors.toString());
-        }
+            Map<String, Map.Entry<ModuleFactory, BundleContext>> factoriesMap) {
         this.moduleNamesToConfigBeanFactories = Collections
-                .unmodifiableMap(moduleNamesToConfigBeanFactories);
+                .unmodifiableMap(factoriesMap);
         moduleNames = Collections.unmodifiableSet(new TreeSet<>(
                 moduleNamesToConfigBeanFactories.keySet()));
+        List<ModuleFactory> factories = new ArrayList<>(this.moduleNamesToConfigBeanFactories.size());
+        Collection<Map.Entry<ModuleFactory, BundleContext>> entryCollection = this.moduleNamesToConfigBeanFactories.values();
+        for (Map.Entry<ModuleFactory, BundleContext> entry : entryCollection) {
+            factories.add(entry.getKey());
+        }
+        this.moduleFactories = Collections.unmodifiableList(factories);
     }
 
     /**
@@ -79,16 +60,20 @@ public class HierarchicalConfigMBeanFactoriesHolder {
      *             if factory is not found
      */
     public ModuleFactory findByModuleName(String moduleName) {
-        ModuleFactory result = moduleNamesToConfigBeanFactories.get(moduleName);
+        Map.Entry<ModuleFactory, BundleContext> result = moduleNamesToConfigBeanFactories.get(moduleName);
         if (result == null) {
             throw new IllegalArgumentException(
                     "ModuleFactory not found with module name: " + moduleName);
         }
-        return result;
+        return result.getKey();
     }
 
     public Set<String> getModuleNames() {
         return moduleNames;
     }
 
+    public List<ModuleFactory> getModuleFactories() {
+        return moduleFactories;
+    }
+
 }
index 4c6697e6b2bcf89502136bb8b49bf7f7366904e6..fc39fab1fb70bf81944777367601e874de0c7170 100644 (file)
@@ -7,9 +7,10 @@
  */
 package org.opendaylight.controller.config.manager.impl.factoriesresolver;
 
-import java.util.List;
-
 import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
+
+import java.util.Map;
 
 /**
  * {@link org.opendaylight.controller.config.manager.impl.ConfigTransactionControllerImpl}
@@ -20,6 +21,6 @@ import org.opendaylight.controller.config.spi.ModuleFactory;
  */
 public interface ModuleFactoriesResolver {
 
-    List<ModuleFactory> getAllFactories();
+    Map<String, Map.Entry<ModuleFactory, BundleContext>> getAllFactories();
 
 }
index 42f8b8790bb666e9fa29761faa5e47169964d4aa..41f577844af5ed448a322a9a21f2f410782632cd 100644 (file)
@@ -7,11 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.osgi;
 
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Set;
-
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
@@ -19,6 +14,11 @@ import org.opendaylight.controller.config.spi.Module;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
 /**
  * Registers instantiated beans as OSGi services and unregisters these services
  * if beans are destroyed.
@@ -28,12 +28,6 @@ public class BeanToOsgiServiceManager {
     static final String INSTANCE_NAME_OSGI_PROP = "instanceName";
     static final String IMPLEMENTATION_NAME_OSGI_PROP = "implementationName";
 
-    private final BundleContext bundleContext;
-
-    public BeanToOsgiServiceManager(BundleContext context) {
-        this.bundleContext = context;
-    }
-
     /**
      * To be called for every created, reconfigured and recreated config bean.
      * It is expected that before using this method OSGi service registry will
@@ -41,7 +35,7 @@ public class BeanToOsgiServiceManager {
      */
     public OsgiRegistration registerToOsgi(
             Class<? extends Module> configBeanClass, AutoCloseable instance,
-            ModuleIdentifier moduleIdentifier) {
+            ModuleIdentifier moduleIdentifier, BundleContext bundleContext) {
         try {
             final Set<Class<?>> configuresInterfaces = InterfacesHelper
                     .getOsgiRegistrationTypes(configBeanClass);
index 7c8c4e600810b2726282bf3437af8a2e4a3a140c..2a533ab9a3a6813ad4fed4c4dcfe4a5dbcec2cf6 100644 (file)
@@ -7,21 +7,26 @@
  */
 package org.opendaylight.controller.config.manager.impl.osgi;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Retrieves list of currently registered Module Factories using bundlecontext.
  */
 public class BundleContextBackedModuleFactoriesResolver implements
         ModuleFactoriesResolver {
+    private static final Logger logger = LoggerFactory
+            .getLogger(BundleContextBackedModuleFactoriesResolver.class);
     private final BundleContext bundleContext;
 
     public BundleContextBackedModuleFactoriesResolver(
@@ -30,7 +35,7 @@ public class BundleContextBackedModuleFactoriesResolver implements
     }
 
     @Override
-    public List<ModuleFactory> getAllFactories() {
+    public Map<String, Map.Entry<ModuleFactory, BundleContext>> getAllFactories() {
         Collection<ServiceReference<ModuleFactory>> serviceReferences;
         try {
             serviceReferences = bundleContext.getServiceReferences(
@@ -38,15 +43,43 @@ public class BundleContextBackedModuleFactoriesResolver implements
         } catch (InvalidSyntaxException e) {
             throw new IllegalStateException(e);
         }
-        List<ModuleFactory> result = new ArrayList<>(serviceReferences.size());
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> result = new HashMap<>(serviceReferences.size());
         for (ServiceReference<ModuleFactory> serviceReference : serviceReferences) {
-            ModuleFactory service = bundleContext.getService(serviceReference);
+            ModuleFactory factory = bundleContext.getService(serviceReference);
             // null if the service is not registered, the service object
             // returned by a ServiceFactory does not
             // implement the classes under which it was registered or the
             // ServiceFactory threw an exception.
-            if (service != null) {
-                result.add(service);
+            if(factory == null) {
+                throw new NullPointerException("ServiceReference of class" + serviceReference.getClass() + "not found.");
+            }
+            StringBuffer errors = new StringBuffer();
+            String moduleName = factory.getImplementationName();
+            if (moduleName == null || moduleName.isEmpty()) {
+                throw new IllegalStateException(
+                        "Invalid implementation name for " + factory);
+            }
+            if (serviceReference.getBundle() == null || serviceReference.getBundle().getBundleContext() == null) {
+                throw new NullPointerException("Bundle context of " + factory + " ModuleFactory not found.");
+            }
+            logger.debug("Reading factory {} {}", moduleName, factory);
+            String error = null;
+            Map.Entry<ModuleFactory, BundleContext> conflicting = result.get(moduleName);
+            if (conflicting != null) {
+                error = String
+                        .format("Module name is not unique. Found two conflicting factories with same name '%s': " +
+                                "\n\t%s\n\t%s\n", moduleName, conflicting.getKey(), factory);
+
+            }
+
+            if (error == null) {
+                result.put(moduleName, new AbstractMap.SimpleImmutableEntry<>(factory,
+                        serviceReference.getBundle().getBundleContext()));
+            } else {
+                errors.append(error);
+            }
+            if (errors.length() > 0) {
+                throw new IllegalArgumentException(errors.toString());
             }
         }
         return result;
index f567f1b31e134be26e6b21124d9ba66ae9f1ce17..ab81143170b91d3c4565049539b16bc410469abe 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegi
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -27,6 +28,7 @@ public class ConfigManagerActivator implements BundleActivator {
     private ExtenderBundleTracker extenderBundleTracker;
     private ConfigRegistryImpl configRegistry;
     private ConfigRegistryJMXRegistrator configRegistryJMXRegistrator;
+    private ServiceRegistration configRegistryServiceRegistration;
 
     @Override
     public void start(BundleContext context) throws Exception {
@@ -37,6 +39,9 @@ public class ConfigManagerActivator implements BundleActivator {
                 bundleContextBackedModuleFactoriesResolver, context,
                 configMBeanServer);
 
+        // register config registry to OSGi
+        configRegistryServiceRegistration = context.registerService(ConfigRegistryImpl.class, configRegistry, null);
+
         // register config registry to jmx
         configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(configMBeanServer);
         configRegistryJMXRegistrator.registerToJMX(configRegistry);
@@ -69,5 +74,10 @@ public class ConfigManagerActivator implements BundleActivator {
                     "Exception while closing config registry jmx registrator",
                     e);
         }
+        try {
+            configRegistryServiceRegistration.unregister();
+        } catch (Exception e) {
+            logger.warn("Exception while unregistering config registry", e);
+        }
     }
 }
index 6cd855450ddec8df16df9431701598fb9084ecd8..76cb64cf9349ae62cc99d7f66eb12e7f66a0ed74 100644 (file)
@@ -87,6 +87,7 @@ public class InterfacesHelper {
      */
     public static Set<Class<?>> getOsgiRegistrationTypes(
             Class<? extends Module> configBeanClass) {
+        // TODO test with service interface hierarchy
         Set<Class<?>> serviceInterfaces = getServiceInterfaces(configBeanClass);
         Set<Class<?>> result = new HashSet<>();
         for (Class<?> clazz : serviceInterfaces) {
index 928f2c18790e310be52f45decea364ec7b94accf..ccb67d371e5e63b9abac0be0a6baeba85f9a352b 100644 (file)
@@ -33,14 +33,15 @@ public class ConfigRegistryImplTest extends
     @Test
     public void testFailOnTwoFactoriesExportingSameImpl() {
         ModuleFactory factory = new TestingFixedThreadPoolModuleFactory();
-        ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver(
-                factory, factory);
-
         BundleContext context = mock(BundleContext.class);
-
-        ConfigRegistryImpl configRegistry = new ConfigRegistryImpl(resolver,
-                context, ManagementFactory.getPlatformMBeanServer());
+        ConfigRegistryImpl configRegistry = null;
         try {
+            ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver(
+                    factory, factory);
+
+            configRegistry = new ConfigRegistryImpl(resolver,
+                    context, ManagementFactory.getPlatformMBeanServer());
+
             configRegistry.beginConfig();
             fail();
         } catch (IllegalArgumentException e) {
index 18a22bb26fa91560dcc24be28a5e9c65877413c1..5ed56bd2bf6f81081be3369a9fa7ffc848c33ace 100644 (file)
@@ -7,21 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import java.io.Closeable;
-import java.lang.management.ManagementFactory;
-import java.util.Dictionary;
-import java.util.Set;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
 import org.junit.After;
 import org.mockito.Matchers;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
@@ -35,6 +20,20 @@ import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.io.Closeable;
+import java.lang.management.ManagementFactory;
+import java.util.Dictionary;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
 /**
  * Each test that relies on
  * {@link org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl}
@@ -51,7 +50,7 @@ public abstract class AbstractConfigTest extends
     protected ConfigRegistryJMXClient configRegistryClient;
     protected BaseJMXRegistrator baseJmxRegistrator;
     protected InternalJMXRegistrator internalJmxRegistrator;
-    protected BundleContext mockedContext;
+    protected BundleContext mockedContext = mock(BundleContext.class);
     protected ServiceRegistration<?> mockedServiceRegistration;
 
     // this method should be called in @Before
@@ -62,12 +61,12 @@ public abstract class AbstractConfigTest extends
 
         configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(
                 platformMBeanServer);
-        this.mockedContext = mock(BundleContext.class);
         this.mockedServiceRegistration = mock(ServiceRegistration.class);
         doNothing().when(mockedServiceRegistration).unregister();
         doReturn(mockedServiceRegistration).when(mockedContext).registerService(
                 Matchers.any(String[].class), any(Closeable.class),
                 any(Dictionary.class));
+
         internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
         baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
 
index c77c97b8f0ca1e93efc04aee03ff4eb27c54bed5..3cb0f447b464d89efd32f69c84378d0de77a5671 100644 (file)
@@ -17,13 +17,14 @@ import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistr
 import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.runtimembean.TestingRuntimeBean;
 import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
 
 import javax.management.MBeanServer;
 import javax.management.MBeanServerFactory;
 import javax.management.ObjectName;
 import java.lang.management.ManagementFactory;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
@@ -59,7 +60,7 @@ public class ConfigTransactionControllerImplTest extends
         baseJMXRegistrator = new BaseJMXRegistrator(
                 ManagementFactory.getPlatformMBeanServer());
         transactionsMBeanServer = MBeanServerFactory.createMBeanServer();
-        List<ModuleFactory> currentlyRegisteredFactories = new ArrayList<>();
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories = new HashMap<>();
         TransactionJMXRegistrator jmxRegistrator123 = baseJMXRegistrator
                 .createTransactionJMXRegistrator(transactionName123);
 
index 04f651f6d301e39d890aea81270e05c458d33853..3c2230735eee0c41589e33dfb03b9e7c5972a0d8 100644 (file)
@@ -7,21 +7,76 @@
  */
 package org.opendaylight.controller.config.manager.impl.factoriesresolver;
 
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import java.io.Closeable;
 import java.util.Arrays;
+import java.util.Dictionary;
 import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.AbstractMap;
 
-import org.opendaylight.controller.config.spi.ModuleFactory;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
 public class HardcodedModuleFactoriesResolver implements ModuleFactoriesResolver {
-    private final List<ModuleFactory> list;
+    private Map<String, Map.Entry<ModuleFactory, BundleContext>> factories;
+
+    public HardcodedModuleFactoriesResolver(BundleContext bundleContext, ModuleFactory... list) {
+        List<ModuleFactory> factoryList = Arrays.asList(list);
+        this.factories = new HashMap<>(factoryList.size());
+        for (ModuleFactory moduleFactory : list) {
+            StringBuffer errors = new StringBuffer();
+            String moduleName = moduleFactory.getImplementationName();
+            if (moduleName == null || moduleName.isEmpty()) {
+                throw new IllegalStateException(
+                        "Invalid implementation name for " + moduleFactory);
+            }
+            String error = null;
+            Map.Entry<ModuleFactory, BundleContext> conflicting = factories.get(moduleName);
+            if (conflicting != null) {
+                error = String
+                        .format("Module name is not unique. Found two conflicting factories with same name '%s': " +
+                                "\n\t%s\n\t%s\n", moduleName, conflicting.getKey(), moduleFactory);
+
+            }
+
+            if (error == null) {
+                factories.put(moduleName, new AbstractMap.SimpleEntry<>(moduleFactory,
+                        bundleContext));
+            } else {
+                errors.append(error);
+            }
+            if (errors.length() > 0) {
+                throw new IllegalArgumentException(errors.toString());
+            }
+        }
+    }
 
     public HardcodedModuleFactoriesResolver(ModuleFactory... list) {
-        this.list = Arrays.asList(list);
+        this(mockBundleContext(),list);
+    }
+
+    private static BundleContext mockBundleContext() {
+        BundleContext bundleContext = Mockito.mock(BundleContext.class);
+        ServiceRegistration<ModuleFactory> serviceRegistration = mock(ServiceRegistration.class);
+        doNothing().when(serviceRegistration).unregister();
+        doReturn(serviceRegistration).when(bundleContext).registerService(
+                Matchers.any(String[].class), any(Closeable.class),
+                any(Dictionary.class));
+        return bundleContext;
     }
 
     @Override
-    public List<ModuleFactory> getAllFactories() {
-        return list;
+    public Map<String, Map.Entry<ModuleFactory, BundleContext>> getAllFactories() {
+        return factories;
     }
 
 }
index a157e1ed5d4ff087b7d44963217e1886bfab9678..5e8612f7b94eae1fda8119ec7b25cafb98eafa0c 100644 (file)
@@ -8,6 +8,22 @@
  */
 package org.opendaylight.controller.config.yang.logback.config;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DependencyResolverFactory;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.osgi.framework.BundleContext;
+import org.slf4j.LoggerFactory;
+
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
@@ -17,21 +33,10 @@ import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
 import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
 import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
+
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
-import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.osgi.framework.BundleContext;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import com.google.common.collect.Sets;
 
 /**
 *
@@ -39,15 +44,15 @@ import java.util.Map.Entry;
 public class LogbackModuleFactory extends
         org.opendaylight.controller.config.yang.logback.config.AbstractLogbackModuleFactory {
 
-    private static final String INSTANCE_NAME = "singleton";
+    public static final String INSTANCE_NAME = "singleton";
     private Map<String, LoggerTO> loggersDTOs;
     private Map<String, RollingFileAppenderTO> rollingDTOs;
     private Map<String, ConsoleAppenderTO> consoleDTOs;
     private Map<String, FileAppenderTO> fileDTOs;
 
     @Override
-    public LogbackModule instantiateModule(String instanceName,
-            DependencyResolver dependencyResolver, BundleContext bundleContext) {
+    public LogbackModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+            BundleContext bundleContext) {
         Preconditions.checkArgument(instanceName.equals(INSTANCE_NAME),
                 "There should be just one instance of logback, named " + INSTANCE_NAME);
         prepareDTOs();
@@ -61,9 +66,8 @@ public class LogbackModuleFactory extends
     }
 
     @Override
-    public LogbackModule instantiateModule(String instanceName,
-            DependencyResolver dependencyResolver, LogbackModule oldModule,
-            AutoCloseable oldInstance, BundleContext bundleContext) {
+    public LogbackModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+            LogbackModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) {
         Preconditions.checkArgument(instanceName.equals(INSTANCE_NAME),
                 "There should be just one instance of logback, named " + INSTANCE_NAME);
         prepareDTOs();
@@ -220,4 +224,14 @@ public class LogbackModuleFactory extends
         return Lists.newArrayList(loggersToReturn.values());
     }
 
+    @Override
+    public Set<LogbackModule> getDefaultModules(DependencyResolverFactory dependencyResolverFactory,
+            BundleContext bundleContext) {
+        DependencyResolver resolver = dependencyResolverFactory.createDependencyResolver(new ModuleIdentifier(
+                getImplementationName(), INSTANCE_NAME));
+        LogbackModule defaultLogback = instantiateModule(INSTANCE_NAME, resolver, bundleContext);
+        Set<LogbackModule> defaultModules = Sets.newHashSet(defaultLogback);
+        return defaultModules;
+    }
+
 }
index 846b9cd352b48ebd34fa13ea99ab0301adf97501..296ce79f6e9cefeb5723107a59cef9b4cc0f3194 100644 (file)
@@ -7,29 +7,24 @@
  */
 package org.opendaylight.controller.config.yang.logback.config;
 
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.junit.matchers.JUnitMatchers.containsString;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
 public class LogbackModuleTest extends AbstractConfigTest {
 
     private static final String INSTANCE_NAME = "singleton";
@@ -37,14 +32,14 @@ public class LogbackModuleTest extends AbstractConfigTest {
     private LogbackModuleFactory factory;
 
     @Before
-    public void setUp() throws IOException, ClassNotFoundException, InterruptedException {
+    public void setUp() throws Exception {
 
         factory = new LogbackModuleFactory();
         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
     }
 
     @Test
-    public void testCreateBean() throws InstanceAlreadyExistsException {
+    public void testCreateBean() throws Exception {
 
         CommitStatus status = createBeans(true, "target/rollingApp",
                 "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5, "target/%i.log", "rolling",
@@ -55,7 +50,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testReusingInstance() throws InstanceAlreadyExistsException {
+    public void testReusingInstance() throws Exception {
         createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5,
                 "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "FixedWindowRollingPolicy", 0,
                 "FileAppender").commit();
@@ -70,8 +65,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testRecreateInstance() throws InstanceAlreadyExistsException, ValidationException,
-            ConflictingVersionException, InstanceNotFoundException {
+    public void testRecreateInstance() throws Exception {
         createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5,
                 "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "FixedWindowRollingPolicy", 0,
                 "FileAppender").commit();
@@ -88,7 +82,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testDestroyInstance() throws InstanceNotFoundException, InstanceAlreadyExistsException {
+    public void testDestroyInstance() throws Exception {
         createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5,
                 "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "FixedWindowRollingPolicy", 0,
                 "FileAppender").commit();
@@ -104,7 +98,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
 
     @Ignore
     @Test
-    public void testValidation1() throws InstanceAlreadyExistsException {
+    public void testValidation1() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5,
                     "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "FixedWindowRollingPolicy",
@@ -116,7 +110,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation2() throws InstanceAlreadyExistsException {
+    public void testValidation2() throws Exception {
         try {
             createBeans(true, "target/rollingApp", null, "30MB", 1, 5, "target/%i.log", "rolling", "consoleName",
                     "ALL", "logger1", "DEBUG", "FixedWindowRollingPolicy", 0, "FileAppender").commit();
@@ -127,7 +121,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation4() throws InstanceAlreadyExistsException {
+    public void testValidation4() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", null, 1, 5,
                     "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "FixedWindowRollingPolicy",
@@ -139,7 +133,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation6() throws InstanceAlreadyExistsException {
+    public void testValidation6() throws Exception {
         try {
             createBeans(true, "", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5, "target/%i.log",
                     "rolling", "consoleName", "ALL", "logger1", "DEBUG", "FixedWindowRollingPolicy", 0, "FileAppender")
@@ -151,7 +145,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation7() throws InstanceAlreadyExistsException {
+    public void testValidation7() throws Exception {
         try {
             createBeans(
 
@@ -164,7 +158,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation8() throws InstanceAlreadyExistsException {
+    public void testValidation8() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5,
                     "target/%i.log", "rolling", "consoleName", "ALL", null, "DEBUG", "FixedWindowRollingPolicy", 0,
@@ -176,7 +170,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation9() throws InstanceAlreadyExistsException {
+    public void testValidation9() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1, 5,
                     "target/%i.log", "rolling", "consoleName", "ALL", "", "DEBUG", "FixedWindowRollingPolicy", 0,
@@ -188,7 +182,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation10() throws InstanceAlreadyExistsException {
+    public void testValidation10() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", null,
                     5, "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG",
@@ -200,7 +194,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation11() throws InstanceAlreadyExistsException {
+    public void testValidation11() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1,
                     null, "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG",
@@ -212,7 +206,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation12() throws InstanceAlreadyExistsException {
+    public void testValidation12() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1,
                     null, "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", null, 1, "FileAppender")
@@ -224,7 +218,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation13() throws InstanceAlreadyExistsException {
+    public void testValidation13() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1,
                     null, "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "", 1, "FileAppender")
@@ -236,7 +230,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testValidation14() throws InstanceAlreadyExistsException {
+    public void testValidation14() throws Exception {
         try {
             createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", 1,
                     null, "target/%i.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "RollingPolicy", 1,
@@ -248,7 +242,7 @@ public class LogbackModuleTest extends AbstractConfigTest {
     }
 
     @Test
-    public void testTimeBasedRollingPolicy() throws InstanceAlreadyExistsException {
+    public void testTimeBasedRollingPolicy() throws Exception {
         createBeans(true, "target/rollingApp", "%-4relative [%thread] %-5level %logger{35} - %msg%n", "30MB", null,
                 null, "target/%d.log", "rolling", "consoleName", "ALL", "logger1", "DEBUG", "TimeBasedRollingPolicy",
                 1, "FileAppender").commit();
@@ -257,10 +251,10 @@ public class LogbackModuleTest extends AbstractConfigTest {
     private ConfigTransactionJMXClient createBeans(Boolean isAppend, String rollingFileName, String encoderPattern,
             String maxFileSize, Integer minIndex, Integer maxIndex, String fileNamePattern, String rollingName,
             String consoleName, String thresholdFilter, String loggerName, String level, String rollingPolicyType,
-            int maxHistory, String fileAppName) throws InstanceAlreadyExistsException {
+            int maxHistory, String fileAppName) throws Exception {
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
-        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), INSTANCE_NAME);
-        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameCreated, LogbackModuleMXBean.class);
+        ObjectName nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), INSTANCE_NAME);
+        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameRetrieved, LogbackModuleMXBean.class);
 
         List<RollingFileAppenderTO> rollingAppenders = new ArrayList<>();
         RollingFileAppenderTO rollingAppender = new RollingFileAppenderTO();
index 79e46ae6d212d56b4613643d48315ca535844375..eeb8289e86196665cd971ce932112779fee04bb7 100644 (file)
@@ -17,7 +17,9 @@ import java.util.Arrays;
 import java.util.List;
 
 import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
 import javax.management.JMX;
+import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
 import org.apache.commons.io.FileUtils;
@@ -142,7 +144,8 @@ public class LogbackModuleWithInitialConfigurationTest extends AbstractConfigTes
 
     }
 
-    public ObjectName createBeans() throws JoranException, InstanceAlreadyExistsException, IOException {
+    public ObjectName createBeans() throws JoranException, InstanceAlreadyExistsException, IOException,
+            MalformedObjectNameException, InstanceNotFoundException {
 
         LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
 
@@ -200,8 +203,8 @@ public class LogbackModuleWithInitialConfigurationTest extends AbstractConfigTes
         loggersDTOs.add(log);
 
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
-        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), "singleton");
-        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameCreated, LogbackModuleMXBean.class);
+        ObjectName nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), LogbackModuleFactory.INSTANCE_NAME);
+        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameRetrieved, LogbackModuleMXBean.class);
 
         bean.setLoggerTO(loggersDTOs);
         bean.setRollingFileAppenderTO(rollingAppenders);
@@ -210,6 +213,6 @@ public class LogbackModuleWithInitialConfigurationTest extends AbstractConfigTes
 
         transaction.commit();
 
-        return nameCreated;
+        return nameRetrieved;
     }
 }
index 004c18c5e08c0b2224e3f50b69654961a68e3258..8718f8a9ce3121c260d41555f8ff509849c09b97 100644 (file)
@@ -17,6 +17,7 @@ import java.util.List;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.JMX;
+import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
 import org.apache.commons.io.FileUtils;
@@ -27,12 +28,12 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
-
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
 import ch.qos.logback.core.joran.spi.JoranException;
 
+import com.google.common.collect.Lists;
+
 public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest {
 
     private LogbackModuleFactory factory;
@@ -56,14 +57,16 @@ public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest {
 
     /**
      * Tests configuration of Logger factory.
+     *
+     * @throws MalformedObjectNameException
      */
     @Test
-    public void test() throws InstanceAlreadyExistsException, InstanceNotFoundException {
+    public void test() throws InstanceAlreadyExistsException, InstanceNotFoundException, MalformedObjectNameException {
 
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
-        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), "singleton");
+        ObjectName nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), LogbackModuleFactory.INSTANCE_NAME);
 
-        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameCreated, LogbackModuleMXBean.class);
+        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameRetrieved, LogbackModuleMXBean.class);
 
         assertEquals(1, bean.getConsoleAppenderTO().size());
 
@@ -73,9 +76,9 @@ public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest {
 
         transaction = configRegistryClient.createTransaction();
 
-        nameCreated = transaction.lookupConfigBean(factory.getImplementationName(), "singleton");
+        nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), "singleton");
 
-        bean = JMX.newMXBeanProxy(platformMBeanServer, nameCreated, LogbackModuleMXBean.class);
+        bean = JMX.newMXBeanProxy(platformMBeanServer, nameRetrieved, LogbackModuleMXBean.class);
 
         assertEquals(1, bean.getConsoleAppenderTO().size());
         assertEquals(1, bean.getRollingFileAppenderTO().size());
@@ -89,11 +92,6 @@ public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest {
     @Test
     public void testAllLoggers() throws InstanceAlreadyExistsException, InstanceNotFoundException {
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
-        transaction.createModule(factory.getImplementationName(), "singleton");
-
-        transaction.commit();
-
-        transaction = configRegistryClient.createTransaction();
 
         LogbackModuleMXBean bean = JMX.newMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
                 transaction.lookupConfigBean("logback", "singleton"), LogbackModuleMXBean.class);
@@ -103,13 +101,16 @@ public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest {
 
     /**
      * Add new logger using FileAppender
+     *
+     * @throws MalformedObjectNameException
      */
     @Test
-    public void testAddNewLogger() throws InstanceAlreadyExistsException, InstanceNotFoundException {
+    public void testAddNewLogger() throws InstanceAlreadyExistsException, InstanceNotFoundException,
+            MalformedObjectNameException {
 
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
-        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), "singleton");
-        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameCreated, LogbackModuleMXBean.class);
+        ObjectName nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), LogbackModuleFactory.INSTANCE_NAME);
+        LogbackModuleMXBean bean = transaction.newMXBeanProxy(nameRetrieved, LogbackModuleMXBean.class);
 
         assertEquals(5, bean.getLoggerTO().size());
 
@@ -124,8 +125,8 @@ public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest {
         transaction.commit();
 
         transaction = configRegistryClient.createTransaction();
-        nameCreated = transaction.lookupConfigBean(factory.getImplementationName(), "singleton");
-        bean = JMX.newMXBeanProxy(platformMBeanServer, nameCreated, LogbackModuleMXBean.class);
+        nameRetrieved = transaction.lookupConfigBean(factory.getImplementationName(), "singleton");
+        bean = JMX.newMXBeanProxy(platformMBeanServer, nameRetrieved, LogbackModuleMXBean.class);
 
         assertEquals(6, bean.getLoggerTO().size());
     }
index aed3a0cc1596b9fc15b2e93fb7516a40971d3ef8..02cbd247a71db70f8dee044771eb904fa67b3b0b 100644 (file)
@@ -14,7 +14,9 @@ import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.EventExecutorGroup;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
+import io.netty.util.concurrent.ScheduledFuture;
 
+import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -108,5 +110,24 @@ public final class GlobalEventExecutorModule extends
             this.executor.shutdown();
         }
 
+        @Override
+        public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
+            return this.executor.scheduleWithFixedDelay(command, initialDelay, delay, unit);
+        }
+
+        @Override
+        public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+            return this.executor.schedule(command, delay, unit);
+        }
+
+        @Override
+        public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+            return this.executor.schedule(callable, delay, unit);
+        }
+
+        @Override
+        public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
+            return this.executor.scheduleAtFixedRate(command, initialDelay, period, unit);
+        }
     }
 }
index fcdc10f109bca6289b3cc181821970430ffa6066..9356dd3752331f2f34fcc33b5df87151081a04b7 100644 (file)
@@ -125,7 +125,7 @@ public class ExtenderYangTracker extends BundleTracker<Object> implements YangSt
         // inconsistent state
         inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
 
-        logger.debug("Yang store is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
+        logger.debug("Yang store is falling back on last consistent state containing {}, inconsistent yang files {}",
                 consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, failureReason);
         logger.warn("Yang store is falling back on last consistent state containing {} files, inconsistent yang files size is {}, reason {}",
                 consistentBundlesToYangURLs.size(), inconsistentBundlesToYangURLs.size(), failureReason.toString());
index b82d2dae3cbf769a5e64239f178d6aaa3e7703f0..99568dfcce886fb89de47fba5cc775b00a24530a 100644 (file)
@@ -35,7 +35,7 @@ import org.opendaylight.controller.sal.utils.StatusCode;
  * files through java serialization API when saving to/reading from Container
  * Manager startup configuration file.
  */
-@XmlRootElement(name = "container-config")
+@XmlRootElement(name = "containerConfig")
 @XmlAccessorType(XmlAccessType.NONE)
 public class ContainerConfig implements Serializable {
     private static final long serialVersionUID = 2L;
index 55ab5caeeb2098cd00ed4095a46f8601a14536b1..5b08af79f835e39b0d729424d31cf522ea78c256 100644 (file)
           <artifactId>sal-common-util</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-netconf-connector</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-core-api</artifactId>
           <artifactId>forwardingrules-manager</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
-
+        <dependency>
+          <groupId>org.opendaylight.controller.md</groupId>
+          <artifactId>statistics-manager</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>concepts</artifactId>
           <artifactId>yang-jmx-generator</artifactId>
           <version>${config.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netty-event-executor-config</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>netty-threadgroup-config</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>threadpool-config-api</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>threadpool-config-impl</artifactId>
+          <version>${config.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>yang-store-api</artifactId>
+          <version>${config.version}</version>
+        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>yang-store-api</artifactId>
index fa0b5893d5dbe38ece62cd797f04b520c93d8cde..947c15b35c27f19a5566f32849a33ab440982c70 100644 (file)
@@ -123,7 +123,5 @@ urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logg
 urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09
 urn:opendaylight:params:xml:ns:yang:iana?module=iana&revision=2013-08-16
 urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
-http://netconfcentral.org/ns/toaster?module=toaster&revision=2009-11-20
 urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&revision=2013-08-19
-urn:opendaylight:params:xml:ns:yang:nps-concepts?module=nps-concepts&revision=2013-09-30
 //END OF CONFIG
index b5f540222a353ede646ddb18246c55e4c9854d82..597483ef6541456b4e417c255e71465e8fa0fe79 100644 (file)
       <artifactId>model-flow-management</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-common</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-broker-impl</artifactId>
index 522b09681b5b77f523d65b010cbc8fb30ade09bd..ae6ce2f8004dd3a3244ff2567507b175fade9f53 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
@@ -57,7 +58,7 @@ public class FRMUtil {
 
     }
 
-    public static boolean validateMatch(NodeFlow flow) {
+    public static boolean validateMatch(Flow flow) {
         Match match = flow.getMatch();
         if (match != null) {
             EthernetMatch ethernetmatch = match.getEthernetMatch();
@@ -198,9 +199,12 @@ public class FRMUtil {
         return true;
     }
 
-    public static boolean validateInstructions(NodeFlow flow) {
+    public static boolean validateInstructions(Flow flow) {
         List<Instruction> instructionsList = new ArrayList<>();
         Instructions instructions = flow.getInstructions();
+        if( instructions == null ) {
+            return false;
+        }
         instructionsList = instructions.getInstruction();
 
         for (Instruction instruction : instructionsList) {
index 2ffe0ecd87eee775b08f6e5b51c1e0febcb66baf..9d2a6a0b110f333be53b6640cb02c83653982e99 100644 (file)
@@ -1,8 +1,10 @@
 package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -20,12 +22,7 @@ import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.Data
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.IContainer;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.ServiceHelper;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.sal.utils.StatusCode;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.Switch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
@@ -54,6 +51,7 @@ import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -86,8 +84,7 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
     private boolean inContainerMode; // being used by global instance only
 
     public FlowConsumerImpl() {
-        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Flows.class).child(Flow.class)
-                .toInstance();
+        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Flows.class).toInstance();
         flowService = FRMConsumerImpl.getProviderSession().getRpcService(SalFlowService.class);
 
         if (null == flowService) {
@@ -116,12 +113,11 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
         }
         // addFlowTest();
         System.out.println("-------------------------------------------------------------------");
-        allocateCaches();
         commitHandler = new FlowDataCommitHandler();
         FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
         clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(
                 IClusterContainerServices.class, this);
-        container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+        allocateCaches();
         /*
          * If we are not the first cluster node to come up, do not initialize
          * the static flow entries ordinal
@@ -204,13 +200,20 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
         System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
 
         // updating the staticflow cache
+        /*
+         *  Commented out... as in many other places... use of ClusteringServices is breaking things
+         *  insufficient time to debug
         Integer ordinal = staticFlowsOrdinal.get(0);
         staticFlowsOrdinal.put(0, ++ordinal);
         staticFlows.put(ordinal, dataObject);
+        */
 
         // We send flow to the sounthbound plugin
         flowService.addFlow(input.build());
+        /*
+         * Commented out as this will also break due to improper use of ClusteringServices
         updateLocalDatabase((NodeFlow) dataObject, true);
+        */
     }
 
     /**
@@ -237,13 +240,19 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
         System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
 
         // updating the staticflow cache
+        /*
+         * Commented out due to problems caused by improper use of ClusteringServices
         Integer ordinal = staticFlowsOrdinal.get(0);
         staticFlowsOrdinal.put(0, ++ordinal);
         staticFlows.put(ordinal, dataObject);
+        */
 
         // We send flow to the sounthbound plugin
         flowService.removeFlow(input.build());
+        /*
+         * Commented out due to problems caused by improper use of ClusteringServices
         updateLocalDatabase((NodeFlow) dataObject, false);
+        */
     }
 
     /**
@@ -257,33 +266,60 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
         UpdateFlowInputBuilder input = new UpdateFlowInputBuilder();
         UpdatedFlowBuilder updatedflowbuilder = new UpdatedFlowBuilder();
         updatedflowbuilder.fieldsFrom(dataObject);
+        input.setNode(dataObject.getNode());
         input.setUpdatedFlow(updatedflowbuilder.build());
 
         // updating the staticflow cache
+        /*
+         * Commented out due to problems caused by improper use of ClusteringServices.
         Integer ordinal = staticFlowsOrdinal.get(0);
         staticFlowsOrdinal.put(0, ++ordinal);
         staticFlows.put(ordinal, dataObject);
+        */
 
         // We send flow to the sounthbound plugin
         flowService.updateFlow(input.build());
+        /*
+         * Commented out due to problems caused by improper use of ClusteringServices.
         updateLocalDatabase((NodeFlow) dataObject, true);
+        */
     }
 
     @SuppressWarnings("unchecked")
     private void commitToPlugin(internalTransaction transaction) {
-        for (Entry<InstanceIdentifier<?>, Flow> entry : transaction.additions.entrySet()) {
-            System.out.println("Coming add cc in FlowDatacommitHandler");
-            addFlow(entry.getKey(), entry.getValue());
+        Set<Entry<InstanceIdentifier<?>, DataObject>> createdEntries = transaction.getModification().getCreatedConfigurationData().entrySet();
+
+        /*
+         * This little dance is because updatedEntries contains both created and modified entries
+         * The reason I created a new HashSet is because the collections we are returned are immutable.
+         */
+        Set<Entry<InstanceIdentifier<?>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<?>, DataObject>>();
+        updatedEntries.addAll(transaction.getModification().getUpdatedConfigurationData().entrySet());
+        updatedEntries.removeAll(createdEntries);
+
+        Set<InstanceIdentifier<?>> removeEntriesInstanceIdentifiers = transaction.getModification().getRemovedConfigurationData();
+        transaction.getModification().getOriginalConfigurationData();
+        for (Entry<InstanceIdentifier<?>, DataObject> entry : createdEntries) {
+            if(entry.getValue() instanceof Flow) {
+                System.out.println("Coming add cc in FlowDatacommitHandler");
+                addFlow(entry.getKey(), (Flow) entry.getValue());
+            }
         }
         for (@SuppressWarnings("unused")
-        Entry<InstanceIdentifier<?>, Flow> entry : transaction.updates.entrySet()) {
-            System.out.println("Coming update cc in FlowDatacommitHandler");
-            updateFlow(entry.getKey(), entry.getValue());
+        Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
+            if(entry.getValue() instanceof Flow) {
+                System.out.println("Coming update cc in FlowDatacommitHandler");
+                updateFlow(entry.getKey(), (Flow) entry.getValue());
+            }
         }
 
-        for (Entry<InstanceIdentifier<?>, Flow> entry : transaction.removals.entrySet()) {
-            System.out.println("Coming remove cc in FlowDatacommitHandler");
-            removeFlow(entry.getKey(), entry.getValue());
+        for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
+            DataObject removeValue = transaction.getModification().getOriginalConfigurationData().get(instanceId);
+            if(removeValue instanceof Flow) {
+                System.out.println("Coming remove cc in FlowDatacommitHandler");
+                removeFlow(instanceId, (Flow) removeValue);
+
+            }
         }
 
     }
@@ -329,39 +365,42 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
             for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
 
                 // validating the DataObject
-
-                Status status = validate(container, (NodeFlow) entry);
-                if (!status.isSuccess()) {
-                    logger.warn("Invalid Configuration for flow {}. The failure is {}", entry, status.getDescription());
-                    String error = "Invalid Configuration (" + status.getDescription() + ")";
-                    logger.error(error);
-                    return;
-                }
-                // Presence check
-                if (flowEntryExists((NodeFlow) entry)) {
-                    String error = "Entry with this name on specified table already exists";
-                    logger.warn("Entry with this name on specified table already exists: {}", entry);
-                    logger.error(error);
-                    return;
-                }
-                if (originalSwView.containsKey(entry)) {
-                    logger.warn("Operation Rejected: A flow with same match and priority exists on the target node");
-                    logger.trace("Aborting to install {}", entry);
-                    continue;
-                }
-                if (!FRMUtil.validateMatch((NodeFlow) entry)) {
-                    logger.error("Not a valid Match");
-                    return;
-                }
-                if (!FRMUtil.validateInstructions((NodeFlow) entry)) {
-                    logger.error("Not a valid Instruction");
-                    return;
-                }
-                if (entry.getValue() instanceof Flow) {
-                    Flow flow = (Flow) entry.getValue();
-                    preparePutEntry(entry.getKey(), flow);
+                DataObject value = entry.getValue();
+                if(value instanceof Flow ) {
+                    Flow flow = (Flow)value;
+                    boolean status = validate(flow);
+                    if (!status) {
+                        return;
+                    }
+                    // Presence check
+                    /*
+                     * This is breaking due to some improper use of caches...
+                     *
+                    if (flowEntryExists(flow)) {
+                        String error = "Entry with this name on specified table already exists";
+                        logger.warn("Entry with this name on specified table already exists: {}", entry);
+                        logger.error(error);
+                        return;
+                    }
+                    if (originalSwView.containsKey(entry)) {
+                        logger.warn("Operation Rejected: A flow with same match and priority exists on the target node");
+                        logger.trace("Aborting to install {}", entry);
+                        continue;
+                    }
+                    */
+                    if (!FRMUtil.validateMatch(flow)) {
+                        logger.error("Not a valid Match");
+                        return;
+                    }
+                    if (!FRMUtil.validateInstructions(flow)) {
+                        logger.error("Not a valid Instruction");
+                        return;
+                    }
+                    /*
+                     * Commented out due to Clustering Services issues
+                     * preparePutEntry(entry.getKey(), flow);
+                     */
                 }
-
             }
 
             // removals = modification.getRemovedConfigurationData();
@@ -398,7 +437,7 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
             commitToPlugin(this);
             // We return true if internal transaction is successful.
             // return Rpcs.getRpcResult(true, null, Collections.emptySet());
-            return Rpcs.getRpcResult(true, null, null);
+            return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
         }
 
         /**
@@ -411,58 +450,48 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
             // NOOP - we did not modified any internal state during
             // requestCommit phase
             // return Rpcs.getRpcResult(true, null, Collections.emptySet());
-            return Rpcs.getRpcResult(true, null, null);
+            return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
 
         }
 
-        public Status validate(IContainer container, NodeFlow dataObject) {
+        public boolean validate(Flow flow) {
+
+            String msg = ""; // Specific part of warn/error log
 
-            // container validation
-            Switch sw = null;
-            Node node = null;
-            String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
-            ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class,
-                    containerName, this);
+            boolean result  = true;
             // flow Name validation
-            if (dataObject.getFlowName() == null || dataObject.getFlowName().trim().isEmpty()
-                    || !dataObject.getFlowName().matches(NAMEREGEX)) {
-                return new Status(StatusCode.BADREQUEST, "Invalid Flow name");
+            if (flow.getFlowName() == null || flow.getFlowName().trim().isEmpty()
+                    || !flow.getFlowName().matches(NAMEREGEX)) {
+                msg = "Invalid Flow name";
+                result = false;
             }
             // Node Validation
-            if (dataObject.getNode() == null) {
-                return new Status(StatusCode.BADREQUEST, "Node is null");
+            if (result == true && flow.getNode() == null) {
+                msg = "Node is null";
+                result = false;
             }
 
-            if (switchManager != null) {
-                for (Switch device : switchManager.getNetworkDevices()) {
-                    node = (Node) device.getNode();
-                    if (device.getNode().equals(dataObject.getNode())) {
-                        sw = device;
-                        break;
-                    }
-                }
-                if (sw == null) {
-                    return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
-                }
-            } else {
-                logger.debug("switchmanager is not set yet");
-            }
+            // TODO: Validate we are seeking to program a flow against a valid Node
 
-            if (dataObject.getPriority() != null) {
-                if (dataObject.getPriority() < 0 || dataObject.getPriority() > 65535) {
-                    return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
-                            dataObject.getPriority()));
+            if (result == true && flow.getPriority() != null) {
+                if (flow.getPriority() < 0 || flow.getPriority() > 65535) {
+                    msg = String.format("priority %s is not in the range 0 - 65535",
+                            flow.getPriority());
+                    result = false;
                 }
             }
-
-            return new Status(StatusCode.SUCCESS);
+            if (result == false) {
+                logger.warn("Invalid Configuration for flow {}. The failure is {}",flow,msg);
+                logger.error("Invalid Configuration ({})",msg);
+            }
+            return result;
         }
 
-        private boolean flowEntryExists(NodeFlow config) {
+        private boolean flowEntryExists(Flow flow) {
             // Flow name has to be unique on per table id basis
             for (ConcurrentMap.Entry<FlowKey, Flow> entry : originalSwView.entrySet()) {
-                if (entry.getValue().getFlowName().equals(config.getFlowName())
-                        && entry.getValue().getTableId().equals(config.getTableId())) {
+                if (entry.getValue().getFlowName().equals(flow.getFlowName())
+                        && entry.getValue().getTableId().equals(flow.getTableId())) {
                     return true;
                 }
             }
index 851e7d9b2685420b5093d8771770a64a3fe52250..714ac89ba13ccf66f3de6e211276d2aace61aba9 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -33,6 +34,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.Add
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
+
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
@@ -40,10 +43,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.gro
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.meters.Meter;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -225,7 +230,7 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
                 return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
             }
 
-            returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
+           /* returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
 
             if (FRMUtil.operation.ADD == operation && returnResult) {
                 logger.error("Record with same Group Name exists");
@@ -233,7 +238,7 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
             } else if (!returnResult) {
                 logger.error("Group record does not exist");
                 return new Status(StatusCode.BADREQUEST, "Group record does not exist");
-            }
+            }*/
 
             if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() && group.getGroupType()
                     .getIntValue() <= GroupType.GroupFf.getIntValue())) {
@@ -259,7 +264,7 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
 
     }
 
-    private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
+   /* private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
         if (!originalSwGroupView.containsKey(key)) {
             return false;
         }
@@ -271,8 +276,8 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
                 }
             }
         }
-        return false;
-    }
+        return true;
+    }*/
 
     /**
      * Update Group entries to the southbound plugin/inventory and our internal
@@ -292,11 +297,11 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
             return groupOperationStatus;
         }
 
-        if (originalSwGroupView.containsKey(groupKey)) {
+        /*if (originalSwGroupView.containsKey(groupKey)) {
             originalSwGroupView.remove(groupKey);
             originalSwGroupView.put(groupKey, groupUpdateDataObject);
         }
-
+*/
         if (groupUpdateDataObject.isInstall()) {
             UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
             updateGroupBuilder = new UpdatedGroupBuilder();
@@ -304,10 +309,10 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
             groupData.setUpdatedGroup(updateGroupBuilder.build());
             // TODO how to get original group and modified group.
 
-            if (installedSwGroupView.containsKey(groupKey)) {
+          /*  if (installedSwGroupView.containsKey(groupKey)) {
                 installedSwGroupView.remove(groupKey);
                 installedSwGroupView.put(groupKey, groupUpdateDataObject);
-            }
+            }*/
 
             groupService.updateGroup(groupData.build());
         }
@@ -330,7 +335,7 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
             return groupOperationStatus;
         }
 
-        originalSwGroupView.put(groupKey, groupAddDataObject);
+        //originalSwGroupView.put(groupKey, groupAddDataObject);
 
         if (groupAddDataObject.isInstall()) {
             AddGroupInputBuilder groupData = new AddGroupInputBuilder();
@@ -339,19 +344,49 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
             groupData.setGroupId(groupAddDataObject.getGroupId());
             groupData.setGroupType(groupAddDataObject.getGroupType());
             groupData.setNode(groupAddDataObject.getNode());
-            installedSwGroupView.put(groupKey, groupAddDataObject);
+        //   installedSwGroupView.put(groupKey, groupAddDataObject);
             groupService.addGroup(groupData.build());
         }
 
         return groupOperationStatus;
     }
 
-    private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
+    /**
+     * Remove Group to the southbound plugin and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private Status removeGroup(InstanceIdentifier<?> path, Group groupRemoveDataObject) {
+        GroupKey groupKey = groupRemoveDataObject.getKey();
+        Status groupOperationStatus = validateGroup(groupRemoveDataObject, FRMUtil.operation.ADD);
+
+        if (!groupOperationStatus.isSuccess()) {
+            logger.error("Group data object validation failed %s" + groupRemoveDataObject.getGroupName());
+            return groupOperationStatus;
+        }
+        //originalSwGroupView.put(groupKey, groupAddDataObject);
+
+        if (groupRemoveDataObject.isInstall()) {
+            RemoveGroupInputBuilder groupData = new RemoveGroupInputBuilder();
+            groupData.setBuckets(groupRemoveDataObject.getBuckets());
+            groupData.setContainerName(groupRemoveDataObject.getContainerName());
+            groupData.setGroupId(groupRemoveDataObject.getGroupId());
+            groupData.setGroupType(groupRemoveDataObject.getGroupType());
+            groupData.setNode(groupRemoveDataObject.getNode());
+        //   installedSwGroupView.put(groupKey, groupAddDataObject);
+            groupService.removeGroup(groupData.build());
+        }
+
+        return groupOperationStatus;
+    }
+    
+    private RpcResult<Void> commitToPlugin(InternalTransaction transaction) {
         for (Entry<InstanceIdentifier<?>, Group> entry : transaction.additions.entrySet()) {
 
             if (!addGroup(entry.getKey(), entry.getValue()).isSuccess()) {
                 transaction.additions.remove(entry.getKey());
-                return Rpcs.getRpcResult(false, null, null);
+                return Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
             }
         }
 
@@ -359,12 +394,18 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
 
             if (!updateGroup(entry.getKey(), entry.getValue()).isSuccess()) {
                 transaction.updates.remove(entry.getKey());
-                return Rpcs.getRpcResult(false, null, null);
+                return Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
             }
         }
 
-        for (InstanceIdentifier<?> removal : transaction.removals) {
-            // removeFlow(removal);
+        for (InstanceIdentifier<?> groupId : transaction.removals) {
+                       DataObject removeValue = transaction.getModification().getOriginalConfigurationData().get(groupId);     
+                
+                       if(removeValue instanceof Group) {
+                           if(!removeGroup(groupId, (Group)removeValue).isSuccess()) {
+                               return Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet()); 
+                           }             
+                       }
         }
 
         return Rpcs.getRpcResult(true, null, null);
@@ -372,19 +413,18 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
 
     private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
 
-        @SuppressWarnings("unchecked")
         @Override
         public DataCommitTransaction<InstanceIdentifier<?>, DataObject> requestCommit(
                 DataModification<InstanceIdentifier<?>, DataObject> modification) {
             // We should verify transaction
             System.out.println("Coming in GroupDatacommitHandler");
-            internalTransaction transaction = new internalTransaction(modification);
+            InternalTransaction transaction = new InternalTransaction(modification);
             transaction.prepareUpdate();
             return transaction;
         }
     }
 
-    private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+    private final class InternalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
 
         private final DataModification<InstanceIdentifier<?>, DataObject> modification;
 
@@ -393,7 +433,7 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
             return modification;
         }
 
-        public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+        public InternalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
             this.modification = modification;
         }
 
@@ -407,33 +447,31 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
          *
          */
         void prepareUpdate() {
-
-            Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
-            for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+               
+                Set<Entry<InstanceIdentifier<?>, DataObject>> groupAdded = modification.getCreatedConfigurationData().entrySet();
+             for (Entry<InstanceIdentifier<?>, DataObject> entry : groupAdded) {
+                 if (entry.getValue() instanceof Group) {
+                     Group group = (Group) entry.getValue();
+                     additions.put(entry.getKey(), group);                     
+                 }
+
+             }
+
+            Set<Entry<InstanceIdentifier<?>, DataObject>> groupUpdate = modification.getUpdatedConfigurationData().entrySet();
+            for (Entry<InstanceIdentifier<?>, DataObject> entry : groupUpdate) {
                 if (entry.getValue() instanceof Group) {
                     Group group = (Group) entry.getValue();
-                    preparePutEntry(entry.getKey(), group);
+                    ///will be fixed once getUpdatedConfigurationData returns only updated data not created data with it.
+                    if (additions.containsKey(entry.getKey())) {
+                       updates.put(entry.getKey(), group);
+                    }
                 }
 
             }
 
             removals = modification.getRemovedConfigurationData();
         }
-
-        private void preparePutEntry(InstanceIdentifier<?> key, Group group) {
-
-            Group original = originalSwGroupView.get(key);
-            if (original != null) {
-                // It is update for us
-
-                updates.put(key, group);
-            } else {
-                // It is addition for us
-
-                additions.put(key, group);
-            }
-        }
-
+        
         /**
          * We are OK to go with execution of plan
          *
@@ -457,7 +495,7 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
             // NOOP - we did not modified any internal state during
             // requestCommit phase
             // return Rpcs.getRpcResult(true, null, Collections.emptySet());
-            return Rpcs.getRpcResult(true, null, null);
+            return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
 
         }
 
index bd0ceb3fea8011aaa575dea0e71e4cbb8a1032c9..483b9a47196580a2b16c9e0c63b2e41be7a40e9f 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -33,6 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.Add
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterAdded;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
@@ -45,6 +47,7 @@ import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -57,13 +60,17 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
     private MeterDataCommitHandler commitHandler;
 
     private ConcurrentMap<MeterKey, Meter> originalSwMeterView;
+    @SuppressWarnings("unused")
     private ConcurrentMap<MeterKey, Meter> installedSwMeterView;
-
+    @SuppressWarnings("unused")
     private ConcurrentMap<Node, List<Meter>> nodeMeters;
+    @SuppressWarnings("unused")
     private ConcurrentMap<MeterKey, Meter> inactiveMeters;
+    @SuppressWarnings("unused")
+    private IContainer container;
 
     private IClusterContainerServices clusterMeterContainerService = null;
-    private IContainer container;
+    
 
     public MeterConsumerImpl() {
         InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Meters.class).child(Meter.class)
@@ -218,11 +225,11 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
                 meterBuilder.setMeterBandHeaders(meterAddDataObject.getMeterBandHeaders());
                 meterBuilder.setMeterId(meterAddDataObject.getMeterId());
                 meterBuilder.setNode(meterAddDataObject.getNode());
-                originalSwMeterView.put(meterKey, meterAddDataObject);
+               // originalSwMeterView.put(meterKey, meterAddDataObject);
                 meterService.addMeter(meterBuilder.build());
             }
 
-            originalSwMeterView.put(meterKey, meterAddDataObject);
+           // originalSwMeterView.put(meterKey, meterAddDataObject);
         } else {
             return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
         }
@@ -243,10 +250,10 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
 
         if (null != meterKey && validateMeter(meterUpdateDataObject, FRMUtil.operation.UPDATE).isSuccess()) {
 
-            if (originalSwMeterView.containsKey(meterKey)) {
+           /* if (originalSwMeterView.containsKey(meterKey)) {
                 originalSwMeterView.remove(meterKey);
                 originalSwMeterView.put(meterKey, meterUpdateDataObject);
-            }
+            }*/
 
             if (meterUpdateDataObject.isInstall()) {
                 UpdateMeterInputBuilder updateMeterInputBuilder = new UpdateMeterInputBuilder();
@@ -254,10 +261,10 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
                 updateMeterBuilder.fieldsFrom(meterUpdateDataObject);
                 updateMeterInputBuilder.setUpdatedMeter(updateMeterBuilder.build());
 
-                if (installedSwMeterView.containsKey(meterKey)) {
+              /*  if (installedSwMeterView.containsKey(meterKey)) {
                     installedSwMeterView.remove(meterKey);
                     installedSwMeterView.put(meterKey, meterUpdateDataObject);
-                }
+                }*/
 
                 meterService.updateMeter(updateMeterInputBuilder.build());
             }
@@ -276,18 +283,23 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
      *
      * @param dataObject
      */
-    private Status RemoveMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {
-        MeterKey meterKey = meterUpdateDataObject.getKey();
-
-        if (null != meterKey && validateMeter(meterUpdateDataObject, FRMUtil.operation.ADD).isSuccess()) {
-            if (meterUpdateDataObject.isInstall()) {
-                UpdateMeterInputBuilder updateMeterBuilder = new UpdateMeterInputBuilder();
-
-                installedSwMeterView.put(meterKey, meterUpdateDataObject);
-                meterService.updateMeter(updateMeterBuilder.build());
+    private Status removeMeter(InstanceIdentifier<?> path, Meter meterRemoveDataObject) {
+        MeterKey meterKey = meterRemoveDataObject.getKey();
+
+        if (null != meterKey && validateMeter(meterRemoveDataObject, FRMUtil.operation.DELETE).isSuccess()) {
+            if (meterRemoveDataObject.isInstall()) {
+                RemoveMeterInputBuilder meterBuilder = new RemoveMeterInputBuilder();
+                meterBuilder.setContainerName(meterRemoveDataObject.getContainerName());
+                meterBuilder.setNode(meterRemoveDataObject.getNode());
+                meterBuilder.setFlags(meterRemoveDataObject.getFlags());
+                meterBuilder.setMeterBandHeaders(meterRemoveDataObject.getMeterBandHeaders());
+                meterBuilder.setMeterId(meterRemoveDataObject.getMeterId());
+                meterBuilder.setNode(meterRemoveDataObject.getNode());
+               // originalSwMeterView.put(meterKey, meterAddDataObject);
+                meterService.removeMeter(meterBuilder.build());
             }
 
-            originalSwMeterView.put(meterKey, meterUpdateDataObject);
+           // originalSwMeterView.put(meterKey, meterAddDataObject);
         } else {
             return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
         }
@@ -299,7 +311,6 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
         String containerName;
         String meterName;
         Status returnStatus = null;
-        boolean returnResult;
 
         if (null != meter) {
             containerName = meter.getContainerName();
@@ -319,7 +330,7 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
                 return returnStatus;
             }
 
-            returnResult = doesMeterEntryExists(meter.getKey(), meterName, containerName);
+         /*   returnResult = doesMeterEntryExists(meter.getKey(), meterName, containerName);
 
             if (FRMUtil.operation.ADD == operation && returnResult) {
                 logger.error("Record with same Meter Name exists");
@@ -329,7 +340,7 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
                 logger.error("Group record does not exist");
                 returnStatus = new Status(StatusCode.BADREQUEST, "Meter record does not exist");
                 return returnStatus;
-            }
+            }*/
 
             for (int i = 0; i < meter.getMeterBandHeaders().getMeterBandHeader().size(); i++) {
                 if (!meter.getFlags().isMeterBurst()) {
@@ -367,7 +378,7 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
         return new Status(StatusCode.SUCCESS);
     }
 
-    private boolean doesMeterEntryExists(MeterKey key, String meterName, String containerName) {
+    /*private boolean doesMeterEntryExists(MeterKey key, String meterName, String containerName) {
         if (!originalSwMeterView.containsKey(key)) {
             return false;
         }
@@ -380,34 +391,9 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
             }
         }
         return false;
-    }
-
-    private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
-        for (Entry<InstanceIdentifier<?>, Meter> entry : transaction.additions.entrySet()) {
-
-            if (!addMeter(entry.getKey(), entry.getValue()).isSuccess()) {
-                return Rpcs.getRpcResult(false, null, null);
-            }
-        }
-        for (@SuppressWarnings("unused")
-        Entry<InstanceIdentifier<?>, Meter> entry : transaction.updates.entrySet()) {
-
-            if (!updateMeter(entry.getKey(), entry.getValue()).isSuccess()) {
-                return Rpcs.getRpcResult(false, null, null);
-            }
-        }
-
-        for (InstanceIdentifier<?> removal : transaction.removals) {
-            /*
-             * if (!removeMeter(entry.getKey(),entry.getValue()).isSuccess()) {
-             * return Rpcs.getRpcResult(false, null, null); }
-             */
-        }
-
-        return Rpcs.getRpcResult(true, null, null);
-    }
+    }*/
 
-    private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+    private final class InternalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
 
         private final DataModification<InstanceIdentifier<?>, DataObject> modification;
 
@@ -416,7 +402,7 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
             return modification;
         }
 
-        public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+        public InternalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
             this.modification = modification;
         }
 
@@ -430,33 +416,30 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
          *
          */
         void prepareUpdate() {
-
-            Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
-            for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+            
+            Set<Entry<InstanceIdentifier<?>, DataObject>> addMeter = modification.getCreatedConfigurationData().entrySet();
+            for (Entry<InstanceIdentifier<?>, DataObject> entry : addMeter) {
                 if (entry.getValue() instanceof Meter) {
-                    Meter Meter = (Meter) entry.getValue();
-                    preparePutEntry(entry.getKey(), Meter);
+                    Meter meter = (Meter) entry.getValue();
+                    additions.put(entry.getKey(), meter);                    
                 }
 
             }
+            
+            Set<Entry<InstanceIdentifier<?>, DataObject>> updateMeter = modification.getUpdatedConfigurationData().entrySet();
+            for (Entry<InstanceIdentifier<?>, DataObject> entry : updateMeter) {
+                if (entry.getValue() instanceof Meter) {
+                    Meter meter = (Meter) entry.getValue();
+                  ///will be fixed once getUpdatedConfigurationData returns only updated data not created data with it.
+                    if (!additions.containsKey(entry.getKey())) {
+                       updates.put(entry.getKey(), meter);       
+                    }
+                }
+            }
 
             removals = modification.getRemovedConfigurationData();
         }
 
-        private void preparePutEntry(InstanceIdentifier<?> key, Meter meter) {
-
-            Meter original = originalSwMeterView.get(key);
-            if (original != null) {
-                // It is update for us
-
-                updates.put(key, meter);
-            } else {
-                // It is addition for us
-
-                additions.put(key, meter);
-            }
-        }
-
         /**
          * We are OK to go with execution of plan
          *
@@ -480,10 +463,37 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
             // NOOP - we did not modified any internal state during
             // requestCommit phase
             // return Rpcs.getRpcResult(true, null, Collections.emptySet());
-            return Rpcs.getRpcResult(true, null, null);
+            return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
+
+        }
+
+    }
+    
+    private RpcResult<Void> commitToPlugin(InternalTransaction transaction) {
+        for (Entry<InstanceIdentifier<?>, Meter> entry : transaction.additions.entrySet()) {
+
+            if (!addMeter(entry.getKey(), entry.getValue()).isSuccess()) {
+                return Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
+            }
+        }
+        for (Entry<InstanceIdentifier<?>, Meter> entry : transaction.updates.entrySet()) {
+
+            if (!updateMeter(entry.getKey(), entry.getValue()).isSuccess()) {
+                return Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
+            }
+        }
 
+        for (InstanceIdentifier<?> meterId : transaction.removals) {
+            DataObject removeValue = transaction.getModification().getOriginalConfigurationData().get(meterId);        
+                
+                if(removeValue instanceof Meter) {
+                    if(!removeMeter(meterId, (Meter)removeValue).isSuccess()) {
+                        return Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
+                        }
+                }    
         }
 
+        return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
     }
 
     private final class MeterDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
@@ -492,7 +502,7 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
                 DataModification<InstanceIdentifier<?>, DataObject> modification) {
             // We should verify transaction
             System.out.println("Coming in MeterDataCommitHandler");
-            internalTransaction transaction = new internalTransaction(modification);
+            InternalTransaction transaction = new InternalTransaction(modification);
             transaction.prepareUpdate();
             return transaction;
         }
index 67c6933cc7b3158d5435b2929cfae9bfaa99dad5..29ea8ddf1889bc8d3cfec6e37d070896fc0bd3ae 100644 (file)
@@ -4,7 +4,7 @@ module opendaylight-flow-types {
 
     import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
     import ietf-yang-types {prefix yang; revision-date "2010-09-24";}    
-    import opendaylight-match-types {prefix match; revision-date 2013-10-26";}
+    import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
     import opendaylight-action-types {prefix action;}
 
     revision "2013-10-26" {
diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/queue-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/queue-types.yang
new file mode 100644 (file)
index 0000000..57a9237
--- /dev/null
@@ -0,0 +1,77 @@
+module opendaylight-queue-types {
+    namespace "urn:opendaylight:flow:types:queue";
+    prefix queue-types;
+
+    import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
+    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+    
+    revision "2013-09-25" {
+        description "Initial revision of Queue Inventory model";
+    }
+    
+    typedef queue-properties {
+        type enumeration {
+            enum min_rate;
+            enum max_rate;
+        }
+    }
+   
+    
+    grouping common-queue {
+
+        leaf property {
+            type uint16;
+            description "One of OFPQT_.";  
+        }
+           
+    }
+    
+     
+    grouping queue-prop-min-rate       {
+               
+               uses common-queue;
+               
+        leaf rate {
+            type uint16;
+            description "OFPQT_MIN, len: 16";  
+        }
+           
+    }
+    
+    
+      
+    grouping queue-prop-max-rate       {
+               
+               uses common-queue;
+               
+        leaf rate {
+            type uint16;
+            description "OFPQT_MAX, len: 16";  
+        }
+           
+    }
+     grouping queue-packet     {
+               
+               
+        leaf queue-id {
+            type uint32;
+            description "id for the specific queue.";  
+        }
+        
+        leaf port {
+            type uint32;
+            description "Port this queue is attached to.";  
+        }
+        uses common-queue;
+    }
+    
+   grouping queue-config-request 
+   {
+           leaf port {
+            type uint32;
+            description "Port to be queried.";  
+        }
+        
+        }
+ }
+}
\ No newline at end of file
index 52629516f3f61314b76d017117b8fcf47fe5b4d5..3774f950fc63aa139b35749cfaf9e2c4ffad0af4 100644 (file)
@@ -4,7 +4,7 @@ module opendaylight-table-types {
 
     import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
     import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
-    import opendaylight-flow-types {prefix flow;revision-date 2013-10-26";}
+    import opendaylight-flow-types {prefix flow;revision-date "2013-10-26";}
     import opendaylight-action-types {prefix action;}
 
     revision "2013-10-26" {
@@ -325,4 +325,4 @@ module opendaylight-table-types {
 
         }
     }    
-}
\ No newline at end of file
+}
diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/queue-config.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/queue-config.yang
new file mode 100644 (file)
index 0000000..b362e3f
--- /dev/null
@@ -0,0 +1,34 @@
+module queue-management {
+    namespace "urn:opendaylight:queue:config";
+    prefix queue-cfg;
+
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}      
+     
+    import opendaylight-queue-types {prefix queue; revision-date "2013-09-25";}
+
+   
+    revision "2013-10-24" {
+        description "Initial revision of queue service";
+    }
+
+    grouping queue-entry {
+        leaf node {
+            type inv:node-connector-ref;
+           
+        }
+        uses queue:queue-config-request;
+    }   
+     
+    container queues {
+        list queue {
+            key "id node"; 
+                        
+            leaf id {
+                type uint32;
+            }                       
+            
+            uses queue-entry;
+        }
+    }    
+}
\ No newline at end of file
index bb010353280b8fa281c0901dde2e8d771f62ac13..b21423b7d4d94d6db1a850a3cbac99bf5547a2d3 100644 (file)
@@ -41,7 +41,7 @@ module sal-group {
 
     rpc remove-group {
         input {
-            uses group-update;
+            uses node-group;
             uses tr:transaction-aware;            
         }
         output {
index 9588652a1c6cdb8fb63901f8cb4ccf72228c7b9c..d49675ad39366bb3e8c9b3a5a191f2a677683ce7 100644 (file)
@@ -5,6 +5,7 @@ module sal-port {
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-11-07" {
         description "Initial revision of port service";
@@ -31,6 +32,10 @@ module sal-port {
     rpc update-port {
         input {
             uses port-update;
+            uses tr:transaction-aware;
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
      
diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/queue-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/queue-service.yang
new file mode 100644 (file)
index 0000000..bf79cbf
--- /dev/null
@@ -0,0 +1,29 @@
+module sal-queue {
+    namespace "urn:opendaylight:queue:service";
+    prefix queue;
+
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+    import opendaylight-queue-types {prefix queue-type; revision-date "2013-09-25";}
+
+    revision "2013-11-07" {
+        description "Initial revision of queue service";
+    }        
+    
+    grouping node-queue {
+        uses "inv:node-context-ref";
+        
+        uses queue-type:queue-packet;
+    }
+
+     
+    rpc get-queue {
+        output {
+            uses queue-type:queue-packet;
+        }
+    }  
+    
+    notification queue-get-config-reply {
+        uses node-queue;
+    }
+}
\ No newline at end of file
index eccb691fa72b3b3f1390d71a97b757b78cfc0fd6..34ad23844f363da800bc33a12b9dfee7eae045cb 100644 (file)
                                         target/generated-sources/sal
                                     </outputBaseDir>
                                 </generator>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
+                                    <outputBaseDir>target/site/restconf</outputBaseDir>
+                                </generator>
                             </codeGenerators>
                             <inspectDependencies>true</inspectDependencies>
                         </configuration>
index bdbcce0950fa449dbc43a7be562fa22bbb7f3ade..94c31dd0411eb041fc11fd61adcab23dd369a105 100644 (file)
@@ -40,7 +40,8 @@
         <!-- Connectors -->
         <module>sal-connector-api</module>
         <module>sal-rest-connector</module>
-
+        <module>sal-netconf-connector</module>
+        
         <!-- Clustered Data Store -->
         <module>clustered-data-store/implementation</module>
 
index 0ddc2c88c8bd5bc99c85260bb13f7ce1c86f592b..ec69fd3b68c8ee84c39edde4e58207adb771b5bd 100644 (file)
@@ -33,6 +33,8 @@ import org.opendaylight.yangtools.binding.generator.util.Types
 import org.osgi.framework.BundleContext
 import java.util.Hashtable
 import org.osgi.framework.ServiceRegistration
+import org.opendaylight.controller.sal.binding.impl.connect.dom.DeserializationException
+import java.util.concurrent.Callable
 
 class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, AutoCloseable {
 
@@ -59,7 +61,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
     val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
 
     val promisedSchemas = HashMultimap.<Type, SettableFuture<SchemaNode>>create;
-    
+
     ServiceRegistration<SchemaServiceListener> listenerRegistration
 
     override onGlobalContextUpdated(SchemaContext arg0) {
@@ -79,7 +81,6 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
             val context = entry.value;
             updateBindingFor(context.childNodes, schemaContext);
             updateBindingFor(context.cases, schemaContext);
-            
 
             val typedefs = context.typedefs;
             for (typedef : typedefs.values) {
@@ -89,7 +90,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
             for (augmentation : augmentations) {
                 binding.typeToDefinition.put(augmentation, augmentation);
             }
-            
+
             binding.typeToAugmentation.putAll(context.typeToAugmentation);
         }
     }
@@ -127,22 +128,36 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
     }
 
     override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
-        if (node == null) {
-            return null;
-        }
-        val targetType = path.targetType
-        val transformer = registry.getCodecForDataObject(targetType);
-        val ret = transformer.deserialize(node)?.value as DataObject;
-        return ret;
+        return tryDeserialization[ |
+            if (node == null) {
+                return null;
+            }
+            val targetType = path.targetType
+            val transformer = registry.getCodecForDataObject(targetType);
+            val ret = transformer.deserialize(node)?.value as DataObject;
+            return ret;
+        ]
     }
-    
+
     override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) {
-        return registry.instanceIdentifierCodec.deserialize(entry);
+        return tryDeserialization[ |
+            registry.instanceIdentifierCodec.deserialize(entry);
+        ]
+    }
+
+    private static def <T> T tryDeserialization(Callable<T> deserializationBlock) throws DeserializationException {
+        try {
+            deserializationBlock.call()
+        } catch (Exception e) {
+            // FIXME: Make this block providing more information.
+            throw new DeserializationException(e);
+        }
     }
 
     private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
         for (entry : map.entrySet) {
             val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+
             //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
             if (schemaNode != null) {
                 typeToSchemaNode.put(entry.value, schemaNode);
@@ -162,8 +177,8 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         binding.typeToDefinition = typeToDefinition
         binding.typeToSchemaNode = typeToSchemaNode
         binding.typeDefinitions = typeDefinitions
-        if(ctx !== null) {
-            listenerRegistration = ctx.registerService(SchemaServiceListener,this,new Hashtable<String,String>());
+        if (ctx !== null) {
+            listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable<String, String>());
         }
     }
 
@@ -217,9 +232,9 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         }
         promisedSchemas.removeAll(builder);
     }
-    
+
     override close() throws Exception {
         listenerRegistration?.unregister();
     }
-    
+
 }
index ccd6079cc997b00b9de8a2a6f5ee935155f01340..7a72afc88550b3871ea72286f5b791b4a90f568c 100644 (file)
@@ -32,7 +32,7 @@ import org.slf4j.LoggerFactory;
 
 public class BindingIndependentDataServiceConnector implements //
         RuntimeDataProvider, //
-        Provider {
+        Provider, AutoCloseable {
 
     private final Logger LOG = LoggerFactory.getLogger(BindingIndependentDataServiceConnector.class);
 
@@ -59,16 +59,24 @@ public class BindingIndependentDataServiceConnector implements //
 
     @Override
     public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
-        CompositeNode result = biDataService.readOperationalData(biPath);
-        return mappingService.dataObjectFromDataDom(path, result);
+        try {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+            CompositeNode result = biDataService.readOperationalData(biPath);
+            return mappingService.dataObjectFromDataDom(path, result);
+        } catch (DeserializationException e) {
+            throw new IllegalStateException(e);
+        }
     }
 
     @Override
     public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
-        CompositeNode result = biDataService.readConfigurationData(biPath);
-        return mappingService.dataObjectFromDataDom(path, result);
+        try {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+            CompositeNode result = biDataService.readConfigurationData(biPath);
+            return mappingService.dataObjectFromDataDom(path, result);
+        } catch (DeserializationException e) {
+            throw new IllegalStateException(e);
+        }
     }
 
     private DataModificationTransaction createBindingToDomTransaction(
@@ -103,23 +111,42 @@ public class BindingIndependentDataServiceConnector implements //
                 .beginTransaction();
         for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
                 .getUpdatedConfigurationData().entrySet()) {
-            InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
-            DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
-            target.putConfigurationData(baKey, baData);
+            try {
+                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+                target.putConfigurationData(baKey, baData);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry.getKey(), e);
+            }
         }
         for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
                 .getUpdatedOperationalData().entrySet()) {
-            InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
-            DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
-            target.putOperationalData(baKey, baData);
+            try {
+
+                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+                target.putOperationalData(baKey, baData);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry.getKey(), e);
+            }
         }
         for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
-            InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
-            target.removeConfigurationData(baEntry);
+            try {
+
+                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+                target.removeConfigurationData(baEntry);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry, e);
+            }
         }
         for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
-            InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
-            target.removeOperationalData(baEntry);
+            try {
+
+                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+                target.removeOperationalData(baEntry);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry, e);
+            }
         }
         return target;
     }
@@ -162,6 +189,18 @@ public class BindingIndependentDataServiceConnector implements //
         start();
     }
 
+    @Override
+    public void close() throws Exception {
+
+        if (baCommitHandlerRegistration != null) {
+            baCommitHandlerRegistration.close();
+        }
+        if (biCommitHandlerRegistration != null) {
+            biCommitHandlerRegistration.close();
+        }
+
+    }
+
     private class DomToBindingTransaction implements
             DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
 
@@ -271,10 +310,11 @@ public class BindingIndependentDataServiceConnector implements //
 
         @Override
         public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
-            
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration.getPath());
+
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
+                    .getPath());
             // FIXME: do registration based on only active commit handlers.
-            
+
         }
 
         @Override
index 9e175b8cb0e0f6c5e79550218986e0f552ae3edd..b1983fe224d89da96f4445efa86469cc0e0e6b9d 100644 (file)
@@ -16,8 +16,8 @@ public interface BindingIndependentMappingService {
 
     org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
 
-    DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
+    DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) throws DeserializationException;
 
-    InstanceIdentifier<?> fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry);
+    InstanceIdentifier<?> fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry)  throws DeserializationException;
 
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DeserializationException.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DeserializationException.java
new file mode 100644 (file)
index 0000000..9331899
--- /dev/null
@@ -0,0 +1,24 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class DeserializationException extends Exception {
+
+    public DeserializationException() {
+    }
+
+    public DeserializationException(String message) {
+        super(message);
+    }
+
+    public DeserializationException(Throwable cause) {
+        super(cause);
+    }
+
+    public DeserializationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public DeserializationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+
+}
index 5b35861e9dd189bbabc2d385a82d0fd6ea5b24fa..9f3a6e8652f8c3d47dc65c2aafce56061d26aace 100644 (file)
@@ -8,6 +8,7 @@ import java.util.Set;
 
 import javassist.ClassPool;
 
+import org.junit.After;
 import org.junit.Before;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
@@ -15,78 +16,96 @@ import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndepende
 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
 import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.reflections.Reflections;
 import org.reflections.scanners.ResourcesScanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Predicate;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 
-public  abstract class AbstractDataServiceTest {
+public abstract class AbstractDataServiceTest {
+    private static Logger log = LoggerFactory.getLogger(AbstractDataServiceTest.class);
+
     protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
     protected DataProviderService baDataService;
-    
+
     /**
      * Workaround for JUNIT sharing classloaders
      * 
      */
     protected static final ClassPool POOL = new ClassPool();
-    
+
     protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
     protected BindingIndependentMappingService mappingService;
     protected DataBrokerImpl baDataImpl;
     protected org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
     protected ListeningExecutorService executor;
     protected BindingIndependentDataServiceConnector connectorServiceImpl;
-    protected HashMapDataStore dataStore;
-    
-    
+    protected HashMapDataStore rawDataStore;
+    private SchemaAwareDataStoreAdapter schemaAwareDataStore;
+    private DataStoreStatsWrapper dataStoreStats;
+
+    protected DataStore dataStore;
+
     @Before
     public void setUp() {
         executor = MoreExecutors.sameThreadExecutor();
         baDataImpl = new DataBrokerImpl();
         baDataService = baDataImpl;
         baDataImpl.setExecutor(executor);
-        
+
         biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
-        biDataService =  biDataImpl;
+        biDataService = biDataImpl;
         biDataImpl.setExecutor(executor);
-        
-        dataStore = new HashMapDataStore();
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance();
+
+        rawDataStore = new HashMapDataStore();
+        schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
+        schemaAwareDataStore.changeDelegate(rawDataStore);
+        dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
+        dataStore = dataStoreStats;
+
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+                .builder().toInstance();
         biDataImpl.registerConfigurationReader(treeRoot, dataStore);
         biDataImpl.registerOperationalReader(treeRoot, dataStore);
         biDataImpl.registerCommitHandler(treeRoot, dataStore);
-        
+
         mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
         mappingServiceImpl.setPool(POOL);
         mappingService = mappingServiceImpl;
         File pathname = new File("target/gen-classes-debug");
-        //System.out.println("Generated classes are captured in " + pathname.getAbsolutePath());
+        // System.out.println("Generated classes are captured in " +
+        // pathname.getAbsolutePath());
         mappingServiceImpl.start(null);
-        //mappingServiceImpl.getBinding().setClassFileCapturePath(pathname);
-        
+        // mappingServiceImpl.getBinding().setClassFileCapturePath(pathname);
+
         connectorServiceImpl = new BindingIndependentDataServiceConnector();
         connectorServiceImpl.setBaDataService(baDataService);
         connectorServiceImpl.setBiDataService(biDataService);
         connectorServiceImpl.setMappingService(mappingServiceImpl);
         connectorServiceImpl.start();
-        
-        String[] yangFiles= getModelFilenames();
-        if(yangFiles != null && yangFiles.length > 0) {
-            mappingServiceImpl.onGlobalContextUpdated(getContext(yangFiles));
+
+        String[] yangFiles = getModelFilenames();
+        if (yangFiles != null && yangFiles.length > 0) {
+            SchemaContext context = getContext(yangFiles);
+            mappingServiceImpl.onGlobalContextUpdated(context);
+            schemaAwareDataStore.onGlobalContextUpdated(context);
         }
     }
 
-
-    protected  String[] getModelFilenames() {
+    protected String[] getModelFilenames() {
         return getAllModelFilenames();
     }
-    
+
     public static String[] getAllModelFilenames() {
         Predicate<String> predicate = new Predicate<String>() {
             @Override
@@ -94,11 +113,11 @@ public  abstract class AbstractDataServiceTest {
                 return input.endsWith(".yang");
             }
         };
-        Reflections reflection= new Reflections("META-INF.yang", new ResourcesScanner());
+        Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
         Set<String> result = reflection.getResources(predicate);
         return (String[]) result.toArray(new String[result.size()]);
     }
-    
+
     public static SchemaContext getContext(String[] yangFiles) {
 
         ClassLoader loader = AbstractDataServiceTest.class.getClassLoader();
@@ -114,4 +133,21 @@ public  abstract class AbstractDataServiceTest {
         Set<Module> modules = parser.parseYangModelsFromStreams(streams);
         return parser.resolveSchemaContext(modules);
     }
+
+    @After
+    public void afterTest() {
+
+        log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns",
+                dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
+                dataStoreStats.getConfigurationReadAverageTime());
+
+        log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns",
+                dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
+                dataStoreStats.getOperationalReadAverageTime());
+
+        log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ns AverageTime (ns): {} ns",
+                dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
+                dataStoreStats.getRequestCommitAverageTime());
+
+    }
 }
index 144a81b2566f549c56e7cbb00bb0e9567db644f2..d62e176e62d1beeb22c934f7c82aa3a713909b91 100644 (file)
@@ -11,15 +11,31 @@ import org.opendaylight.yangtools.concepts.Immutable;
 
 public interface DataChangeEvent<P,D> extends DataChange<P, D>, Immutable {
 
+    /**
+     * Returns a orignal subtree of data, which starts at the path
+     * where listener was registered.
+     * 
+     */
+    D getOriginalConfigurationSubtree();
+
     /**
      * Returns a new subtree of data, which starts at the path
      * where listener was registered.
      * 
      */
+    D getOriginalOperationalSubtree();
+    
+    
+    
+    /**
+     * Returns a updated subtree of data, which starts at the path
+     * where listener was registered.
+     * 
+     */
     D getUpdatedConfigurationSubtree();
 
     /**
-     * Returns a new subtree of data, which starts at the path
+     * Returns a udpated subtree of data, which starts at the path
      * where listener was registered.
      * 
      */
index e3d2b567a71f42b202bf028db6f0d8dcd5f70ae2..a18e5a9c824a675af339d93e02d770e4ccbaf285 100644 (file)
@@ -38,6 +38,7 @@ import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegis
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener
 import org.opendaylight.yangtools.concepts.util.ListenerRegistry
 import java.util.concurrent.atomic.AtomicLong
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
 
 abstract class AbstractDataBroker<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements DataModificationTransactionFactory<P, D>, //
 DataReader<P, D>, //
@@ -91,6 +92,10 @@ DataProvisionService<P, D> {
     override final def registerDataChangeListener(P path, DCL listener) {
         val reg = new DataChangeListenerRegistration(path, listener, this);
         listeners.put(path, reg);
+        val initialConfig = dataReadRouter.readConfigurationData(path);
+        val initialOperational = dataReadRouter.readOperationalData(path);
+        val event = createInitialListenerEvent(path,initialConfig,initialOperational);
+        listener.onDataChanged(event);
         return reg;
     }
 
@@ -108,6 +113,10 @@ DataProvisionService<P, D> {
         return ret;
     }
     
+    protected  def DataChangeEvent<P,D> createInitialListenerEvent(P path,D initialConfig,D initialOperational) {
+        return new InitialDataChangeEventImpl<P, D>(initialConfig,initialOperational);
+        
+    }
 
     protected final def removeListener(DataChangeListenerRegistration<P, D, DCL> registration) {
         listeners.remove(registration.path, registration);
index 4eb9586fdf94a8b1a1ffa8388f7a699d3fbd60b1..68f9506c56425e29ad91e6b2c42a1fd9059542f1 100644 (file)
@@ -11,6 +11,8 @@ public class DataChangeEventImpl<P, D> implements DataChangeEvent<P, D> {
     private final DataChange<P, D> dataChange;
 
     private final D originalConfigurationSubtree;
+
+
     private final D originalOperationalSubtree;
     private final D updatedOperationalSubtree;
     private final D updatedConfigurationSubtree;
@@ -28,6 +30,16 @@ public class DataChangeEventImpl<P, D> implements DataChangeEvent<P, D> {
         this.updatedConfigurationSubtree = updatedConfigurationSubtree;
     }
 
+    @Override
+    public D getOriginalConfigurationSubtree() {
+        return originalConfigurationSubtree;
+    }
+
+    @Override
+    public D getOriginalOperationalSubtree() {
+        return originalOperationalSubtree;
+    }
+
     @Override
     public D getUpdatedOperationalSubtree() {
         return updatedOperationalSubtree;
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java
new file mode 100644 (file)
index 0000000..2764635
--- /dev/null
@@ -0,0 +1,75 @@
+package org.opendaylight.controller.md.sal.common.impl.service;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+
+public class InitialDataChangeEventImpl<P,D> implements DataChangeEvent<P, D> {
+
+    private final D originalOperationalTree;
+    private final D originalConfigurationTree;
+
+    public InitialDataChangeEventImpl(D configTree, D operTree) {
+        originalConfigurationTree = configTree;
+        originalOperationalTree = operTree;
+    }
+    
+    @Override
+    public Map<P, D> getCreatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+    
+    @Override
+    public Map<P, D> getCreatedOperationalData() {
+        return Collections.emptyMap();
+    }
+    
+    @Override
+    public Map<P, D> getOriginalConfigurationData() {
+        return Collections.emptyMap();
+    }
+    @Override
+    public Map<P, D> getOriginalOperationalData() {
+        return Collections.emptyMap();
+    }
+    @Override
+    public Set<P> getRemovedConfigurationData() {
+        return Collections.emptySet();
+    }
+    @Override
+    public Set<P> getRemovedOperationalData() {
+        return Collections.emptySet();
+    }
+    @Override
+    public Map<P, D> getUpdatedConfigurationData() {
+        return Collections.emptyMap();
+    }
+    
+    @Override
+    public D getUpdatedConfigurationSubtree() {
+        return originalConfigurationTree;
+    }
+    @Override
+    public D getUpdatedOperationalSubtree() {
+        return originalOperationalTree;
+    }
+    
+    @Override
+    public D getOriginalConfigurationSubtree() {
+        return originalConfigurationTree;
+    }
+    
+    @Override
+    public D getOriginalOperationalSubtree() {
+        return originalOperationalTree;
+    }
+    
+    @Override
+    public Map<P, D> getUpdatedOperationalData() {
+        return Collections.emptyMap();
+    }
+    
+
+}
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/AbstractLockableDelegator.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/AbstractLockableDelegator.java
new file mode 100644 (file)
index 0000000..61abe66
--- /dev/null
@@ -0,0 +1,76 @@
+package org.opendaylight.controller.md.sal.common.impl.util;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+import org.opendaylight.yangtools.concepts.Delegator;
+
+import com.google.common.base.Preconditions;
+
+public class AbstractLockableDelegator<T> implements Delegator<T> {
+
+    private final ReentrantReadWriteLock delegateLock = new ReentrantReadWriteLock();
+    private final ReadLock delegateReadLock = delegateLock.readLock();
+    private final WriteLock delegateWriteLock = delegateLock.writeLock();
+    
+    
+    protected Lock getDelegateReadLock() {
+        return delegateReadLock;
+    }
+
+    private T delegate;
+
+    public AbstractLockableDelegator() {
+        // NOOP
+    }
+
+    public AbstractLockableDelegator(T initialDelegate) {
+        delegate = initialDelegate;
+    }
+
+    @Override
+    public T getDelegate() {
+        try {
+            delegateReadLock.lock();
+            return delegate;
+        } finally {
+            delegateReadLock.unlock();
+        }
+    }
+
+    public T retrieveDelegate() {
+        try {
+            delegateReadLock.lock();
+            Preconditions.checkState(delegate != null,"Delegate is null");
+            return delegate;
+        } finally {
+            delegateReadLock.unlock();
+        }
+    }
+
+    /**
+     * 
+     * @param newDelegate
+     * @return oldDelegate
+     */
+    public final T changeDelegate(T newDelegate) {
+        try {
+            delegateWriteLock.lock();
+            T oldDelegate = delegate;
+            delegate = newDelegate;
+            onDelegateChanged(oldDelegate, newDelegate);
+            return oldDelegate;
+        } finally {
+            delegateWriteLock.unlock();
+        }
+    }
+    
+    
+    protected void onDelegateChanged(T oldDelegate, T newDelegate) {
+        // NOOP in abstract calss;
+    }
+}
index 1062f5e5352d82f8fa003431c92561a6633dc62f..87129d68631ba382f0096b604d9c6e6302e14fd7 100644 (file)
@@ -8,5 +8,12 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 public interface DataStore extends //
     DataReader<InstanceIdentifier, CompositeNode>,
     DataCommitHandler<InstanceIdentifier, CompositeNode> {
+    
+    
+    Iterable<InstanceIdentifier> getStoredConfigurationPaths();
+    Iterable<InstanceIdentifier> getStoredOperationalPaths();
+    
+    boolean containsConfigurationPath(InstanceIdentifier path);
+    boolean containsOperationalPath(InstanceIdentifier path);
 
 }
index 9a4fc6ddc1f303ba8521667a0604036d592bb74e..050966faa0496a81715388352c0ccefb38fe3567 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.controller.sal.core.api.data.DataStore;
 import org.opendaylight.controller.sal.dom.broker.BrokerConfigActivator;
 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
 import org.osgi.framework.BundleContext;
+import static com.google.common.base.Preconditions.*;
 
 /**
 *
@@ -33,8 +34,10 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi
     @Override
     public void validate(){
         super.validate();
-        // Add custom validation for module attributes here.
+        checkArgument(getDataStore() != null, "Data Store needs to be provided for DomBroker");
     }
+    
+    
 
     @Override
     public java.lang.AutoCloseable createInstance() {
index a6aa0ce32eea75a5aa0498bfe22a9bcf4b0c2169..54c94dca9f83601dfbbd666a49e48476091feb02 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Hashtable
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.controller.sal.core.api.data.DataStore
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter
 
 class BrokerConfigActivator implements AutoCloseable {
     
@@ -27,6 +28,8 @@ class BrokerConfigActivator implements AutoCloseable {
     private var SchemaServiceImpl schemaService;
     private var DataBrokerImpl dataService;
     private var MountPointManagerImpl mountService;
+    
+    SchemaAwareDataStoreAdapter wrappedStore
 
     public def void start(BrokerImpl broker,DataStore store,BundleContext context) {
         val emptyProperties = new Hashtable<String, String>();
@@ -45,9 +48,13 @@ class BrokerConfigActivator implements AutoCloseable {
         dataReg = context.registerService(DataBrokerService, dataService, emptyProperties);
         dataProviderReg = context.registerService(DataProviderService, dataService, emptyProperties);
 
-        dataService.registerConfigurationReader(ROOT, store);
-        dataService.registerCommitHandler(ROOT, store);
-        dataService.registerOperationalReader(ROOT, store);
+        wrappedStore = new SchemaAwareDataStoreAdapter();
+        wrappedStore.changeDelegate(store);
+        wrappedStore.setValidationEnabled(false);
+        
+        dataService.registerConfigurationReader(ROOT, wrappedStore);
+        dataService.registerCommitHandler(ROOT, wrappedStore);
+        dataService.registerOperationalReader(ROOT, wrappedStore);
         
         mountService = new MountPointManagerImpl();
         mountService.setDataBroker(dataService);
index 1197ef34bd926d2de186931184c70043c5404033..ac5313a9caa99fdaf4fdb5c29fd7690b08e3589c 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.sal.dom.broker;
 
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
index fbed2ca113621c728dd00a5fa4b9ae932344d7db..504a3d639413f7f6b1b901297bbf215aa9825842 100644 (file)
@@ -4,15 +4,100 @@ import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRo
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.yang.common.QName
+import java.net.URI
+import java.util.List
+import org.opendaylight.yangtools.yang.data.api.Node
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import java.util.Map
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.HashMap
+import static com.google.common.base.Preconditions.*;
+import java.util.Collection
+import java.util.Set
+import java.util.Map.Entry
+import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
 
 class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
+    private static val LOG = LoggerFactory.getLogger(DataReaderRouter);
+    private static val NETCONF_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
+    private static val NETCONF_DATA = new QName(NETCONF_NAMESPACE,"data");
 
     override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
+        val pathArgument = path.path.last;
+        var empty = true;
+        var name = pathArgument?.nodeType;
+        val nodes = new ArrayList<Node<?>>();
+        val keyNodes = new HashMap<QName, SimpleNode<?>>();
         val iterator = data.iterator;
-        if(iterator.hasNext) {
-            return data.iterator.next
+        for(dataBit : data) {
+            try {
+                if(pathArgument != null && dataBit != null) {
+                    empty = false;
+                    val keyNodesLocal = getKeyNodes(pathArgument,dataBit);
+                    nodes.addAll(dataBit.childrenWithout(keyNodesLocal.entrySet));
+                } else if (dataBit != null) {
+                    empty = false;
+                    nodes.addAll(dataBit.children)
+                }
+            }   catch (IllegalStateException e) {
+                LOG.error("BUG: Readed data for path {} was invalid",path,e);
+            }
         }
-        return null;
+        if(empty) {
+            return null;
+        }
+        /**
+         * Reading from Root
+         * 
+         */
+        if(pathArgument == null) {
+            return new CompositeNodeTOImpl(NETCONF_DATA,null,nodes);
+        }
+        val finalNodes = new ArrayList<Node<?>>();
+        finalNodes.addAll(keyNodes.values);
+        finalNodes.addAll(nodes);
+        return new CompositeNodeTOImpl(name,null,finalNodes);
     }
-
+    
+    
+    
+    dispatch def Map<QName, SimpleNode<?>> getKeyNodes(PathArgument argument, CompositeNode node) {
+        return Collections.emptyMap();
+    }
+    
+    dispatch def getKeyNodes(NodeIdentifierWithPredicates argument, CompositeNode node) {
+        val ret = new HashMap<QName, SimpleNode<?>>();
+        for (keyValue : argument.keyValues.entrySet) {
+            val simpleNode = node.getSimpleNodesByName(keyValue.key);
+            if(simpleNode !== null && !simpleNode.empty) {
+                checkState(simpleNode.size <= 1,"Only one simple node for key $s is allowed in node $s",keyValue.key,node);
+                checkState(simpleNode.get(0).value == keyValue.value,"Key node must equals to instance identifier value");
+                ret.put(keyValue.key,simpleNode.get(0));
+            }
+            val compositeNode = node.getCompositesByName(keyValue.key);
+            checkState(compositeNode === null || compositeNode.empty,"Key node must be Simple Node, not composite node.");
+        }
+        return ret;
+    }
+    
+    def Collection<? extends Node<?>> childrenWithout(CompositeNode node, Set<Entry<QName, SimpleNode<?>>> entries) {
+        if(entries.empty) {
+            return node.children;
+        }
+        val filteredNodes = new ArrayList<Node<?>>();
+        for(scannedNode : node.children) {
+            if(!entries.contains(scannedNode.nodeType)) {
+                filteredNodes.add(scannedNode);
+            }
+        }
+        return filteredNodes;
+    }
+    
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java
new file mode 100644 (file)
index 0000000..9116d50
--- /dev/null
@@ -0,0 +1,137 @@
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DataStoreStatsWrapper implements Delegator<DataStore>, DataStore {
+
+    private final DataStore delegate;
+
+    private AtomicLong cfgReadCount = new AtomicLong();
+    private AtomicLong cfgReadTimeTotal = new AtomicLong();
+
+    private AtomicLong operReadCount = new AtomicLong();
+    private AtomicLong operReadTimeTotal = new AtomicLong();
+
+    private AtomicLong requestCommitCount = new AtomicLong();
+    private AtomicLong requestCommitTimeTotal = new AtomicLong();
+
+    public DataStoreStatsWrapper(DataStore store) {
+        delegate = store;
+    }
+
+    @Override
+    public DataStore getDelegate() {
+        return delegate;
+    }
+
+    @Override
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        cfgReadCount.incrementAndGet();
+        final long startTime = System.nanoTime();
+        try {
+            return delegate.readConfigurationData(path);
+        } finally {
+            final long endTime = System.nanoTime();
+            final long runTime = endTime - startTime;
+            cfgReadTimeTotal.addAndGet(runTime);
+        }
+    }
+
+    @Override
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        operReadCount.incrementAndGet();
+        final long startTime = System.nanoTime();
+        try {
+            return delegate.readOperationalData(path);
+        } finally {
+            final long endTime = System.nanoTime();
+            final long runTime = endTime - startTime;
+            cfgReadTimeTotal.addAndGet(runTime);
+        }
+    }
+
+    public DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
+            DataModification<InstanceIdentifier, CompositeNode> modification) {
+        requestCommitCount.incrementAndGet();
+        final long startTime = System.nanoTime();
+        try {
+            return delegate.requestCommit(modification);
+        } finally {
+            final long endTime = System.nanoTime();
+            final long runTime = endTime - startTime;
+            requestCommitTimeTotal.addAndGet(runTime);
+        }
+    };
+
+    @Override
+    public boolean containsConfigurationPath(InstanceIdentifier path) {
+        return delegate.containsConfigurationPath(path);
+    }
+
+    public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
+        return delegate.getStoredConfigurationPaths();
+    }
+
+    public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
+        return delegate.getStoredOperationalPaths();
+    }
+
+    public boolean containsOperationalPath(InstanceIdentifier path) {
+        return delegate.containsOperationalPath(path);
+    }
+
+    public final long getConfigurationReadCount() {
+        return cfgReadCount.get();
+    }
+
+    public final long getOperationalReadCount() {
+        return operReadCount.get();
+    }
+
+    public final long getRequestCommitCount() {
+        return requestCommitCount.get();
+    }
+
+    public final long getConfigurationReadTotalTime() {
+        return cfgReadTimeTotal.get();
+    }
+
+    public final long getOperationalReadTotalTime() {
+        return operReadTimeTotal.get();
+    }
+
+    public final long getRequestCommitTotalTime() {
+        return requestCommitTimeTotal.get();
+    }
+
+    public final long getConfigurationReadAverageTime() {
+        long readCount = cfgReadCount.get();
+        if(readCount == 0) {
+            return 0;
+        }
+        return cfgReadTimeTotal.get() / readCount;
+    }
+
+    public final long getOperationalReadAverageTime() {
+        long readCount = operReadCount.get();
+        if(readCount == 0) {
+            return 0;
+        }
+        return operReadTimeTotal.get() / readCount;
+    }
+
+    public final long getRequestCommitAverageTime() {
+        long count = requestCommitCount.get();
+        if(count == 0) {
+            return 0;
+        }
+        return requestCommitTimeTotal.get() / count;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend
deleted file mode 100644 (file)
index 1a2f947..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.opendaylight.controller.sal.dom.broker.impl
-
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import java.util.Map
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import java.util.Map.Entry
-import java.util.HashSet
-import java.util.ArrayList
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-
-class DataUtils {
-
-    static def CompositeNode read(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
-        val root = map.get(path);
-        val childs = map.getChilds(path);
-        if(root === null && childs.empty) {
-            return null;
-        }
-        
-        return merge(path, root, childs);
-    }
-
-    static def CompositeNode merge(InstanceIdentifier path, CompositeNode node,
-        HashSet<Entry<InstanceIdentifier, CompositeNode>> entries) {
-        val it = new ArrayList<Node<?>>();
-        val qname = path.path.last.nodeType;
-        if (node != null) {
-            addAll(node.children);
-        }
-        for (entry : entries) {
-            val nesting = entry.key.path.size - path.path.size;
-            if (nesting === 1) {
-                add(entry.value);
-            }
-        }
-        return new CompositeNodeTOImpl(qname, null, it);
-    }
-
-    static def getChilds(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
-        val it = new HashSet<Entry<InstanceIdentifier, CompositeNode>>();
-        for (entry : map.entrySet) {
-            if (path.contains(entry.key)) {
-                add(entry);
-            }
-        }
-        return it;
-    }
-
-}
index e7445e6965582c90a9401279d37aab18f704f17e..e9ed71a05287982faad6438962b3324c66c5cb6c 100644 (file)
@@ -9,23 +9,41 @@ import org.opendaylight.controller.sal.common.util.Rpcs
 import java.util.Collections
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import static extension org.opendaylight.controller.sal.dom.broker.impl.DataUtils.*;
 import org.opendaylight.controller.sal.core.api.data.DataStore
 import java.util.HashSet
 
 class HashMapDataStore implements DataStore, AutoCloseable {
 
+
     val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
     val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
+    
+    
+    
+    override containsConfigurationPath(InstanceIdentifier path) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        
+    }
+    
+    override containsOperationalPath(InstanceIdentifier path) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+    
+    override getStoredConfigurationPaths() {
+        configuration.keySet
+    }
+    
+    override getStoredOperationalPaths() {
+        operational.keySet
+    }
 
     override readConfigurationData(InstanceIdentifier path) {
-        configuration.read(path);
+        configuration.get(path);
     }
 
     override readOperationalData(InstanceIdentifier path) {
-        operational.read(path);
+        operational.get(path);
     }
-    
 
 
 
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend
new file mode 100644 (file)
index 0000000..8cdbf92
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.sal.dom.broker.impl
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+
+class SchemaAwareDataMerger {
+
+    private SchemaContext schema;
+    
+    
+    
+    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java
new file mode 100644 (file)
index 0000000..1f90814
--- /dev/null
@@ -0,0 +1,245 @@
+package org.opendaylight.controller.sal.dom.broker.impl;
+
+import java.awt.PageAttributes.OriginType;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.util.AbstractLockableDelegator;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+
+import static com.google.common.base.Preconditions.*;
+
+public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
+        DataStore, //
+        SchemaServiceListener, //
+        AutoCloseable {
+
+    private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class);
+
+    private SchemaContext schema = null;
+    private boolean validationEnabled = false;
+    private SchemaAwareDataMerger dataMerger = null;
+    private DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
+
+    @Override
+    public boolean containsConfigurationPath(InstanceIdentifier path) {
+        try {
+            getDelegateReadLock().lock();
+            return getDelegate().containsConfigurationPath(path);
+
+        } finally {
+            getDelegateReadLock().unlock();
+        }
+    }
+
+    @Override
+    public boolean containsOperationalPath(InstanceIdentifier path) {
+        try {
+            getDelegateReadLock().lock();
+            return getDelegate().containsOperationalPath(path);
+
+        } finally {
+            getDelegateReadLock().unlock();
+        }
+    }
+
+    @Override
+    public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
+        try {
+            getDelegateReadLock().lock();
+            return getDelegate().getStoredConfigurationPaths();
+
+        } finally {
+            getDelegateReadLock().unlock();
+        }
+    }
+
+    @Override
+    public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
+        try {
+            getDelegateReadLock().lock();
+            return getDelegate().getStoredOperationalPaths();
+
+        } finally {
+            getDelegateReadLock().unlock();
+        }
+    }
+
+    @Override
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return reader.readConfigurationData(path);
+    }
+
+    @Override
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return reader.readOperationalData(path);
+    }
+
+    @Override
+    public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
+            DataModification<InstanceIdentifier, CompositeNode> modification) {
+        validateAgainstSchema(modification);
+        DataModification<InstanceIdentifier, CompositeNode> cleanedUp = prepareMergedTransaction(modification);
+        return retrieveDelegate().requestCommit(cleanedUp);
+    }
+
+    public boolean isValidationEnabled() {
+        return validationEnabled;
+    }
+
+    public void setValidationEnabled(boolean validationEnabled) {
+        this.validationEnabled = validationEnabled;
+    }
+
+    private void validateAgainstSchema(DataModification<InstanceIdentifier, CompositeNode> modification) {
+        if (!validationEnabled) {
+            return;
+        }
+
+        if (schema == null) {
+            LOG.info("Validation not performed for {}. Reason: YANG Schema not present.", modification.getIdentifier());
+            return;
+        }
+    }
+
+    @Override
+    protected void onDelegateChanged(DataStore oldDelegate, DataStore newDelegate) {
+        // NOOP
+    }
+
+    @Override
+    public void onGlobalContextUpdated(SchemaContext context) {
+        this.schema = context;
+    }
+
+    @Override
+    public void close() throws Exception {
+        this.schema = null;
+    }
+
+    private DataModification<InstanceIdentifier, CompositeNode> prepareMergedTransaction(
+            DataModification<InstanceIdentifier, CompositeNode> original) {
+        // NOOP for now
+        return original;
+    }
+
+    private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
+        @Override
+        public int compare(Entry<InstanceIdentifier, CompositeNode> o1, Entry<InstanceIdentifier, CompositeNode> o2) {
+            InstanceIdentifier o1Key = o1.getKey();
+            InstanceIdentifier o2Key = o2.getKey();
+            return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size());
+        }
+    };
+
+    private class MergeFirstLevelReader implements DataReader<InstanceIdentifier, CompositeNode> {
+
+        @Override
+        public CompositeNode readConfigurationData(final InstanceIdentifier path) {
+            getDelegateReadLock().lock();
+            try {
+                if (path.getPath().isEmpty()) {
+                    return null;
+                }
+                QName qname = null;
+                CompositeNode original = getDelegate().readConfigurationData(path);
+                ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
+                if (original != null) {
+                    childNodes.addAll(original.getChildren());
+                    qname = original.getNodeType();
+                } else {
+                    qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
+                }
+
+                FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
+                        .filter(new Predicate<InstanceIdentifier>() {
+                            @Override
+                            public boolean apply(InstanceIdentifier input) {
+                                if (path.contains(input)) {
+                                    int nesting = input.getPath().size() - path.getPath().size();
+                                    if (nesting == 1) {
+                                        return true;
+                                    }
+                                }
+                                return false;
+                            }
+                        });
+                for (InstanceIdentifier instanceIdentifier : directChildren) {
+                    childNodes.add(getDelegate().readConfigurationData(instanceIdentifier));
+                }
+                if (original == null && childNodes.isEmpty()) {
+                    return null;
+                }
+
+                return new CompositeNodeTOImpl(qname, null, childNodes);
+            } finally {
+                getDelegateReadLock().unlock();
+            }
+        }
+
+        @Override
+        public CompositeNode readOperationalData(final InstanceIdentifier path) {
+            getDelegateReadLock().lock();
+            try {
+                if (path.getPath().isEmpty()) {
+                    return null;
+                }
+                QName qname = null;
+                CompositeNode original = getDelegate().readOperationalData(path);
+                ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
+                if (original != null) {
+                    childNodes.addAll(original.getChildren());
+                    qname = original.getNodeType();
+                } else {
+                    qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
+                }
+
+                FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
+                        .filter(new Predicate<InstanceIdentifier>() {
+                            @Override
+                            public boolean apply(InstanceIdentifier input) {
+                                if (path.contains(input)) {
+                                    int nesting = input.getPath().size() - path.getPath().size();
+                                    if (nesting == 1) {
+                                        return true;
+                                    }
+                                }
+                                return false;
+                            }
+                        });
+
+                for (InstanceIdentifier instanceIdentifier : directChildren) {
+                    childNodes.add(getDelegate().readOperationalData(instanceIdentifier));
+                }
+                if (original == null && childNodes.isEmpty()) {
+                    return null;
+                }
+
+                return new CompositeNodeTOImpl(qname, null, childNodes);
+            } finally {
+                getDelegateReadLock().unlock();
+            }
+        }
+    }
+}
index 6ef5780c8a577c1bc93c97bd95420a50d608f5fc..e790a9dbb1bbd396570445e0e58da1eee105e443 100644 (file)
             <groupId>org.eclipse.xtend</groupId>
             <artifactId>org.eclipse.xtend.lib</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netty-threadgroup-config</artifactId>
+            <version>0.2.3-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>netconf-client</artifactId>
@@ -62,7 +67,7 @@
             <groupId>${project.groupId}</groupId>
             <artifactId>config-api</artifactId>
             <version>${netconf.version}</version>
-            <scope>test</scope>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <version>${netconf.version}</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>netconf-api</artifactId>
-            <version>${netconf.version}</version>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.bgpcep</groupId>
             <artifactId>util</artifactId>
@@ -91,7 +90,6 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>netconf-client</artifactId>
-            <scope>test</scope>
             <version>${netconf.version}</version>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+            <version>2010.09.24.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>threadpool-config-api</artifactId>
+            <version>0.2.3-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netty-config-api</artifactId>
+            <version>0.2.3-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
     <packaging>bundle</packaging>
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Bundle-Activator>org.opendaylight.controller.sal.connect.netconf.NetconfProvider</Bundle-Activator>
-                    </instructions>
-                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>0.5.9-SNAPSHOT</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                                    <additionalConfiguration>
+                                        <namespaceToPackage1>
+                                            urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
+                                        </namespaceToPackage1>
+                                    </additionalConfiguration>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.controller</groupId>
+                        <artifactId>yang-jmx-generator-plugin</artifactId>
+                        <version>0.2.3-SNAPSHOT</version>
+                    </dependency>
+                </dependencies>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>1.8</version>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>${project.build.directory}/generated-sources/config</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
new file mode 100644 (file)
index 0000000..2a556c9
--- /dev/null
@@ -0,0 +1,89 @@
+/**
+* Generated file
+
+* Generated from: yang module name: opendaylight-sal-netconf-connector  yang module local name: sal-netconf-connector
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Nov 18 09:44:16 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.connector.netconf;
+
+import io.netty.channel.EventLoopGroup;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+import javax.net.ssl.SSLContext;
+
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
+import org.osgi.framework.BundleContext;
+
+import static com.google.common.base.Preconditions.*;
+
+import com.google.common.base.Optional;
+import com.google.common.net.InetAddresses;
+
+/**
+*
+*/
+public final class NetconfConnectorModule extends org.opendaylight.controller.config.yang.md.sal.connector.netconf.AbstractNetconfConnectorModule
+{
+
+    private BundleContext bundleContext;
+
+    public NetconfConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NetconfConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, NetconfConnectorModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate(){
+        super.validate();
+        checkState(getAddress() != null,"Address must be set.");
+        //checkState(getAddress().getIpv4Address() != null || getAddress().getIpv6Address() != null,"Address must be set.");
+        checkState(getPort() != null,"Port must be set.");
+        checkState(getDomRegistry() != null,"Dom Registry must be provided.");
+    }
+
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        
+        getDomRegistryDependency();
+        NetconfDevice device = new NetconfDevice(getIdentifier().getInstanceName());
+        String addressValue = getAddress();
+        
+        
+        /*
+         * Uncomment after Switch to IP Address
+        if(getAddress().getIpv4Address() != null) {
+            addressValue = getAddress().getIpv4Address().getValue();
+        } else {
+            addressValue = getAddress().getIpv6Address().getValue();
+        }
+        
+        */
+        InetAddress addr = InetAddresses.forString(addressValue);
+        InetSocketAddress socketAddress = new InetSocketAddress(addr , getPort().intValue());
+        device.setSocketAddress(socketAddress);
+        
+        EventLoopGroup bossGroup = getBossThreadGroupDependency();
+        EventLoopGroup workerGroup = getWorkerThreadGroupDependency();
+        Optional<SSLContext> maybeContext = Optional.absent();
+        NetconfClientDispatcher dispatcher = new NetconfClientDispatcher(maybeContext , bossGroup, workerGroup);
+        
+        getDomRegistryDependency().registerProvider(device, bundleContext);
+        
+        device.start(dispatcher);
+        return device;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModuleFactory.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModuleFactory.java
new file mode 100644 (file)
index 0000000..51e288d
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: opendaylight-sal-netconf-connector  yang module local name: sal-netconf-connector
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Mon Nov 18 09:44:16 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.md.sal.connector.netconf;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
+/**
+*
+*/
+public class NetconfConnectorModuleFactory extends
+        org.opendaylight.controller.config.yang.md.sal.connector.netconf.AbstractNetconfConnectorModuleFactory {
+
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver,
+            DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
+        NetconfConnectorModule module = (NetconfConnectorModule) super.createModule(instanceName, dependencyResolver,
+                old, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+        NetconfConnectorModule module = (NetconfConnectorModule) super.createModule(instanceName, dependencyResolver,
+                bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+}
index 0171c1f9e312b5020f26ee4dec1d0b23a8f34cf2..49d9757f421058cb05ffed90f81922f6509ff688 100644 (file)
@@ -14,8 +14,16 @@ import org.opendaylight.yangtools.yang.common.QName
 import java.util.Collections
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
 import org.opendaylight.yangtools.concepts.Registration
+import org.opendaylight.controller.sal.core.api.Provider
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
 
-class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, RpcImplementation {
+class NetconfDevice implements Provider, DataReader<InstanceIdentifier, CompositeNode>, RpcImplementation, AutoCloseable {
 
     var NetconfClient client;
 
@@ -23,25 +31,29 @@ class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, Rp
     var InetSocketAddress socketAddress;
 
     @Property
-    val MountProvisionInstance mountInstance;
+    var MountProvisionInstance mountInstance;
 
     @Property
-    val InstanceIdentifier path;
-    
-    Registration<DataReader<InstanceIdentifier,CompositeNode>> operReaderReg
-    
-    Registration<DataReader<InstanceIdentifier,CompositeNode>> confReaderReg
-    
-    public new(MountProvisionInstance mount,InstanceIdentifier path) {
-        _mountInstance = mount;
-        _path = path;
+    var InstanceIdentifier path;
+
+    Registration<DataReader<InstanceIdentifier, CompositeNode>> operReaderReg
+
+    Registration<DataReader<InstanceIdentifier, CompositeNode>> confReaderReg
+
+    String name
+
+    MountProvisionService mountService
+
+    public new(String name) {
+        this.name = name;
+        this.path = InstanceIdentifier.builder(INVENTORY_PATH).nodeWithKey(INVENTORY_NODE,
+            Collections.singletonMap(INVENTORY_ID, name)).toInstance;
     }
 
     def start(NetconfClientDispatcher dispatcher) {
-        client = new NetconfClient("sal-netconf-connector", socketAddress, dispatcher);
-        
-        confReaderReg = mountInstance.registerConfigurationReader(path,this);
-        operReaderReg = mountInstance.registerOperationalReader(path,this);
+        client = new NetconfClient(name, socketAddress, dispatcher);
+        confReaderReg = mountInstance.registerConfigurationReader(path, this);
+        operReaderReg = mountInstance.registerOperationalReader(path, this);
     }
 
     override readConfigurationData(InstanceIdentifier path) {
@@ -66,6 +78,40 @@ class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, Rp
         return result.toRpcResult();
     }
 
+    override getProviderFunctionality() {
+        Collections.emptySet
+    }
+
+    override onSessionInitiated(ProviderSession session) {
+        val dataBroker = session.getService(DataBrokerService);
+        
+        
+        
+        val transaction = dataBroker.beginTransaction
+        if(transaction.operationalNodeNotExisting) {
+            transaction.putOperationalData(path,nodeWithId)
+        }
+        if(transaction.configurationNodeNotExisting) {
+            transaction.putConfigurationData(path,nodeWithId)
+        }
+        transaction.commit().get();
+        mountService = session.getService(MountProvisionService);
+        mountInstance = mountService.createOrGetMountPoint(path);
+    }
+    
+    def getNodeWithId() {
+        val id = new SimpleNodeTOImpl(INVENTORY_ID,null,name);
+        return new CompositeNodeTOImpl(INVENTORY_NODE,null,Collections.singletonList(id));
+    }
+    
+    def boolean configurationNodeNotExisting(DataModificationTransaction transaction) {
+        return null === transaction.readConfigurationData(path);
+    }
+    
+    def boolean operationalNodeNotExisting(DataModificationTransaction transaction) {
+        return null === transaction.readOperationalData(path);
+    }
+
     def Node<?> findNode(CompositeNode node, InstanceIdentifier identifier) {
 
         var Node<?> current = node;
@@ -86,10 +132,11 @@ class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, Rp
         }
         return current;
     }
-    
-    public def stop() {
+
+    override close() {
         confReaderReg?.close()
         operReaderReg?.close()
+        client?.close()
     }
 
 }
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend
deleted file mode 100644 (file)
index 2fe145e..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.opendaylight.controller.sal.connect.netconf
-
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.common.QName
-import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*;
-import static extension org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils.*;
-
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
-import java.util.Map
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
-import java.io.OptionalDataException
-import com.google.common.base.Optional
-import java.net.SocketAddress
-import java.net.InetSocketAddress
-
-class NetconfDeviceManager {
-
-    val Map<InstanceIdentifier, NetconfDevice> devices = new ConcurrentHashMap;
-
-    var ProviderSession session;
-
-    @Property
-    var DataProviderService dataService;
-    
-    @Property
-    var MountProvisionService mountService;
-    
-    val nodeUpdateListener = new NetconfInventoryListener(this);
-
-
-    @Property
-    var NetconfClientDispatcher dispatcher;
-
-    def void start() {
-        dataService?.registerDataChangeListener(INVENTORY_PATH, nodeUpdateListener);
-        if(dispatcher == null) {
-        dispatcher = new NetconfClientDispatcher(Optional.absent);
-        }
-    }
-
-    def netconfNodeAdded(InstanceIdentifier path, CompositeNode node) {
-        val address = node.endpointAddress;
-        val port = Integer.parseInt(node.endpointPort);
-        netconfNodeAdded(path,new InetSocketAddress(address,port))
-
-    }
-    
-    def netconfNodeAdded(InstanceIdentifier path, InetSocketAddress address) {
-    
-        val mountPointPath = path;
-        val mountPoint = mountService.createOrGetMountPoint(mountPointPath);
-        val localPath = InstanceIdentifier.builder().toInstance;
-        val netconfDevice = new NetconfDevice(mountPoint,localPath);
-        netconfDevice.setSocketAddress(address);
-        netconfDevice.start(dispatcher);
-    }
-
-    def netconfNodeRemoved(InstanceIdentifier path) {
-    
-    }
-
-}
-
-class NetconfInventoryListener implements DataChangeListener {
-
-    val NetconfDeviceManager manager;
-
-    new(NetconfDeviceManager manager) {
-        this.manager = manager;
-    }
-
-    override onDataChanged(DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
-        
-        //manager.netconfNodeAdded(path, change);
-    }
-}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java
deleted file mode 100644 (file)
index 8cf5f02..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.opendaylight.controller.sal.connect.netconf;
-
-import java.util.Hashtable;
-
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.osgi.framework.BundleContext;
-
-public class NetconfProvider extends AbstractProvider {
-
-    private NetconfDeviceManager netconfDeviceManager;
-
-    @Override
-    protected void startImpl(BundleContext context) {
-        netconfDeviceManager = new NetconfDeviceManager();
-        context.registerService(NetconfDeviceManager.class, netconfDeviceManager, new Hashtable<String,String>());
-    }
-    
-    
-    @Override
-    public void onSessionInitiated(ProviderSession session) {
-        MountProvisionService mountService = session.getService(MountProvisionService.class);
-        
-        
-        netconfDeviceManager.setMountService(mountService);
-        netconfDeviceManager.start();
-    }
-
-    @Override
-    protected void stopImpl(BundleContext context) {
-        
-    }
-}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang b/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang
new file mode 100644 (file)
index 0000000..45f1016
--- /dev/null
@@ -0,0 +1,75 @@
+module odl-sal-netconf-connector-cfg {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf";
+    prefix "sal-netconf";
+
+       import config { prefix config; revision-date 2013-04-05; }
+       import threadpool {prefix th;}
+       import netty {prefix netty;}
+       import ietf-inet-types {prefix inet;}
+       import opendaylight-md-sal-dom {prefix dom;}
+
+    description
+        "Service definition for Binding Aware MD-SAL.";
+    revision "2013-10-28" {
+        description
+            "Initial revision";
+    }
+
+    identity sal-netconf-connector {
+        base config:module-type;
+        config:java-name-prefix NetconfConnector;
+    }
+
+
+    grouping server {
+        leaf address {
+            type string;
+        }
+    
+        leaf port {
+            type uint32;
+        }
+    }
+
+
+    augment "/config:modules/config:module/config:configuration" {
+        case sal-netconf-connector {
+            when "/config:modules/config:module/config:type = 'sal-netconf-connector'";
+            
+            leaf address {
+                type string;
+            }
+
+            leaf port {
+                type uint32;
+            }
+
+            container dom-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity dom:dom-broker-osgi-registry;
+                    }
+                }
+            }
+
+            container boss-thread-group {
+                uses config:service-ref {
+                    refine type {
+                        config:required-identity netty:netty-threadgroup;
+                    }
+                }
+            }
+
+            container worker-thread-group {
+                uses config:service-ref {
+                    refine type {
+                        config:required-identity netty:netty-threadgroup;
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft01.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft01.java
new file mode 100644 (file)
index 0000000..557adb6
--- /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.sal.rest.api;
+
+public class Draft01 {
+    public static class MediaTypes {
+        public static final String API = "application/vnd.yang.api";
+        public static final String DATASTORE = "application/vnd.yang.datastore";
+        public static final String DATA = "application/vnd.yang.data";
+        public static final String EVENT = "application/vnd.yang.event";
+        public static final String OPERATION = "application/vnd.yang.operation";
+        public static final String PATCH = "application/vnd.yang.patch";
+    }
+}
index a22ea623975049cd3bd37c8af3103fecce4317e4..5d08b3e7b6cb27bec3e2bbb68c5c1f9927f603aa 100644 (file)
@@ -7,14 +7,13 @@
  */
 package org.opendaylight.controller.sal.rest.api;
 
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
@@ -58,42 +57,51 @@ public interface RestconfService extends RestconfServiceLegacy {
 
     @GET
     @Path("/modules")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft01.MediaTypes.API+JSON,Draft01.MediaTypes.API+XML,
+               Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML})
     public StructuredData getModules();
 
     @POST
     @Path("/operations/{identifier}")
-    @Produces({Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML,API+JSON,API+XML})
+    @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML,
+               Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
     
     @GET
     @Path("/config/{identifier:.+}")
-    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
     
-    @PUT
+    @POST
     @Path("/config/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
 
-    @POST
+    @PUT
     @Path("/config/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @GET
     @Path("/operational/{identifier:.+}")
-    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public StructuredData readOperationalData(@PathParam("identifier") String identifier);
 
-    @PUT
+    @POST
     @Path("/operational/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
 
-    @POST
+    @PUT
     @Path("/operational/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
 
 }
index 242e7f3150d4b775ce56d957ae62ba947a080eba..35da98b1a0db82e72d6cb32de8e0e34c858e1a41 100644 (file)
@@ -1,13 +1,12 @@
 package org.opendaylight.controller.sal.rest.api;
 
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
@@ -21,25 +20,28 @@ public interface RestconfServiceLegacy {
     @Deprecated
     @GET
     @Path("/datastore")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft01.MediaTypes.DATASTORE+JSON,Draft01.MediaTypes.DATASTORE+XML})
     public StructuredData readAllData();
 
     @Deprecated
     @GET
     @Path("/datastore/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public StructuredData readData(@PathParam("identifier") String identifier);
 
     @Deprecated
-    @PUT
+    @POST
     @Path("/datastore/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @Deprecated
-    @POST
+    @PUT
     @Path("/datastore/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
+    @Produces({Draft01.MediaTypes.DATA+JSON,Draft01.MediaTypes.DATA+XML, 
+               MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
     public Response updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
 
 }
index 5a1b42fd8009d074613407088c94359bac5dc6d9..351ae6ebbee085614943d7608ec51669a204f1ff 100644 (file)
@@ -3,70 +3,57 @@ package org.opendaylight.controller.sal.rest.impl;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.IOException;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import javax.activation.UnsupportedDataTypeException;
 
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.type.*;
 
 import com.google.common.base.Preconditions;
 import com.google.gson.stream.JsonWriter;
 
 class JsonMapper {
-    
+
     private final Set<LeafListSchemaNode> foundLeafLists = new HashSet<>();
     private final Set<ListSchemaNode> foundLists = new HashSet<>();
-    
+
     public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
         Preconditions.checkNotNull(writer);
         Preconditions.checkNotNull(data);
         Preconditions.checkNotNull(schema);
 
         writer.beginObject();
-        
+
         if (schema instanceof ContainerSchemaNode) {
             writeContainer(writer, data, (ContainerSchemaNode) schema);
         } else if (schema instanceof ListSchemaNode) {
-            writeList(writer, data, (ListSchemaNode) schema);
+            writeList(writer, null, data, (ListSchemaNode) schema);
         } else {
             throw new UnsupportedDataTypeException(
                     "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
         }
-        
+
         writer.endObject();
-        
+
         foundLeafLists.clear();
         foundLists.clear();
     }
 
-    private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema) throws IOException {
+    private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema)
+            throws IOException {
         checkNotNull(parent);
         checkNotNull(parentSchema);
-        
+
         for (Node<?> child : parent.getChildren()) {
             DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
             if (childSchema == null) {
                 throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
                         + "\" is not conform to schema");
             }
-            
+
             if (childSchema instanceof ContainerSchemaNode) {
                 Preconditions.checkState(child instanceof CompositeNode,
                         "Data representation of Container should be CompositeNode - " + child.getNodeType());
@@ -76,14 +63,14 @@ class JsonMapper {
                     Preconditions.checkState(child instanceof CompositeNode,
                             "Data representation of List should be CompositeNode - " + child.getNodeType());
                     foundLists.add((ListSchemaNode) childSchema);
-                    writeList(writer, (CompositeNode) child, (ListSchemaNode) childSchema);
+                    writeList(writer, parent, (CompositeNode) child, (ListSchemaNode) childSchema);
                 }
             } else if (childSchema instanceof LeafListSchemaNode) {
                 if (!foundLeafLists.contains(childSchema)) {
                     Preconditions.checkState(child instanceof SimpleNode<?>,
                             "Data representation of LeafList should be SimpleNode - " + child.getNodeType());
                     foundLeafLists.add((LeafListSchemaNode) childSchema);
-                    writeLeafList(writer, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
+                    writeLeafList(writer, parent, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
                 }
             } else if (childSchema instanceof LeafSchemaNode) {
                 Preconditions.checkState(child instanceof SimpleNode<?>,
@@ -94,7 +81,7 @@ class JsonMapper {
                         + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet.");
             }
         }
-        
+
         for (Node<?> child : parent.getChildren()) {
             DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
             if (childSchema instanceof LeafListSchemaNode) {
@@ -104,7 +91,7 @@ class JsonMapper {
             }
         }
     }
-    
+
     private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
         for (DataSchemaNode dsn : dataSchemaNode) {
             if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
@@ -113,84 +100,166 @@ class JsonMapper {
         }
         return null;
     }
-    
+
     private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
-        writer.name(node.getNodeType().getLocalName());
+        writeName(node, schema, writer);
         writer.beginObject();
         writeChildrenOfParent(writer, node, schema);
         writer.endObject();
     }
-    
-    private void writeList(JsonWriter writer, CompositeNode node, ListSchemaNode schema) throws IOException {
-            writer.name(node.getNodeType().getLocalName());
-            writer.beginArray();
-            
-            if (node.getParent() != null) {
-                CompositeNode parent = node.getParent();
-                List<CompositeNode> nodeLists = parent.getCompositesByName(node.getNodeType());
-                for (CompositeNode nodeList : nodeLists) {
-                    writer.beginObject();
-                    writeChildrenOfParent(writer, nodeList, schema);
-                    writer.endObject();
-                }
-            } else {
+
+    private void writeList(JsonWriter writer, CompositeNode nodeParent, CompositeNode node, ListSchemaNode schema)
+            throws IOException {
+        writeName(node, schema, writer);
+        writer.beginArray();
+
+        if (nodeParent != null) {
+            List<CompositeNode> nodeLists = nodeParent.getCompositesByName(node.getNodeType());
+            for (CompositeNode nodeList : nodeLists) {
                 writer.beginObject();
-                writeChildrenOfParent(writer, node, schema);
+                writeChildrenOfParent(writer, nodeList, schema);
                 writer.endObject();
             }
-            
-            writer.endArray();
-    }
-    
-    private void writeLeafList(JsonWriter writer, SimpleNode<?> node, LeafListSchemaNode schema) throws IOException {
-            writer.name(node.getNodeType().getLocalName());
-            writer.beginArray();
-            
-            CompositeNode parent = node.getParent();
-            List<SimpleNode<?>> nodeLeafLists = parent.getSimpleNodesByName(node.getNodeType());
-            for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
-                writeValueOfNodeByType(writer, nodeLeafList, schema.getType());
-            }
-            
-            writer.endArray();
+        } else {
+            writer.beginObject();
+            writeChildrenOfParent(writer, node, schema);
+            writer.endObject();
+        }
+
+        writer.endArray();
+    }
+
+    private void writeLeafList(JsonWriter writer, CompositeNode nodeParent, SimpleNode<?> node,
+            LeafListSchemaNode schema) throws IOException {
+        writeName(node, schema, writer);
+        writer.beginArray();
+
+        List<SimpleNode<?>> nodeLeafLists = nodeParent.getSimpleNodesByName(node.getNodeType());
+        for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
+            writeValueOfNodeByType(writer, nodeLeafList, schema.getType());
+        }
+
+        writer.endArray();
     }
-    
+
     private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
-        writer.name(node.getNodeType().getLocalName());
+        writeName(node, schema, writer);
         writeValueOfNodeByType(writer, node, schema.getType());
     }
-    
-    private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type) throws IOException {
-        if (!(node.getValue() instanceof String)) {
-            throw new IllegalStateException("Value in SimpleNode should be type String");
-        }
-        
-        String value = (String) node.getValue();
-        // TODO check Leafref, InstanceIdentifierTypeDefinition, IdentityrefTypeDefinition, UnionTypeDefinition
-        if (type.getBaseType() != null) {
-            writeValueOfNodeByType(writer, node, type.getBaseType());
-        } else if (type instanceof InstanceIdentifierTypeDefinition) {
-            writer.value(((InstanceIdentifierTypeDefinition) type).getPathStatement().toString());
-        } else if (type instanceof DecimalTypeDefinition 
-                || type instanceof IntegerTypeDefinition
-                || type instanceof UnsignedIntegerTypeDefinition) {
+
+    private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type)
+            throws IOException {
+
+        String value = String.valueOf(node.getValue());
+        // TODO check Leafref, InstanceIdentifierTypeDefinition,
+        // IdentityrefTypeDefinition, UnionTypeDefinition
+        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+        if (baseType instanceof InstanceIdentifierTypeDefinition) {
+            writer.value(((InstanceIdentifierTypeDefinition) baseType).getPathStatement().toString());
+        } else if (baseType instanceof UnionTypeDefinition) {
+            processTypeIsUnionType(writer, (UnionTypeDefinition) baseType, value);
+        } else if (baseType instanceof DecimalTypeDefinition || baseType instanceof IntegerTypeDefinition
+                || baseType instanceof UnsignedIntegerTypeDefinition) {
+            writer.value(new NumberForJsonWriter(value));
+        } else if (baseType instanceof BooleanTypeDefinition) {
+            writer.value(Boolean.parseBoolean(value));
+        } else if (baseType instanceof EmptyTypeDefinition) {
+            writeEmptyDataTypeToJson(writer);
+        } else {
+            writer.value(value.equals("null") ? "" : value);
+        }
+    }
+
+    private void processTypeIsUnionType(JsonWriter writer, UnionTypeDefinition unionType, String value)
+            throws IOException {
+        if (value == null) {
+            writeEmptyDataTypeToJson(writer);
+        } else if ((isNumber(value))
+                && containsType(unionType, UnsignedIntegerTypeDefinition.class, IntegerTypeDefinition.class,
+                        DecimalTypeDefinition.class)) {
             writer.value(new NumberForJsonWriter(value));
-        } else if (type instanceof BooleanTypeDefinition) {
+        } else if (isBoolean(value) && containsType(unionType, BooleanTypeDefinition.class)) {
             writer.value(Boolean.parseBoolean(value));
-        } else if (type instanceof EmptyTypeDefinition) {
-            writer.beginArray();
-            writer.nullValue();
-            writer.endArray();
         } else {
-            writer.value(value != null ? value : "");
+            writer.value(value);
         }
     }
-    
+
+    private boolean isBoolean(String value) {
+        if (value.equals("true") || value.equals("false")) {
+            return true;
+        }
+        return false;
+    }
+
+    private void writeEmptyDataTypeToJson(JsonWriter writer) throws IOException {
+        writer.beginArray();
+        writer.nullValue();
+        writer.endArray();
+    }
+
+    private boolean isNumber(String value) {
+        try {
+            Double.valueOf(value);
+        } catch (NumberFormatException e) {
+            return false;
+        }
+        return true;
+    }
+
+    private boolean containsType(UnionTypeDefinition unionType, Class<?>... searchedTypes) {
+        List<TypeDefinition<?>> allUnionSubtypes = resolveAllUnionSubtypesFrom(unionType);
+
+        for (TypeDefinition<?> unionSubtype : allUnionSubtypes) {
+            for (Class<?> searchedType : searchedTypes) {
+                if (searchedType.isInstance(unionSubtype)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private List<TypeDefinition<?>> resolveAllUnionSubtypesFrom(UnionTypeDefinition inputType) {
+        List<TypeDefinition<?>> result = new ArrayList<>();
+        for (TypeDefinition<?> subtype : inputType.getTypes()) {
+            TypeDefinition<?> resolvedSubtype = subtype;
+
+            resolvedSubtype = resolveBaseTypeFrom(subtype);
+
+            if (resolvedSubtype instanceof UnionTypeDefinition) {
+                List<TypeDefinition<?>> subtypesFromRecursion = resolveAllUnionSubtypesFrom((UnionTypeDefinition) resolvedSubtype);
+                result.addAll(subtypesFromRecursion);
+            } else {
+                result.add(resolvedSubtype);
+            }
+        }
+
+        return result;
+    }
+
+    private TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
+        return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
+    }
+
+    private void writeName(Node<?> node, DataSchemaNode schema, JsonWriter writer) throws IOException {
+        String nameForOutput = node.getNodeType().getLocalName();
+        if (schema.isAugmenting()) {
+            ControllerContext contContext = ControllerContext.getInstance();
+            CharSequence moduleName;
+            moduleName = contContext.toRestconfIdentifier(schema.getQName());
+            if (moduleName != null) {
+                nameForOutput = moduleName.toString();
+            }
+        }
+        writer.name(nameForOutput);
+    }
+
     private static final class NumberForJsonWriter extends Number {
-        
+
         private static final long serialVersionUID = -3147729419814417666L;
         private final String value;
-        
+
         public NumberForJsonWriter(String value) {
             this.value = value;
         }
@@ -219,7 +288,7 @@ class JsonMapper {
         public String toString() {
             return value;
         }
-        
+
     }
 
 }
index dea4a73cd17d23f53f7c88d9b2ace669b285a2a6..2b1abaa987a6488a5626b8c0e2d48f5517abf80a 100644 (file)
@@ -1,7 +1,5 @@
 package org.opendaylight.controller.sal.rest.impl;
 
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
@@ -15,14 +13,17 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.Provider;
 
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 @Provider
-@Consumes({API+RestconfService.JSON})
+@Consumes({ Draft01.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
+        MediaType.APPLICATION_JSON })
 public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
     INSTANCE;
-    
+
     @Override
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return true;
@@ -36,8 +37,8 @@ public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNo
         try {
             return jsonReader.read(entityStream);
         } catch (UnsupportedFormatException e) {
-            throw new WebApplicationException(e,Response.status(Response.Status.BAD_REQUEST)
-                    .entity(e.getMessage()).build());
+            throw new WebApplicationException(e, Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())
+                    .build());
         }
     }
 
index 90e6d2affc5cde925d4adc941b24d42005aad117..7022db2bc9bba631b2b21f50f2bb2a20d395d7d5 100644 (file)
@@ -1,7 +1,5 @@
 package org.opendaylight.controller.sal.rest.impl;
 
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -16,6 +14,8 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.Provider;
 
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -24,10 +24,11 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import com.google.gson.stream.JsonWriter;
 
 @Provider
-@Produces({API+RestconfService.JSON})
+@Produces({ Draft01.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
+        MediaType.APPLICATION_JSON })
 public enum StructuredDataToJsonProvider implements MessageBodyWriter<StructuredData> {
     INSTANCE;
-    
+
     @Override
     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return true;
index 9f41b571dade2dc5eb806e350a6e229d17598ded..d0c007795263be5d8777ebd9af29774a8b47d0d9 100644 (file)
@@ -1,7 +1,5 @@
 package org.opendaylight.controller.sal.rest.impl;
 
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
 import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
@@ -21,7 +19,10 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
@@ -30,10 +31,11 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
 @Provider
-@Produces({API+RestconfService.XML})
+@Produces({ Draft01.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
+        MediaType.APPLICATION_XML, MediaType.TEXT_XML })
 public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredData> {
     INSTANCE;
-    
+
     private final static Logger logger = LoggerFactory.getLogger(StructuredDataToXmlProvider.class);
 
     @Override
@@ -52,9 +54,9 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
             throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
         if (data == null) {
-            throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
+            throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
         }
-        
+
         Document domTree = NodeUtils.buildShadowDomTree(data);
         try {
             TransformerFactory tf = TransformerFactory.newInstance();
@@ -67,7 +69,7 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
             transformer.transform(new DOMSource(domTree), new StreamResult(entityStream));
         } catch (TransformerException e) {
             logger.error("Error during translation of Document to OutputStream", e);
-            throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR).build());
+            throw new ResponseException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
         }
     }
 
index 9f31eb46d52e9a722bffdc7d742859adba09cfc6..bf7ff7d43524732f067982042fb46e19f3d35134 100644 (file)
@@ -18,13 +18,13 @@ import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
 
 public class XmlReader {
-    
+
     private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
     private XMLEventReader eventReader;
 
     public CompositeNodeWrapper read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException {
         eventReader = xmlInputFactory.createXMLEventReader(entityStream);
-        
+
         if (eventReader.hasNext()) {
             XMLEvent element = eventReader.peek();
             if (element.isStartDocument()) {
@@ -35,7 +35,7 @@ public class XmlReader {
         if (eventReader.hasNext() && !isCompositeNodeEvent(eventReader.peek())) {
             throw new UnsupportedFormatException("Root element of XML has to be composite element.");
         }
-        
+
         final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
         CompositeNodeWrapper root = null;
         NodeWrapper<?> element = null;
@@ -73,14 +73,14 @@ public class XmlReader {
                 element = processingQueue.pop();
             }
         }
-        
+
         if (!root.getLocalName().equals(element.getLocalName())) {
             throw new UnsupportedFormatException("XML should contain only one root element");
         }
-        
+
         return root;
     }
-    
+
     private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
         checkArgument(event != null, "XML Event cannot be NULL!");
         if (event.isStartElement()) {
@@ -99,7 +99,7 @@ public class XmlReader {
         }
         return false;
     }
-    
+
     private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
         checkArgument(event != null, "XML Event cannot be NULL!");
         if (event.isStartElement()) {
@@ -120,8 +120,9 @@ public class XmlReader {
         }
         return false;
     }
-    
-    private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement) throws XMLStreamException {
+
+    private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement)
+            throws XMLStreamException {
         checkArgument(startElement != null, "Start Element cannot be NULL!");
         String data = null;
 
@@ -133,25 +134,29 @@ public class XmlReader {
                     data = innerEvent.asCharacters().getData();
                 }
             } else if (innerEvent.isEndElement()) {
-                data = "";
+                if (startElement.getLocation().getCharacterOffset() == innerEvent.getLocation().getCharacterOffset()) {
+                    data = null;
+                } else {
+                    data = "";
+                }
             }
         }
-        
+
         return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
     }
-    
+
     private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
         checkArgument(startElement != null, "Start Element cannot be NULL!");
         return new CompositeNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
     }
-    
+
     private String getLocalNameFrom(StartElement startElement) {
         return startElement.getName().getLocalPart();
     }
-    
+
     private URI getNamespaceFrom(StartElement startElement) {
         String namespaceURI = startElement.getName().getNamespaceURI();
         return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
     }
-    
+
 }
index 19720107d3b2e12a63e10cedec8ec173b7ea52e8..f09c3b4cc1769dfd02ff1b5e8666b14571673451 100644 (file)
@@ -1,7 +1,5 @@
 package org.opendaylight.controller.sal.rest.impl;
 
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
@@ -16,11 +14,15 @@ import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.Provider;
 import javax.xml.stream.XMLStreamException;
 
+import org.opendaylight.controller.sal.rest.api.Draft01;
+import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 @Provider
-@Consumes({ API + RestconfService.XML })
+@Consumes({ Draft01.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
+        MediaType.APPLICATION_XML, MediaType.TEXT_XML })
 public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
     INSTANCE;
 
@@ -37,8 +39,7 @@ public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNod
         try {
             return xmlReader.read(entityStream);
         } catch (XMLStreamException | UnsupportedFormatException e) {
-            throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())
-                    .build());
+            throw new ResponseException(Response.Status.BAD_REQUEST, e.getMessage());
         }
     }
 
index f5b913253201ee3d045bfbc00d3af994fdf8cba0..29ad7522c43436891ec6cb717ee6cbc713a04abd 100644 (file)
@@ -22,7 +22,7 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
     private DataBrokerService dataService;
     
     private new() {
-        if (INSTANCE != null) {
+        if (INSTANCE !== null) {
             throw new IllegalStateException("Already instantiated");
         }
     }
@@ -32,9 +32,8 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
     }
 
     private def void checkPreconditions() {
-        if (context == null || dataService == null) {
-            throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE)
-                    .entity(RestconfProvider::NOT_INITALIZED_MSG).build())
+        if (context === null || dataService === null) {
+            throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
         }
     }
 
index c1ee611e07c77241b1346f0683387d503111e1e9..065d01e8e9405058f563189e6f5117d30eed4857 100644 (file)
@@ -9,7 +9,6 @@ import java.util.HashMap
 import java.util.List
 import java.util.Map
 import java.util.concurrent.ConcurrentHashMap
-import javax.ws.rs.WebApplicationException
 import javax.ws.rs.core.Response
 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
 import org.opendaylight.controller.sal.rest.impl.RestconfProvider
@@ -46,7 +45,7 @@ class ControllerContext implements SchemaServiceListener {
     
 
     private new() {
-        if (INSTANCE != null) {
+        if (INSTANCE !== null) {
             throw new IllegalStateException("Already instantiated");
         }
     }
@@ -56,9 +55,8 @@ class ControllerContext implements SchemaServiceListener {
     }
     
     private def void checkPreconditions() {
-        if (schemas == null) {
-            throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE)
-                    .entity(RestconfProvider::NOT_INITALIZED_MSG).build())
+        if (schemas === null) {
+            throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
         }
     }
 
@@ -72,7 +70,7 @@ class ControllerContext implements SchemaServiceListener {
             pathArgs.remove(0)
         }
         val schemaNode = ret.collectPathArguments(pathArgs, restconfInstance.findModule);
-        if (schemaNode == null) {
+        if (schemaNode === null) {
             return null
         }
         new InstanceIdWithSchemaNode(ret.toInstance, schemaNode)
@@ -92,7 +90,7 @@ class ControllerContext implements SchemaServiceListener {
 
     private def getLatestModule(SchemaContext schema, String moduleName) {
         checkNotNull(schema)
-        checkArgument(moduleName != null && !moduleName.empty)
+        checkArgument(moduleName !== null && !moduleName.empty)
         val modules = schema.modules.filter[m|m.name == moduleName]
         var latestModule = modules.head
         for (module : modules) {
@@ -134,9 +132,9 @@ class ControllerContext implements SchemaServiceListener {
     def CharSequence toRestconfIdentifier(QName qname) {
         checkPreconditions
         var module = uriToModuleName.get(qname.namespace)
-        if (module == null) {
+        if (module === null) {
             val moduleSchema = schemas.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
-            if(moduleSchema == null) throw new IllegalArgumentException()
+            if(moduleSchema === null) throw new IllegalArgumentException()
             uriToModuleName.put(qname.namespace, moduleSchema.name)
             module = moduleSchema.name;
         }
@@ -189,13 +187,16 @@ class ControllerContext implements SchemaServiceListener {
     }
 
     private def toUriString(Object object) {
-        if(object == null) return "";
+        if(object === null) return "";
         return URLEncoder.encode(object.toString)
     }
 
     private def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
         DataNodeContainer parentNode) {
         checkNotNull(strings)
+        if (parentNode === null) {
+            return null;
+        }
         if (strings.empty) {
             return parentNode as DataSchemaNode;
         }
@@ -203,14 +204,14 @@ class ControllerContext implements SchemaServiceListener {
 
         val nodeName = nodeRef.toNodeName();
         val targetNode = parentNode.getDataChildByName(nodeName);
-        if (targetNode == null) {
+        if (targetNode === null) {
             val children = parentNode.childNodes
             for (child : children) {
                 if (child instanceof ChoiceNode) {
                     val choice = child as ChoiceNode
                     for (caze : choice.cases) {
                         val result = builder.collectPathArguments(strings, caze as DataNodeContainer);
-                        if (result != null)
+                        if (result !== null)
                             return result
                     }
                 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/MediaTypes.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/MediaTypes.java
deleted file mode 100644 (file)
index af18828..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.restconf.impl;
-
-public class MediaTypes {
-    public static final String API = "application/vnd.yang.api";
-    public static final String DATASTORE = "application/vnd.yang.datastore";
-    public static final String DATA = "application/vnd.yang.data";
-    public static final String EVENT = "application/vnd.yang.event";
-    public static final String OPERATION = "application/vnd.yang.operation";
-    public static final String PATCH = "application/vnd.yang.patch";
-}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ResponseException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ResponseException.java
new file mode 100644 (file)
index 0000000..e2edd5d
--- /dev/null
@@ -0,0 +1,15 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+public class ResponseException extends WebApplicationException {
+
+    private static final long serialVersionUID = -5320114450593021655L;
+
+    public ResponseException(Status status, String msg) {
+        super(Response.status(status).type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
+    }
+}
index d9ac53589fa5415bcba3e59467576fcbb98d069e..8f6ca1685bbb4b0c6f81ec2dc85ae4fd4c92d5f2 100644 (file)
@@ -7,6 +7,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
+import javax.ws.rs.WebApplicationException
 
 class RestconfImpl implements RestconfService {
     
@@ -19,7 +20,7 @@ class RestconfImpl implements RestconfService {
     extension ControllerContext controllerContext
     
     private new() {
-        if (INSTANCE != null) {
+        if (INSTANCE !== null) {
             throw new IllegalStateException("Already instantiated");
         }
     }
@@ -42,13 +43,13 @@ class RestconfImpl implements RestconfService {
     }
 
     override readData(String identifier) {
-        val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+        val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
     }
 
     override createConfigurationData(String identifier, CompositeNode payload) {
-        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
         switch status.result {
@@ -58,7 +59,7 @@ class RestconfImpl implements RestconfService {
     }
 
     override updateConfigurationData(String identifier, CompositeNode payload) {
-        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
         switch status.result {
@@ -76,13 +77,13 @@ class RestconfImpl implements RestconfService {
     }
     
     override readConfigurationData(String identifier) {
-        val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+        val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
     }
     
     override readOperationalData(String identifier) {
-        val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+        val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
     }
@@ -96,7 +97,7 @@ class RestconfImpl implements RestconfService {
     }
     
     override createOperationalData(String identifier, CompositeNode payload) {
-        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
         val status = broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
         switch status.result {
@@ -106,7 +107,7 @@ class RestconfImpl implements RestconfService {
     }
     
     override updateOperationalData(String identifier, CompositeNode payload) {
-        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
         val status = broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
         switch status.result {
@@ -115,6 +116,14 @@ class RestconfImpl implements RestconfService {
         }
     }
     
+    private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        if (identifierWithSchemaNode === null) {
+            throw new ResponseException(Response.Status.BAD_REQUEST, "URI has bad format");
+        }
+        return identifierWithSchemaNode
+    }
+    
     private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) {
         if (node instanceof CompositeNodeWrapper) {
             addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema)
@@ -124,7 +133,7 @@ class RestconfImpl implements RestconfService {
     }
 
     private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
-        if (nodeBuilder.namespace == null) {
+        if (nodeBuilder.namespace === null) {
             nodeBuilder.namespace = schema.QName.namespace
         }
         if (nodeBuilder instanceof CompositeNodeWrapper) {
index 12f33d4562526b25feef31e8dd9e7c6a9dfa352c..62a9ae05814b3a2d7a7d259c0811d484c580f99e 100644 (file)
@@ -1,13 +1,13 @@
 package org.opendaylight.controller.sal.restconf.impl;
 
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.*;
 
 public class StructuredData {
-    
+
     private final CompositeNode data;
     private final DataSchemaNode schema;
-    
+
     public StructuredData(CompositeNode data, DataSchemaNode schema) {
         this.data = data;
         this.schema = schema;
@@ -20,5 +20,4 @@ public class StructuredData {
     public DataSchemaNode getSchema() {
         return schema;
     }
-    
 }
index ede225c709ea89f53b411ecf14fc366dda27522b..2e8b07151914b12c9b0c2a360b1c9b075c0a880a 100644 (file)
@@ -90,7 +90,7 @@ public class FromJsonToCompositeNodeTest {
     }
 
     @Test
-    public void nullArrayToCompositeNodeWithNullValueTest() {
+    public void nullArrayToSimpleNodeWithNullValueTest() {
         CompositeNode compositeNode = compositeContainerFromJson("/json-to-composite-node/array-with-null.json", true);
         assertNotNull(compositeNode);
         assertEquals("cont", compositeNode.getNodeType().getLocalName());
index 6249d2a5b0d3a475fa6435714a24fc57d901a554..ef122dd8d7f68cba55088831d9ebe639c869b646 100644 (file)
@@ -11,7 +11,7 @@ import javax.ws.rs.WebApplicationException;
 
 import org.junit.*;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.*;
 import org.opendaylight.yangtools.yang.data.api.*;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.slf4j.*;
@@ -41,9 +41,36 @@ public class FromXmlToCompositeNodeTest {
         String nameSpace = "data:container:yang";
         assertEquals(nameSpace, compNode.getNodeType().getNamespace().toString());
 
+        verifyNullAndEmptyStringSingleNode(compNode, nameSpace);
         verifyCommonPartAOfXml(compNode, "", nameSpace);
     }
 
+    private void verifyNullAndEmptyStringSingleNode(CompositeNode compNode, String nameSpace) {
+        assertEquals("cont", compNode.getNodeType().getLocalName());
+
+        SimpleNode<?> lf2 = null;
+        SimpleNode<?> lf3 = null;
+        int found = 0;
+        for (Node<?> child : compNode.getChildren()) {
+            if (found == 0x3)
+                break;
+            if (child instanceof SimpleNode<?>) {
+                SimpleNode<?> childSimple = (SimpleNode<?>) child;
+                if (childSimple.getNodeType().getLocalName().equals("lf3")) {
+                    lf3 = childSimple;
+                    found = found | (1 << 0);
+                } else if (childSimple.getNodeType().getLocalName().equals("lf2")) {
+                    lf2 = childSimple;
+                    found = found | (1 << 1);
+                }
+            }
+            assertEquals(nameSpace, child.getNodeType().getNamespace().toString());
+        }
+
+        assertEquals("", lf2.getValue());
+        assertEquals(null, lf3.getValue());
+    }
+
     @Test
     public void testXmlDataList() {
         CompositeNode compNode = compositeContainerFromXml("/xml-to-composite-node/data-list.xml", false);
index 1d8d7495f9dfabae21bdddb737401032af34724b..bc941b997e35dd63c8a3250cb52e8ccf66e27314 100644 (file)
@@ -13,9 +13,7 @@ import java.util.*;
 import java.util.concurrent.Future;
 
 import javax.ws.rs.WebApplicationException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.*;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.*;
 import javax.xml.transform.dom.DOMSource;
@@ -24,8 +22,7 @@ import javax.xml.transform.stream.StreamResult;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.restconf.impl.*;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.*;
 import org.opendaylight.yangtools.yang.data.api.*;
 import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
 import org.opendaylight.yangtools.yang.model.api.*;
@@ -99,7 +96,7 @@ final class TestUtils {
         }
         return (CompositeNode) dataTree;
     }
-    
+
     public static Document loadDocumentFrom(InputStream inputStream) {
         try {
             DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
@@ -135,6 +132,11 @@ final class TestUtils {
     }
 
     static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath, String outputPath) {
+        return convertCompositeNodeDataAndYangToJson(compositeNode, yangPath, outputPath, null, null);
+    }
+
+    static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath,
+            String outputPath, String searchedModuleName, String searchedDataSchemaName) {
         String jsonResult = null;
         Set<Module> modules = null;
 
@@ -145,30 +147,54 @@ final class TestUtils {
         }
         assertNotNull("modules can't be null.", modules);
 
+        Module module = null;
+        if (searchedModuleName != null) {
+            for (Module m : modules) {
+                if (m.getName().equals(searchedModuleName)) {
+                    module = m;
+                    break;
+                }
+            }
+        } else if (modules.size() == 1) {
+            module = modules.iterator().next();
+        }
+        assertNotNull("Module is missing", module);
+
         assertNotNull("Composite node can't be null", compositeNode);
 
         StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
-        for (Module module : modules) {
-            ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
-            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
-                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
-                try {
-                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
-                } catch (WebApplicationException | IOException e) {
-                    e.printStackTrace();
+        ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+        DataSchemaNode dataSchemaNode = null;
+        if (searchedDataSchemaName != null) {
+            for (DataSchemaNode dsn : module.getChildNodes()) {
+                if (dsn.getQName().getLocalName().equals(searchedDataSchemaName)) {
+                    dataSchemaNode = dsn;
                 }
-                assertFalse(
-                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
-                        byteArrayOS.toString().isEmpty());
-            }
-            jsonResult = byteArrayOS.toString();
-            try {
-                outputToFile(byteArrayOS, outputPath);
-            } catch (IOException e) {
-                System.out.println("Output file wasn't cloased sucessfuly.");
             }
+        } else if (module.getChildNodes().size() == 1) {
+            dataSchemaNode = module.getChildNodes().iterator().next();
+        }
+        assertNotNull(dataSchemaNode);
+        // SchemaContextUtil.
+
+        ControllerContext controllerContext = ControllerContext.getInstance();
+        controllerContext.setSchemas(loadSchemaContext(modules));
+        StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+        try {
+            structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+        } catch (WebApplicationException | IOException e) {
+            e.printStackTrace();
+        }
+        assertFalse("Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+                byteArrayOS.toString().isEmpty());
 
+        jsonResult = byteArrayOS.toString();
+        try {
+            outputToFile(byteArrayOS, outputPath);
+        } catch (IOException e) {
+            System.out.println("Output file wasn't cloased sucessfuly.");
         }
+
         return jsonResult;
     }
 
@@ -296,7 +322,8 @@ final class TestUtils {
         RpcResult<TransactionStatus> rpcResult = DummyRpcResult.builder().result(TransactionStatus.COMMITED).build();
         Future<RpcResult<TransactionStatus>> future = DummyFuture.builder().rpcResult(rpcResult).build();
         when(controllerContext.toInstanceIdentifier(any(String.class))).thenReturn(instIdAndSchema);
-        when(broker.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(future);
+        when(broker.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(
+                future);
 
         restconf.setControllerContext(controllerContext);
         restconf.setBroker(broker);
@@ -320,15 +347,15 @@ final class TestUtils {
         if (modules.size() < 1) {
             return null;
         }
-        
-        Module moduleRes = null;        
+
+        Module moduleRes = null;
         if (modules.size() > 1) {
             if (moduleName == null) {
                 return null;
             } else {
-                for (Module module: modules) {
+                for (Module module : modules) {
                     if (module.getName().equals(moduleName)) {
-                        moduleRes = module; 
+                        moduleRes = module;
                     }
                 }
                 if (moduleRes == null) {
@@ -338,7 +365,7 @@ final class TestUtils {
         } else {
             moduleRes = modules.iterator().next();
         }
-        
+
         if (moduleRes.getChildNodes() == null) {
             return null;
         }
index f88a335f18c9ac37927f34e973ab469ebaa0315c..69de9f86c1defa491003d13db1a4825183deb521 100644 (file)
@@ -18,10 +18,6 @@ public class ToJsonBasicDataTypesTest {
     @Test
     public void simpleYangDataTest() {
         String jsonOutput;
-        // jsonOutput =
-        // TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
-        // false);
-
         jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
                 TestUtils.loadCompositeNode("/yang-to-json-conversion/simple-data-types/xml/data.xml"),
                 "/yang-to-json-conversion/simple-data-types", "/yang-to-json-conversion/simple-data-types/xml");
@@ -73,7 +69,7 @@ public class ToJsonBasicDataTypesTest {
         // boolean lfref1Checked = false;
         boolean lfemptyChecked = false;
         boolean lfstr1Checked = false;
-        
+
         while (jReader.hasNext()) {
             String keyName = jReader.nextName();
             JsonToken peek = null;
@@ -148,10 +144,8 @@ public class ToJsonBasicDataTypesTest {
                 jReader.nextNull();
                 jReader.endArray();
                 lfemptyChecked = true;
-                // TODO: test will be implemented when functionality will be
-                // implemented
-            } else if (keyName.equals("lflstunion")) {
-                jReader.skipValue();
+            } else if (keyName.startsWith("lfunion")) {
+                checkLfUnion(jReader, keyName, peek);
             } else {
                 assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
             }
@@ -180,4 +174,44 @@ public class ToJsonBasicDataTypesTest {
         jReader.endObject();
 
     }
+
+    private void checkLfUnion(JsonReader jReader, String keyName, JsonToken peek) throws IOException {
+        if (keyName.equals("lfunion1")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion2")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion3")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            jReader.nextInt();
+        } else if (keyName.equals("lfunion4")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
+            jReader.nextBoolean();
+        } else if (keyName.equals("lfunion5")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion6")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion7")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion8")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion9")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion10")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.STRING, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion11")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.NUMBER, peek);
+            jReader.nextString();
+        } else if (keyName.equals("lfunion12")) {
+            assertEquals("Key " + keyName + " has incorrect type", JsonToken.BOOLEAN, peek);
+            jReader.nextBoolean();
+        }
+    }
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonWithAugmentTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ToJsonWithAugmentTest.java
new file mode 100644 (file)
index 0000000..994916d
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class ToJsonWithAugmentTest {
+
+    /**
+     * Test of json output when as input are specified composite node with empty
+     * data + YANG file
+     */
+    @Test
+    public void augmentedElementsToJson() {
+        String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
+                TestUtils.loadCompositeNode("/yang-to-json-conversion/augmentation/xml/data.xml"),
+                "/yang-to-json-conversion/augmentation", "/yang-to-json-conversion/augmentation/xml", "yang", "cont");
+
+        assertTrue(jsonOutput.contains("\"augment-leaf:lf2\": \"lf2\""));
+        assertTrue(jsonOutput.contains("\"augment-container:cont1\": {"));
+        assertTrue(jsonOutput.contains("\"augment-container:lf11\": \"lf11\""));
+        assertTrue(jsonOutput.contains("\"augment-list:lst1\": ["));
+        assertTrue(jsonOutput.contains("\"augment-list:lf11\": \"lf1_1\""));
+        assertTrue(jsonOutput.contains("\"augment-list:lf11\": \"lf1_2\""));
+        assertTrue(jsonOutput.contains("\"augment-leaflist:lflst1\": ["));
+    }
+}
index 7b63c5fd9422e5bb3abd0060be1ba57dc9643389..4336ac8a8325b14ab883834a7e9b91a0a6fb7655 100644 (file)
@@ -29,12 +29,12 @@ import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.rest.api.Draft01;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.MediaTypes;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -49,7 +49,8 @@ public class XmlProvidersTest extends JerseyTest {
     private static ControllerContext controllerContext;
     private static BrokerFacade brokerFacade;
     private static RestconfImpl restconfImpl;
-    private static final MediaType MEDIA_TYPE = new MediaType("application", "vnd.yang.api+xml");
+    private static final MediaType MEDIA_TYPE = new MediaType("application", "vnd.yang.data+xml");
+    private static final MediaType MEDIA_TYPE_DRAFT02 = new MediaType("application", "yang.data+xml");
 
     @BeforeClass
     public static void init() throws FileNotFoundException {
@@ -87,11 +88,11 @@ public class XmlProvidersTest extends JerseyTest {
     public void testBadFormatXmlToCompositeNodeProvider() throws UnsupportedEncodingException, URISyntaxException {
         String uri = createUri("/operations/", "ietf-interfaces:interfaces/interface/eth0");
         
-        Response response = target(uri).request(MediaTypes.API + RestconfService.XML).post(
+        Response response = target(uri).request(Draft01.MediaTypes.DATA + RestconfService.XML).post(
                 Entity.entity("<SimpleNode/>", MEDIA_TYPE));
         assertEquals(400, response.getStatus());
         
-        response = target(uri).request(MediaTypes.API + RestconfService.XML).post(
+        response = target(uri).request(Draft01.MediaTypes.DATA + RestconfService.XML).post(
                 Entity.entity("<SimpleNode>", MEDIA_TYPE));
         assertEquals(400, response.getStatus());
     }
@@ -102,59 +103,69 @@ public class XmlProvidersTest extends JerseyTest {
         
         when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(null);
         
-        Response response = target(uri).request(MediaTypes.API+RestconfService.XML).get();
+        Response response = target(uri).request(Draft01.MediaTypes.DATA+RestconfService.XML).get();
         assertEquals(404, response.getStatus());
     }
     
+    @Test
+    public void testXmlToCompositeNode400() throws UnsupportedEncodingException, URISyntaxException {
+        String uri = createUri("/datastore/", "simple-nodes:user/name");
+        
+        when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(null);
+        
+        Response response = target(uri).request(Draft01.MediaTypes.DATA+RestconfService.XML).get();
+        assertEquals(400, response.getStatus());
+    }
+    
     @Test
     public void testRpcResultCommitedToStatusCodes() throws UnsupportedEncodingException {
         InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
         String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream));
-        Entity<String> entity = Entity.entity(xml, MEDIA_TYPE);
+        Entity<String> entity = Entity.entity(xml, MEDIA_TYPE_DRAFT02);
         RpcResult<TransactionStatus> rpcResult = DummyRpcResult.builder().result(TransactionStatus.COMMITED).build();
         Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
         when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
         when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
         
         String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
-        Response response = target(uri).request(MEDIA_TYPE).put(entity);
-        assertEquals(200, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE).post(entity);
+        Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
         assertEquals(204, response.getStatus());
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+        assertEquals(200, response.getStatus());
         
         uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
-        response = target(uri).request(MEDIA_TYPE).put(entity);
-        assertEquals(200, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE).post(entity);
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
         assertEquals(204, response.getStatus());
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+        assertEquals(200, response.getStatus());
         
         uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
         response = target(uri).request(MEDIA_TYPE).put(entity);
-        assertEquals(200, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE).post(entity);
         assertEquals(204, response.getStatus());
+        response = target(uri).request(MEDIA_TYPE).post(entity);
+        assertEquals(200, response.getStatus());
     }
     
     @Test
     public void testRpcResultOtherToStatusCodes() throws UnsupportedEncodingException {
         InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
         String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream));
-        Entity<String> entity = Entity.entity(xml, MEDIA_TYPE);
+        Entity<String> entity = Entity.entity(xml, MEDIA_TYPE_DRAFT02);
         RpcResult<TransactionStatus> rpcResult = DummyRpcResult.builder().result(TransactionStatus.FAILED).build();
         Future<RpcResult<TransactionStatus>> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
         when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
         when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture);
         
         String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
-        Response response = target(uri).request(MEDIA_TYPE).put(entity);
+        Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
         assertEquals(500, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE).post(entity);
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
         assertEquals(500, response.getStatus());
         
         uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
-        response = target(uri).request(MEDIA_TYPE).put(entity);
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
         assertEquals(500, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE).post(entity);
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
         assertEquals(500, response.getStatus());
         
         uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
index 7c17bf9fdf3b240290595fecb734c33db87b7552..b038eb193ccbc882c2e0c218a27e4531a75e2342 100644 (file)
@@ -2,13 +2,22 @@ module data-container-yang {
   namespace "data:container:yang";  
 
   prefix "dtconyg";
-  revision 2013-11-19 {    
+       revision 2013-11-19 {    
   }
   
   container cont {
        leaf lf1 {
                type string;
        }
+       
+       leaf lf2 {
+               type string;
+       }
+       
+       leaf lf3 {
+               type empty;
+       }
+       
        leaf-list lflst1 {
                type string;
        }
index 0c60fbcff3903fb64ab3fc8165758948f546d107..ce97dd1715c51e8f96b54ca90da5a4d9f6d88ef7 100644 (file)
@@ -1,5 +1,7 @@
 <cont>
        <lf1>str0</lf1>
+       <lf2></lf2>
+       <lf3/>
        <lflst1>121</lflst1>
        <lflst1>131</lflst1>
        <lflst1>str1</lflst1>
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-container.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-container.yang
new file mode 100644 (file)
index 0000000..7efe4f7
--- /dev/null
@@ -0,0 +1,22 @@
+module augment-container {
+  namespace "ns:augment:container";  
+  prefix "augcont";
+
+  
+  import yang {prefix yng; revision-date 2013-11-26;}  
+
+
+  revision "2013-11-26" {    
+  }
+  
+       augment "/yng:cont" {
+               container cont1 {
+                       leaf lf11 {
+                               type string;
+                       }
+               }
+       }
+       
+
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaf.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaf.yang
new file mode 100644 (file)
index 0000000..248d3bb
--- /dev/null
@@ -0,0 +1,18 @@
+module augment-leaf {
+  namespace "ns:augment:leaf";  
+  prefix "auglf";
+
+  
+  import yang {prefix yng; revision-date 2013-11-26;}  
+
+
+  revision "2013-11-26" {    
+  }
+  
+       augment "/yng:cont" {
+               leaf lf2 {
+                       type string;
+               }
+       }
+       
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaflist.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-leaflist.yang
new file mode 100644 (file)
index 0000000..1f4b937
--- /dev/null
@@ -0,0 +1,20 @@
+module augment-leaflist {
+  namespace "ns:augment:leaflist";  
+  prefix "auglflst";
+
+  
+  import yang {prefix yng; revision-date 2013-11-26;}  
+
+
+  revision "2013-11-26" {    
+  }
+  
+       augment "/yng:cont" {
+               leaf-list lflst1 {
+                       type string;
+               }
+       }
+       
+
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-list.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/augment-list.yang
new file mode 100644 (file)
index 0000000..a35a87e
--- /dev/null
@@ -0,0 +1,22 @@
+module augment-list {
+  namespace "ns:augment:list";  
+  prefix "auglst";
+
+  
+  import yang {prefix yng; revision-date 2013-11-26;}  
+
+
+  revision "2013-11-26" {    
+  }
+  
+       augment "/yng:cont" {
+               list lst1 {
+                       leaf lf11 {
+                               type string;
+                       }
+               }
+       }
+       
+
+         
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/xml/data.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/xml/data.xml
new file mode 100644 (file)
index 0000000..08cdb34
--- /dev/null
@@ -0,0 +1,16 @@
+<cont>
+       <lf1>lf1</lf1>
+       <lf2>lf2</lf2>
+       <cont1>
+               <lf11>lf11</lf11>
+       </cont1>
+       <lst1>
+               <lf11>lf1_1</lf11>
+       </lst1>
+       <lst1>
+               <lf11>lf1_2</lf11>
+       </lst1>
+       <lflst1>lflst1_1</lflst1>
+       <lflst1>lflst1_2</lflst1>
+       <lflst1>lflst1_3</lflst1>
+</cont>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/yang.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/augmentation/yang.yang
new file mode 100644 (file)
index 0000000..aeb9737
--- /dev/null
@@ -0,0 +1,17 @@
+module yang {
+  namespace "ns:yang";  
+
+  prefix "yng";
+  revision 2013-11-26 {    
+  }
+  
+       container cont {
+               leaf lf1 {
+                       type string;
+               }
+               
+       }
+       
+
+         
+}
\ No newline at end of file
index 010d3b1c2b374c1a9002877700bac6787ea6b676..759b3ecf71cd564a8702bb694f7b9177748b8c30 100644 (file)
@@ -5,6 +5,45 @@ module simple-data-types {
   revision 2013-11-12 {    
   }
   
+  typedef tpdfempty {
+       type empty;
+  }
+  
+  typedef tpdfbit {
+       type bits {
+               bit b1;
+               bit b2;
+               bit b3;
+       }
+  }
+  
+  typedef tpdfun4 {
+       type boolean;
+  }
+  
+  typedef tpdfun3 {
+       type union {
+               type tpdfbit;
+               type tpdfempty;
+       }
+  }  
+  
+  typedef tpdfun2 {
+       type union {
+               type tpdfun3;
+               type tpdfun4;
+       }
+  }
+  
+  typedef tpdfun1 {
+       type union {
+               type uint8;
+               type decimal64 {
+                       fraction-digits 2;
+               }
+       }
+  }
+  
   container cont {
          leaf lfnint8Min {
                type int8; 
@@ -125,12 +164,87 @@ module simple-data-types {
        type empty;
     }
     
-    leaf-list lflstunion {
+    leaf lfunion1 {
        type union {
                type uint16;
                type string;
        }
     }
+    leaf lfunion2 {
+       type union {
+               type decimal64 {
+                               fraction-digits 2;              
+               }
+               type string;
+       }
+    }
+    
+    leaf lfunion3 {
+       type union {
+               type empty;
+               type string;
+       }
+    }
+    
+    leaf lfunion4 {
+       type union {
+               type boolean;
+               type string;
+       }
+    }
+    
+    leaf lfunion5 {
+       type union {
+               type uint16;
+               type string;
+       }
+    }
+    
+    leaf lfunion6 {
+       type union {
+               type uint16;
+               type empty;
+       }
+    }
+    
+    leaf lfunion7 {
+               type tpdfun3;
+    }
+    
+    leaf lfunion8 {
+       type union {
+               type uint16;
+               type string;
+       }
+    }
+    
+    leaf lfunion9 {
+       type union {
+               type uint16;
+               type boolean;                   
+       }
+    }
+    
+    leaf lfunion10 {
+       type union {
+               type bits {
+                       bit bt1;
+                       bit bt2;
+               }
+               type boolean;                   
+       }
+    }
+    
+    leaf lfunion11 {
+               type union {
+                       type tpdfun1;
+                       type tpdfun2;
+               }
+    }
+    
+    leaf lfunion12 {
+               type tpdfun2;
+    }
          
          
   }
index df00ca917e7d16f1e5f8a65bdaec9f10671cecc8..0d31e9037a763b3732274da5eddc2512a8c8ecb4 100644 (file)
        <lfbits>bit3</lfbits>   
        <lfbinary>AAaacdabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%%-#^</lfbinary>
        <lfempty></lfempty>
-       <lflstunion>324</lflstunion>
-       <lflstunion>33.3</lflstunion>
-       <lflstunion>lfunion</lflstunion>
-       <lflstunion>true</lflstunion>
+       <lfunion1>324</lfunion1>
+       <lfunion2>33.3</lfunion2>
+       <lfunion3>55</lfunion3>
+       <lfunion4>true</lfunion4>
+       <lfunion5>true</lfunion5>
+       <lfunion6>false</lfunion6>
+       <lfunion7></lfunion7>
+       <lfunion8></lfunion8>
+       <lfunion9></lfunion9>
+       <lfunion10>bt1</lfunion10>
+       <lfunion11>33</lfunion11>
+       <lfunion12>false</lfunion12>
 </cont>
\ No newline at end of file
index 7cbd2314b60265e04626ba4d2409a4f2912be559..521de7e394ee69fd3d5dfdda4bf8f546a1b513c0 100644 (file)
@@ -28,6 +28,7 @@ public class StatisticsManagerActivator extends AbstractBindingAwareProvider {
     @Override
     public void onSessionInitiated(ProviderContext session) {
         
+        pSession = session;
         DataProviderService dps = session.<DataProviderService>getSALService(DataProviderService.class);
         StatisticsManagerActivator.statsProvider.setDataService(dps);
         NotificationProviderService nps = session.<NotificationProviderService>getSALService(NotificationProviderService.class);
index 5218d051fa2cdb40ec9fa47f58114abf5c334dc6..d1ab3515035dfb0b5597c263c5f23ac29656d659 100644 (file)
@@ -100,8 +100,6 @@ public class StatisticsProvider implements AutoCloseable {
             public void run() {
                 while(true){
                     try {
-                        spLogger.info("Statistics requester thread started with timer interval : {}",5000);
-                        
                         statsRequestSender();
                         
                         Thread.sleep(5000);
@@ -111,6 +109,11 @@ public class StatisticsProvider implements AutoCloseable {
                 }
             }
         });
+        
+        spLogger.debug("Statistics requester thread started with timer interval : {}",5000);
+        
+        statisticsRequesterThread.start();
+        
         spLogger.info("Statistics Provider started.");
     }
     
@@ -124,6 +127,9 @@ public class StatisticsProvider implements AutoCloseable {
         
         //Need to call API to receive all the nodes connected to controller.
         List<Node> targetNodes = getAllConnectedNodes();
+        
+        if(targetNodes == null)
+            return;
 
         for (Node targetNode : targetNodes){
             spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
@@ -212,6 +218,9 @@ public class StatisticsProvider implements AutoCloseable {
     private List<Node> getAllConnectedNodes(){
         
         Nodes nodes = (Nodes) dps.readOperationalData(nodesIdentifier);
+        if(nodes == null)
+            return null;
+        
         spLogger.info("Number of connected nodes : {}",nodes.getNode().size());
         return nodes.getNode();
     }
index 23ba8aaea41e5866fc1934290bfd17f6154aadd9..41ae52b3bf0ff5da3cfb3adcffb6ccfbeb4ac491 100644 (file)
@@ -21,7 +21,6 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
-import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
 import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
@@ -61,9 +60,6 @@ public class ServiceProviderController {
     @Inject
     DataBrokerService dataBroker;
 
-    @Inject
-    NetconfDeviceManager netconfManager;
-
     @Test
     public void properInitialized() throws Exception {
 
@@ -72,8 +68,6 @@ public class ServiceProviderController {
         InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
                 .nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
 
-        netconfManager.netconfNodeAdded(path, new InetSocketAddress("127.0.0.1", 8383));
-
         
         InstanceIdentifier mountPointPath = path;
         
diff --git a/opendaylight/md-sal/topology-manager/pom.xml b/opendaylight/md-sal/topology-manager/pom.xml
new file mode 100644 (file)
index 0000000..6e50f9c
--- /dev/null
@@ -0,0 +1,75 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.opendaylight.controller.md</groupId>
+    <artifactId>topology-manager</artifactId>
+    <packaging>bundle</packaging>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-inventory</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-topology-view</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.controller.md.inventory.manager.InventoryActivator</Bundle-Activator>
+                        <Private-Package>org.opendaylight.controller.md.inventory.manager</Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableNodeMapping.xtend b/opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableNodeMapping.xtend
new file mode 100644 (file)
index 0000000..46f5d2b
--- /dev/null
@@ -0,0 +1,45 @@
+package org.opendaylight.md.controller.topology.manager
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnector
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointBuilder
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId
+
+class FlowCapableNodeMapping {
+
+    static def NodeKey getNodeKey(NodeRef ref) {
+        (ref?.value?.path?.get(1) as IdentifiableItem<Node,NodeKey>).key
+    }
+
+    static def NodeKey getNodeKey(NodeConnectorRef ref) {
+        (ref?.value?.path?.get(1) as IdentifiableItem<Node,NodeKey>).key
+    }
+
+    static def NodeConnectorKey getNodeConnectorKey(NodeConnectorRef ref) {
+        (ref?.value?.path?.get(2) as IdentifiableItem<NodeConnector,NodeConnectorKey>).key
+    }
+
+    static def TerminationPoint toTerminationPoint(NodeConnectorUpdated updated) {
+        val it = new TerminationPointBuilder
+        key = new TerminationPointKey(new TpId(updated.id));
+        return it.build()
+    }
+
+    static def NodeId toToplogyNodeId(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nodeId) {
+        return new NodeId(nodeId);
+    }
+
+    static def toTerminationPointId(NodeConnectorId id) {
+        return new TpId(id);
+    }
+}
diff --git a/opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableTopologyExporter.xtend b/opendaylight/md-sal/topology-manager/src/main/java/org/opendaylight/md/controller/topology/manager/FlowCapableTopologyExporter.xtend
new file mode 100644 (file)
index 0000000..fb129e4
--- /dev/null
@@ -0,0 +1,132 @@
+package org.opendaylight.md.controller.topology.manager
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryListener
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkDiscovered
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkOverutilized
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkRemoved
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkUtilizationNormal
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import static extension org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.*
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
+import com.google.common.collect.FluentIterable
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link
+
+class FlowCapableTopologyExporter implements //
+FlowTopologyDiscoveryListener, //
+OpendaylightInventoryListener //
+{
+
+    var TopologyKey topology;
+
+    @Property
+    var DataProviderService dataService;
+
+    override onNodeRemoved(NodeRemoved notification) {
+        val invNodeKey = notification.nodeRef.nodeKey
+        val tpNodeId = invNodeKey.id.toToplogyNodeId()
+        val tpNodeInstance = notification.nodeRef.toNodeIdentifier()
+
+        val it = dataService.beginTransaction
+        removeRuntimeData(tpNodeInstance);
+        removeAffectedLinks(tpNodeId)
+        commit()
+
+    }
+
+    override onNodeUpdated(NodeUpdated notification) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override onNodeConnectorRemoved(NodeConnectorRemoved notification) {
+        val tpRef = notification.nodeConnectorRef.toTerminationPointIdentifier();
+        val it = dataService.beginTransaction
+        removeRuntimeData(tpRef);
+        commit()
+
+    }
+
+    override onNodeConnectorUpdated(NodeConnectorUpdated notification) {
+        val nodeId = notification.nodeConnectorRef.nodeKey.id.toToplogyNodeId();
+        val TerminationPoint point = notification.toTerminationPoint();
+        val path = tpPath(nodeId, point.key.tpId);
+
+        val it = dataService.beginTransaction
+        putRuntimeData(path, point);
+        commit()
+    }
+
+    override onLinkDiscovered(LinkDiscovered notification) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override onLinkOverutilized(LinkOverutilized notification) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override onLinkRemoved(LinkRemoved notification) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    override onLinkUtilizationNormal(LinkUtilizationNormal notification) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    def InstanceIdentifier<Node> toNodeIdentifier(NodeRef ref) {
+        val invNodeKey = ref.nodeKey
+
+        val nodeKey = new NodeKey(invNodeKey.id.toToplogyNodeId);
+        return InstanceIdentifier.builder.node(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
+            toInstance;
+    }
+
+    def InstanceIdentifier<TerminationPoint> toTerminationPointIdentifier(NodeConnectorRef ref) {
+        val invNodeKey = ref.nodeKey
+        val invNodeConnectorKey = ref.nodeConnectorKey
+        return tpPath(invNodeKey.id.toToplogyNodeId(), invNodeConnectorKey.id.toTerminationPointId())
+    }
+
+    private def void removeAffectedLinks(DataModificationTransaction transaction, NodeId id) {
+        val reader = TypeSafeDataReader.forReader(transaction)
+        val topologyPath = InstanceIdentifier.builder().node(NetworkTopology).child(Topology, topology).toInstance;
+        val topologyData = reader.readOperationalData(topologyPath);
+        if (topologyData === null) {
+            return;
+        }
+        val affectedLinkInstances = FluentIterable.from(topologyData.link).filter[
+            source.sourceNode == id || destination.destNode == id].transform [
+            //
+            InstanceIdentifier.builder().node(NetworkTopology).child(Topology, topology).child(Link, key).toInstance
+        //
+        ]
+        for(affectedLink : affectedLinkInstances) {
+            transaction.removeRuntimeData(affectedLink);
+        }
+    }
+    
+    private def InstanceIdentifier<TerminationPoint> tpPath(NodeId nodeId, TpId tpId) {
+        val nodeKey = new NodeKey(nodeId);
+        val tpKey = new TerminationPointKey(tpId)
+        return InstanceIdentifier.builder.node(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
+            child(TerminationPoint, tpKey).toInstance;
+    }
+}
index 556541ab22009d6f5cfb5aee439d453e6320b3ac..ef286ac862912ea0bf58f8250bf1264d8ddd3f6d 100644 (file)
@@ -24,8 +24,9 @@ public class Rpcs {
     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(),
+        String moduleName = id.getModuleName();
+        ModuleRpcs rpcMapping = modules.get(moduleName);
+        Preconditions.checkState(rpcMapping != null, "No module %s found for namespace %s", moduleName,
                 id.getNamespace());
 
         return rpcMapping;
index 9d348d0985518c2595445f89c73a69e74bcb93ca..70b10d00191cd04c01e83dee8be44fd0c4db0f9d 100644 (file)
@@ -12,7 +12,6 @@ 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;
 
@@ -83,15 +82,14 @@ public class InstanceRuntime {
         }));
     }
 
-    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, Element parentElement, String namespace) {
+        return toXml(rootOn, childRbeOns, document, null, parentElement, namespace);
     }
 
     public Element toXml(ObjectName rootOn, Set<ObjectName> childRbeOns, Document document, String instanceIndex,
-            String keyName) {
-        Element xml = document.createElement(keyName == null ? XmlNetconfConstants.DATA_KEY : keyName);
+                         Element parentElement, String namespace) {
         // TODO namespace
-        xml = instanceMapping.toXml(rootOn, null, "namespace", document, xml);
+        Element xml = instanceMapping.toXml(rootOn, null, namespace, document, parentElement);
 
         if (instanceIndex != null) {
             xml.setAttribute(KEY_ATTRIBUTE_KEY, instanceIndex);
@@ -106,8 +104,11 @@ public class InstanceRuntime {
                 String runtimeInstanceIndex = objectName.getKeyProperty(childMappingEntry.getKey());
 
                 String elementName = jmxToYangChildRbeMapping.get(childMappingEntry.getKey());
-                xml.appendChild(childMappingEntry.getValue().toXml(objectName, innerChildRbeOns, document,
-                        runtimeInstanceIndex, elementName));
+
+                Element innerXml = document.createElement(elementName);
+                childMappingEntry.getValue().toXml(objectName, innerChildRbeOns, document,
+                        runtimeInstanceIndex, innerXml, namespace);
+                xml.appendChild(innerXml);
             }
         }
 
index 07da65ed19b548646234b11f8aa2a7cbb9c7e70d..4dbfba119f865980daf18ac49b3564bfddff996c 100644 (file)
@@ -8,7 +8,6 @@
 
 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;
@@ -41,31 +40,30 @@ public class ModuleRuntime {
         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);
+    public Element toXml(String namespace, String instanceName, Collection<ObjectName> runtimeBeanOns, Document document) {
+        Element moduleElement = document.createElement(XmlNetconfConstants.MODULE_KEY);
 
-        Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, moduleName);
-        root.appendChild(nameElement);
+        final String prefix = getPrefix(namespace);
+        Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlNetconfConstants.TYPE_KEY, prefix,
+                moduleName);
+        XmlUtil.addPrefixedNamespaceAttr(typeElement, prefix, namespace);
+        moduleElement.appendChild(typeElement);
 
-        for (String instanceName : instances.keySet()) {
-            Element instance = document.createElement(XmlNetconfConstants.INSTANCE_KEY);
+        Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, instanceName);
+        moduleElement.appendChild(nameElement);
 
-            Element innerNameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, instanceName);
-            instance.appendChild(innerNameElement);
+        ObjectName rootName = findRoot(runtimeBeanOns);
 
-            Collection<ObjectName> runtimeBeanOns = instances.get(instanceName);
-            ObjectName rootName = findRoot(runtimeBeanOns);
+        Set<ObjectName> childrenRuntimeBeans = Sets.newHashSet(runtimeBeanOns);
+        childrenRuntimeBeans.remove(rootName);
 
-            Set<ObjectName> childrenRuntimeBeans = Sets.newHashSet(runtimeBeanOns);
-            childrenRuntimeBeans.remove(rootName);
+        instanceRuntime.toXml(rootName, childrenRuntimeBeans, document, moduleElement, namespace);
 
-            instance.appendChild(instanceRuntime.toXml(rootName, childrenRuntimeBeans, document));
-
-            root.appendChild(instance);
-        }
+        return moduleElement;
+    }
 
-        return root;
+    private String getPrefix(String namespace) {
+        return XmlNetconfConstants.PREFIX;
     }
 
 }
index da281269e63275b3b11c55f3aa4d439784f83469..8af1e0ee90e94fe7c009eb93ece4b1f478b16d4f 100644 (file)
@@ -66,9 +66,12 @@ public class Runtime {
                 if (instanceToRbe == null)
                     continue;
 
-                ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName);
-                Element innerXml = moduleRuntime.toXml(localNamespace, instanceToRbe, document);
-                modulesElement.appendChild(innerXml);
+                for (String instanceName : instanceToRbe.keySet()) {
+                    ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName);
+                    Element innerXml = moduleRuntime.toXml(localNamespace, instanceName, instanceToRbe.get(instanceName), document);
+                    modulesElement.appendChild(innerXml);
+                }
+
             }
         }
 
index 838e5d87317fd503ba545019e93c38a8c56000a0..0f0b1227a625cd717840f2841dcb4706b270e47c 100644 (file)
@@ -33,11 +33,11 @@ public final class RuntimeRpcElementResolved {
 
     private RuntimeRpcElementResolved(String namespace, String moduleName, String instanceName, String runtimeBeanName,
             Map<String, String> additionalAttributes) {
-        this.moduleName = moduleName;
-        this.instanceName = instanceName;
+        this.moduleName = Preconditions.checkNotNull(moduleName, "Module name");
+        this.instanceName =  Preconditions.checkNotNull(instanceName, "Instance name");
         this.additionalAttributes = additionalAttributes;
-        this.namespace = namespace;
-        this.runtimeBeanName = runtimeBeanName;
+        this.namespace = Preconditions.checkNotNull(namespace, "Namespace");
+        this.runtimeBeanName = Preconditions.checkNotNull(runtimeBeanName, "Runtime bean name");
     }
 
     public String getModuleName() {
@@ -68,12 +68,22 @@ public final class RuntimeRpcElementResolved {
         return ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, additionalAttributesJavaNames);
     }
 
-    private static final String xpathPatternBlueprint = "/" + XmlNetconfConstants.DATA_KEY + "/"
-            + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "\\["
-            + XmlNetconfConstants.NAME_KEY + "='(.+)'\\]/" + XmlNetconfConstants.INSTANCE_KEY + "\\["
-            + XmlNetconfConstants.NAME_KEY + "='([^']+)'\\](.*)";
+    private static final String xpathPatternBlueprint =
+            "/" + XmlNetconfConstants.MODULES_KEY
+            + "/" + XmlNetconfConstants.MODULE_KEY
+            + "\\["
+
+            + "(?<key1>type|name)"
+            + "='(?<value1>[^']+)'"
+            + "( and |\\]\\[)"
+            + "(?<key2>type|name)"
+            + "='(?<value2>[^']+)'"
+
+            + "\\]"
+            + "(?<additional>.*)";
+
     private static final Pattern xpathPattern = Pattern.compile(xpathPatternBlueprint);
-    private static final String additionalPatternBlueprint = "(.+)\\[(.+)='(.+)'\\]";
+    private static final String additionalPatternBlueprint = "(?<additionalKey>.+)\\[(.+)='(?<additionalValue>.+)'\\]";
     private static final Pattern additionalPattern = Pattern.compile(additionalPatternBlueprint);
 
     public static RuntimeRpcElementResolved fromXpath(String xpath, String elementName, String namespace) {
@@ -82,26 +92,65 @@ public final class RuntimeRpcElementResolved {
                 "Node %s with value '%s' not in required form on rpc element %s, required format is %s",
                 RuntimeRpc.CONTEXT_INSTANCE, xpath, elementName, xpathPatternBlueprint);
 
-        String moduleName = matcher.group(1);
-        String instanceName = matcher.group(2);
-        String additionalString = matcher.group(3);
-        HashMap<String, String> additionalAttributes = Maps.<String, String> newHashMap();
-        String runtimeBeanYangName = moduleName;
-        for (String additionalKeyValue : additionalString.split("/")) {
-            if (Strings.isNullOrEmpty(additionalKeyValue))
-                continue;
-            matcher = additionalPattern.matcher(additionalKeyValue);
-            Preconditions
-                    .checkState(
-                            matcher.matches(),
-                            "Attribute %s not in required form on rpc element %s, required format for additional attributes is  %s",
-                            additionalKeyValue, elementName, additionalPatternBlueprint);
-            String name = matcher.group(1);
-            runtimeBeanYangName = name;
-            additionalAttributes.put(name, matcher.group(3));
-        }
+        PatternGroupResolver groups = new PatternGroupResolver(matcher.group("key1"), matcher.group("value1"),
+                matcher.group("key2"), matcher.group("value2"), matcher.group("additional"));
+
+        String moduleName = groups.getModuleName();
+        String instanceName = groups.getInstanceName();
+
+        HashMap<String, String> additionalAttributes = groups.getAdditionalKeys(elementName, moduleName);
 
-        return new RuntimeRpcElementResolved(namespace, moduleName, instanceName, runtimeBeanYangName,
+        return new RuntimeRpcElementResolved(namespace, moduleName, instanceName, groups.getRuntimeBeanYangName(),
                 additionalAttributes);
     }
+
+    private static final class PatternGroupResolver {
+
+        private final String key1, key2, value1, value2;
+        private final String additional;
+        private String runtimeBeanYangName;
+
+        PatternGroupResolver(String key1, String value1, String key2, String value2, String additional) {
+            this.key1 = Preconditions.checkNotNull(key1);
+            this.value1 = Preconditions.checkNotNull(value1);
+
+            this.key2 = Preconditions.checkNotNull(key2);
+            this.value2 = Preconditions.checkNotNull(value2);
+
+            this.additional = Preconditions.checkNotNull(additional);
+        }
+
+        String getModuleName() {
+            return key1.equals(XmlNetconfConstants.TYPE_KEY) ? value1 : value2;
+        }
+
+        String getInstanceName() {
+            return key1.equals(XmlNetconfConstants.NAME_KEY) ? value1 : value2;
+        }
+
+        HashMap<String, String> getAdditionalKeys(String elementName, String moduleName) {
+            HashMap<String, String> additionalAttributes = Maps.newHashMap();
+
+            runtimeBeanYangName = moduleName;
+            for (String additionalKeyValue : additional.split("/")) {
+                if (Strings.isNullOrEmpty(additionalKeyValue))
+                    continue;
+                Matcher matcher = additionalPattern.matcher(additionalKeyValue);
+                Preconditions
+                        .checkState(
+                                matcher.matches(),
+                                "Attribute %s not in required form on rpc element %s, required format for additional attributes is  %s",
+                                additionalKeyValue, elementName, additionalPatternBlueprint);
+                String name = matcher.group("additionalKey");
+                runtimeBeanYangName = name;
+                additionalAttributes.put(name, matcher.group("additionalValue"));
+            }
+            return additionalAttributes;
+        }
+
+        private String getRuntimeBeanYangName() {
+            Preconditions.checkState(runtimeBeanYangName!=null);
+            return runtimeBeanYangName;
+        }
+    }
 }
index de0ecdbf1e2a448a82c001462b3dd9db46f2aba1..296b224fffbbc2e33fccc898dd78dcd204267d46 100644 (file)
@@ -441,7 +441,9 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         Element response = get();
 
-        assertEquals(2, getElementsSize(response, "instance"));
+        System.err.println(XmlUtil.toString(response));
+
+        assertEquals(2, getElementsSize(response, "module"));
         assertEquals(2, getElementsSize(response, "asdf"));
         assertEquals(5, getElementsSize(response, "inner-running-data"));
         assertEquals(5, getElementsSize(response, "deep2"));
index 0d68e25f67071b1505b2ab4a54e836e6cfe78e2d..25d2ad6abd09943278d28262a7184649a0688f4f 100644 (file)
@@ -41,6 +41,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetSocketAddress;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -152,9 +153,11 @@ public class ConfigPersisterNotificationHandler implements NotificationListener,
 
             Thread.sleep(delay);
         }
-
-        throw new RuntimeException("Netconf server did not provide required capabilities " + expectedCaps
-                + " in time, provided capabilities " + currentCapabilities);
+        Set<String> allNotFound = new HashSet<>(expectedCaps);
+        allNotFound.removeAll(currentCapabilities);
+        logger.error("Netconf server did not provide required capabilities. Expected but not found: {}, all expected {}, current {}",
+                allNotFound, expectedCaps ,currentCapabilities);
+        throw new RuntimeException("Netconf server did not provide required capabilities. Expected but not found:" + allNotFound);
 
     }
 
index 54deb91837b002b76a7c7f80a6d01ef5ee56e9cc..11b8dc623c8a07903df1d05da46407aef1770a47 100644 (file)
@@ -121,8 +121,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         String messageAsString = XmlUtil.toString(message);
 
         try {
-            netconfOperationExecution = getNetconfOperationWithHighestPriority(
-                    message, session);
+            netconfOperationExecution = getNetconfOperationWithHighestPriority(message, session);
         } catch (IllegalArgumentException | IllegalStateException e) {
             logger.warn("Unable to handle rpc {} on session {}", messageAsString, session, e);
 
@@ -140,8 +139,29 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
             throw new NetconfDocumentedException(errorMessage, e, NetconfDocumentedException.ErrorType.application,
                     tag, NetconfDocumentedException.ErrorSeverity.error, errorInfo);
+        } catch (RuntimeException e) {
+            throw handleUnexpectedEx("Unexpected exception during netconf operation sort", e);
         }
 
+        try {
+            return executeOperationWithHighestPriority(message, netconfOperationExecution, messageAsString);
+        } catch (RuntimeException e) {
+            throw handleUnexpectedEx("Unexpected exception during netconf operation execution", e);
+        }
+    }
+
+    private NetconfDocumentedException handleUnexpectedEx(String s, Exception e) throws NetconfDocumentedException {
+        logger.error(s, e);
+
+        Map<String, String> info = Maps.newHashMap();
+        info.put(NetconfDocumentedException.ErrorSeverity.error.toString(), e.toString());
+        return new NetconfDocumentedException("Unexpected error",
+                NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.operation_failed,
+                NetconfDocumentedException.ErrorSeverity.error, info);
+    }
+
+    private Document executeOperationWithHighestPriority(Document message, NetconfOperationExecution netconfOperationExecution, String messageAsString) throws NetconfDocumentedException {
         logger.debug("Forwarding netconf message {} to {}", messageAsString,
                 netconfOperationExecution.operationWithHighestPriority);
 
index 5f6e046929b4a5183f3e4cce1932db9f61c538bd..c03254dba2bbda03677efc89c4eadd39e2024acc 100644 (file)
@@ -275,7 +275,7 @@ public class NetconfITTest extends AbstractConfigTest {
                     + "<no-arg xmlns=\""
                     + expectedNamespace
                     + "\">    "
-                    + "<context-instance>/data/modules/module[name='impl-netconf']/instance[name='instance']</context-instance>"
+                    + "<context-instance>/modules/module[type='impl-netconf'][name='instance']</context-instance>"
                     + "<arg1>argument1</arg1>" + "</no-arg>" + "</rpc>";
             final Document doc = XmlUtil.readXmlToDocument(rpc);
             final NetconfMessage message = netconfClient.sendMessage(new NetconfMessage(doc));
index b2a2ee30c815a6a0ac6b1b57f236dc0dd819d7de..413b78c5d344bae7cceec2ec6752206a4cf01a46 100644 (file)
@@ -1,6 +1,6 @@
 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <no-arg xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-        <context-instance>/data/modules/module[name='impl-netconf']/instance[name='instance']</context-instance>
+        <context-instance>/modules/module[type='impl-netconf' and name='instance']</context-instance>
         <arg1>
             testarg1
         </arg1>
index 8bc504a56e87f71c1990dcb926fe294b88e40cd0..cf15000b1a3473678d6f98906981d8ce68707444 100644 (file)
@@ -1,7 +1,7 @@
 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <noArgInner xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /data/modules/module[name='impl-netconf']/instance[name='instance2']/inner-running-data-additional[key='randomString_1003']
+            /modules/module[name='instance2'][type='impl-netconf']/inner-running-data-additional[key='randomString_1003']
         </context-instance>
     </noArgInner>
 </rpc>
index 2356398e64d232ee0abc666cb65d8c73cf6ea3c9..31f417e879dd813e558e60a2a46524100027fb32 100644 (file)
@@ -2,7 +2,7 @@
     <noArgInnerInner
             xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /data/modules/module[name='impl-netconf']/instance[name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
+            /modules/module[type='impl-netconf'][name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
         </context-instance>
 
         <arg1>
index 209c382252d81f693c525278224e1d232bc9fe6a..af0835b5dfc7216a840557f231af108a43b2edee 100644 (file)
@@ -2,7 +2,7 @@
     <leaf-list-output
             xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /data/modules/module[name='impl-netconf']/instance[name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
+            /modules/module[type='impl-netconf'][name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
         </context-instance>
     </leaf-list-output>
 </rpc>
index eecc19f2167b71a77d5c381a99bb365dd6b28ed7..582c0766dd35360c6517460ba67f0d340970c7ee 100644 (file)
@@ -20,10 +20,10 @@ import javax.xml.bind.annotation.XmlRootElement;
 import org.opendaylight.controller.containermanager.ContainerConfig;
 
 
-@XmlRootElement(name = "container-config-list")
+@XmlRootElement(name = "containerConfig-list")
 @XmlAccessorType(XmlAccessType.NONE)
 public class ContainerConfigs {
-        @XmlElement(name = "container-config")
+        @XmlElement(name = "containerConfig")
     List<ContainerConfig> containerConfig;
 
     //To satisfy JAXB
index 518fc4692f0d6e11c7a24a0f0551803791708945..fe38361cca246465bf514686b0beb872e72dd9f5 100644 (file)
@@ -114,8 +114,8 @@ public class ContainerManagerNorthbound {
      * http://localhost:8080/controller/nb/v2/containermanager/containers
      *
      * Response body in XML:
-     * &lt;container-config-list&gt;
-     *    &#x20;&#x20;&#x20;&lt;container-config&gt;
+     * &lt;containerConfig-list&gt;
+     *    &#x20;&#x20;&#x20;&lt;containerConfig&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;container&gt;black&lt;/container&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;staticVlan&gt;10&lt;/staticVlan&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;nodeConnectors&gt;OF|1@OF|00:00:00:00:00:00:00:01&lt;/nodeConnectors&gt;
@@ -124,8 +124,8 @@ public class ContainerManagerNorthbound {
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;name&gt;tcp&lt;/name&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;protocol&gt;TCP&lt;/protocol&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;/flowSpecs&gt;
-     *    &#x20;&#x20;&#x20;&#x20;&lt;/container-config&gt;
-     *    &#x20;&#x20;&#x20;&#x20;&lt;container-config&gt;
+     *    &#x20;&#x20;&#x20;&#x20;&lt;/containerConfig&gt;
+     *    &#x20;&#x20;&#x20;&#x20;&lt;containerConfig&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;container&gt;red&lt;/container&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;staticVlan&gt;20&lt;/staticVlan&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;nodeConnectors&gt;OF|1@OF|00:00:00:00:00:00:00:01&lt;/nodeConnectors&gt;
@@ -134,11 +134,11 @@ public class ContainerManagerNorthbound {
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;name&gt;udp&lt;/name&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;protocol&gt;UDP&lt;/protocol&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;/flowSpecs&gt;
-     *  &#x20;&#x20;&#x20;&#x20;&lt;/container-config&gt;
-     * &lt;/container-config-list&gt;
+     *  &#x20;&#x20;&#x20;&#x20;&lt;/containerConfig&gt;
+     * &lt;/containerConfig-list&gt;
      *
      * Response body in JSON:
-     * { "container-config" : [
+     * { "containerConfig" : [
      *     { "container" : "black",
      *       "nodeConnectors" : [
      *          "OF|1@OF|00:00:00:00:00:00:00:01", "OF|23@OF|00:00:00:00:00:00:20:21"
@@ -196,16 +196,16 @@ public class ContainerManagerNorthbound {
      * http://localhost:8080/controller/nb/v2/containermanager/container/blue
      *
      * Response body in XML:
-     * &lt;container-config&gt;
+     * &lt;containerConfig&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;container&gt;blue&lt;/container&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;staticVlan&gt;10&lt;/staticVlan&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;nodeConnectors&gt;OF|1@OF|00:00:00:00:00:00:00:01&lt;/nodeConnectors&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;nodeConnectors&gt;OF|23@OF|00:00:00:00:00:00:20:21&lt;/nodeConnectors&gt;
-     * &lt;/container-config&gt;
+     * &lt;/containerConfig&gt;
      *
      * Response body in JSON:
      * {
-     *    "container-config": [
+     *    "containerConfig": [
      *       {
      *        "container": "yellow",
      *        "staticVlan": "10",
@@ -259,11 +259,11 @@ public class ContainerManagerNorthbound {
      * http://localhost:8080/controller/nb/v2/containermanager/container/yellow
      *
      * Request body in XML:
-     * &lt;container-config&gt;
+     * &lt;containerConfig&gt;
      *   &#x20;&#x20;&#x20;&#x20;&lt;container&gt;yellow&lt;/container&gt;
      *   &#x20;&#x20;&#x20;&#x20;&lt;staticVlan&gt;10&lt;/staticVlan&gt;
      *   &#x20;&#x20;&#x20;&#x20;&lt;nodeConnectors&gt;&lt;/nodeConnectors&gt;
-     * &lt;/container-config&gt;
+     * &lt;/containerConfig&gt;
      *
      * Request body in JSON:
      * {