Merge "- Added exi capability utilities, handlers and necessary modifications - Exi...
authorEd Warnicke <eaw@cisco.com>
Fri, 8 Nov 2013 10:57:06 +0000 (10:57 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 8 Nov 2013 10:57:06 +0000 (10:57 +0000)
40 files changed:
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/DependencyResolver.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/dependencyresolver/DependencyResolverImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/ModulesHolder.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/TransactionHolder.java
opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java
opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.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/meter-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java [new file with mode: 0644]
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/YangAndXmlToJsonConversionJsonReaderTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionRegExTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java with 51% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json

index 7cac1060ba6357fd1cdd4e8bc26d4d9bf7118b52..39845454ef5ed17d108255dbf5e47f5b774ab93b 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.config.api;
 import javax.management.ObjectName;
 
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.yangtools.concepts.Identifiable;
 
 /**
  * Each new {@link org.opendaylight.controller.config.spi.Module} can receive
@@ -18,7 +19,7 @@ import org.opendaylight.controller.config.api.annotations.AbstractServiceInterfa
  *
  * @see org.opendaylight.controller.config.spi.Module
  */
-public interface DependencyResolver {
+public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
 
     /**
      * To be used during validation phase to validate serice interface of
index 343d45a236e99bd9208ff4846d13c1e0a43bc571..3f569ae324ebebe51cf0550aa74b21bbcc8d58b8 100644 (file)
@@ -138,8 +138,10 @@ class ConfigTransactionControllerImpl implements
         for (ModuleFactory moduleFactory : toBeAdded) {
             Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
             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());
                 try {
-                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null);
+                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver);
                 } catch (InstanceAlreadyExistsException e) {
                     throw new IllegalStateException(e);
                 }
@@ -179,7 +181,7 @@ class ConfigTransactionControllerImpl implements
                     "Error while copying old configuration from %s to %s",
                     oldConfigBeanInfo, moduleFactory), e);
         }
-        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo);
+        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver);
     }
 
     @Override
@@ -196,19 +198,24 @@ class ConfigTransactionControllerImpl implements
         DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
         Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext);
         return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
-                moduleFactory, null);
+                moduleFactory, null, dependencyResolver);
     }
 
     private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
             ModuleIdentifier moduleIdentifier, Module module,
             ModuleFactory moduleFactory,
-            @Nullable ModuleInternalInfo maybeOldConfigBeanInfo)
+            @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver)
             throws InstanceAlreadyExistsException {
+
         logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
         if (moduleIdentifier.equals(module.getIdentifier())==false) {
             throw new IllegalStateException("Incorrect name reported by module. Expected "
              + moduleIdentifier + ", got " + module.getIdentifier());
         }
+        if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) {
+            throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected "
+                    + moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
+        }
         DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
                 module, moduleIdentifier, transactionIdentifier,
                 readOnlyAtomicBoolean, transactionsMBeanServer,
@@ -224,8 +231,6 @@ class ConfigTransactionControllerImpl implements
                 maybeOldConfigBeanInfo, transactionModuleJMXRegistration);
 
         dependencyResolverManager.put(moduleInternalTransactionalInfo);
-        // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
-        dependencyResolverManager.getOrCreate(moduleIdentifier);
         return writableON;
     }
 
index f817b41c5f929b18f0ff3dfcd7b89003dbd2ea93..065a0f843f501cdb7e2a4230c9cc0b72caf31f3c 100644 (file)
@@ -7,15 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import static java.lang.String.format;
-
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
@@ -25,7 +16,14 @@ import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.concepts.Identifiable;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.ObjectName;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.lang.String.format;
 
 /**
  * Protect {@link org.opendaylight.controller.config.spi.Module#getInstance()}
@@ -33,7 +31,7 @@ import org.opendaylight.yangtools.concepts.Identifiable;
  * during validation. Tracks dependencies for ordering purposes.
  */
 final class DependencyResolverImpl implements DependencyResolver,
-       Identifiable<ModuleIdentifier>, Comparable<DependencyResolverImpl> {
+       Comparable<DependencyResolverImpl> {
     private final ModulesHolder modulesHolder;
     private final ModuleIdentifier name;
     private final TransactionStatus transactionStatus;
@@ -47,11 +45,6 @@ final class DependencyResolverImpl implements DependencyResolver,
         this.modulesHolder = modulesHolder;
     }
 
-    @Deprecated
-    public ModuleIdentifier getName() {
-        return name;
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -177,7 +170,7 @@ final class DependencyResolverImpl implements DependencyResolver,
         int maxDepth = 0;
         LinkedHashSet<ModuleIdentifier> chainForDetectingCycles2 = new LinkedHashSet<>(
                 chainForDetectingCycles);
-        chainForDetectingCycles2.add(impl.getName());
+        chainForDetectingCycles2.add(impl.getIdentifier());
         for (ModuleIdentifier dependencyName : impl.dependencies) {
             DependencyResolverImpl dependentDRI = manager
                     .getOrCreate(dependencyName);
index 28f2e37ec187b5aaec8c18b98b568b4f47cc6dac..dea78c8b155d9f125783232bd7c5b531e673bce0 100644 (file)
@@ -7,15 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.JmxAttribute;
@@ -26,6 +17,14 @@ import org.opendaylight.controller.config.manager.impl.TransactionStatus;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Holds information about modules being created and destroyed within this
  * transaction. Observes usage of DependencyResolver within modules to figure
@@ -80,7 +79,7 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
         List<ModuleIdentifier> result = new ArrayList<>(
                 moduleIdentifiersToDependencyResolverMap.size());
         for (DependencyResolverImpl dri : getAllSorted()) {
-            ModuleIdentifier driName = dri.getName();
+            ModuleIdentifier driName = dri.getIdentifier();
             result.add(driName);
         }
         return result;
index f70c4bf57904b72b2e29d8071f671b2ea4042af5..6bbd7875a94b1fa8a1d4dd8662b2a9cb835420ea 100644 (file)
@@ -7,18 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
@@ -28,6 +16,17 @@ import org.opendaylight.controller.config.manager.impl.ModuleInternalTransaction
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Represents modules to be committed.
  */
@@ -117,8 +116,7 @@ class ModulesHolder implements TransactionHolder {
             throws InstanceAlreadyExistsException {
         if (commitMap.containsKey(moduleIdentifier)) {
             throw new InstanceAlreadyExistsException(
-                    "There is an instance registered with name "
-                            + moduleIdentifier);
+                    "There is an instance registered with name " + moduleIdentifier);
         }
     }
 
index f81e747f620950f71a1e0a217ee52e73d4b068fb..8f05ed75ae74a64d4c45c42969ee32d235880395 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.Map;
-
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.manager.impl.CommitInfo;
@@ -18,6 +14,9 @@ import org.opendaylight.controller.config.manager.impl.ModuleInternalTransaction
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.management.InstanceAlreadyExistsException;
+import java.util.Map;
+
 interface TransactionHolder {
     CommitInfo toCommitInfo();
 
index 9b96f86c92497c70ec8c5b03c0d01aae70538224..29de77270bb6d63c5f791f0ad70cce2eda6d9250 100644 (file)
             <Import-Package>
               org.opendaylight.controller.sal.binding.api,
               org.opendaylight.controller.sal.binding.api.data,
-              org.opendaylight.controller.md.sal.common.api.data,              
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow,
+              org.opendaylight.controller.md.sal.common.api.data, 
+              org.opendaylight.controller.sal.utils, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket,
               org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
+              org.opendaylight.controller.clustering.services, org.opendaylight.controller.sal.core, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction,
+              org.opendaylight.controller.switchmanager, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024,
               org.opendaylight.yangtools.concepts,              
               org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819,
               org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819,
index ae488b689f4788c95d017a07c53cb0ddecb9f0fd..e48e03867c89025fc62babeab7548a8947a27712 100644 (file)
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
 
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationService;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class FRMConsumerImpl extends AbstractBindingAwareProvider {
+public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider{
        protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class);
        private static ProviderContext p_session;
     private static DataBrokerService dataBrokerService;         
@@ -28,11 +35,21 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
        private GroupConsumerImpl groupImplRef;
        private static DataProviderService dataProviderService;  
 
+       private static IClusterContainerServices clusterContainerService = null;
+       private static ISwitchManager switchManager;
+       private static IContainer container;
+       
        @Override
     public void onSessionInitiated(ProviderContext session) {
        
         FRMConsumerImpl.p_session = session;
         
+        if (!getDependentModule()) {
+            logger.error("Unable to fetch handlers for dependent modules");
+            System.out.println("Unable to fetch handlers for dependent modules");
+            return;
+        }
+        
         if (null != session) {
                notificationService = session.getSALService(NotificationService.class);
                
@@ -44,7 +61,8 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
                                
                                if (null != dataProviderService) {
                                        flowImplRef = new FlowConsumerImpl();
-                                       groupImplRef = new GroupConsumerImpl();
+                       //              groupImplRef = new GroupConsumerImpl();
+                                       registerWithOSGIConsole();
                                }
                                else {
                                        logger.error("Data Provider Service is down or NULL. " +
@@ -68,18 +86,85 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
                System.out.println("Consumer session is NULL. Please check if provider is registered");
         }
   
+    }
+       
+       public static IClusterContainerServices getClusterContainerService() {
+        return clusterContainerService;
+    }
+
+    public static void setClusterContainerService(
+            IClusterContainerServices clusterContainerService) {
+        FRMConsumerImpl.clusterContainerService = clusterContainerService;
+    }
+
+    public static ISwitchManager getSwitchManager() {
+        return switchManager;
+    }
+
+    public static void setSwitchManager(ISwitchManager switchManager) {
+        FRMConsumerImpl.switchManager = switchManager;
+    }
+
+    public static IContainer getContainer() {
+        return container;
     }
 
-       public static DataProviderService getDataProviderService() {
+    public static void setContainer(IContainer container) {
+        FRMConsumerImpl.container = container;
+    }
+
+    private void registerWithOSGIConsole() {
+        BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+        bundleContext.registerService(CommandProvider.class.getName(), this, null);
+    }
+       
+       private boolean getDependentModule() {
+           do {
+        clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(IClusterContainerServices.class, this);
+        try {
+            Thread.sleep(4);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+           } while(clusterContainerService == null);
+           
+           do {
+               
+           
+        container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+        try {
+            Thread.sleep(5);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+           } while (container == null);
+           
+           do {
+               switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, container.getName(), this);
+               try {
+                   Thread.sleep(5);
+               } catch (InterruptedException e) {
+                   // TODO Auto-generated catch block
+                   e.printStackTrace();
+               }
+           } while(null == switchManager);
+        return true;
+       }
+
+       
+
+    public static DataProviderService getDataProviderService() {
                return dataProviderService;
        }
 
        public FlowConsumerImpl getFlowImplRef() {
-               return flowImplRef;
+           return flowImplRef;
        }
 
        public GroupConsumerImpl getGroupImplRef() {
-                       return groupImplRef;
+           return groupImplRef;
        }
         
        public static ProviderContext getProviderSession() {
@@ -93,6 +178,15 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
        public static DataBrokerService getDataBrokerService() {
                return dataBrokerService;
        }
+       
+       /*
+     * OSGI COMMANDS
+     */
+    @Override
+    public String getHelp() {
+        StringBuffer help = new StringBuffer();
+        return help.toString();
+    }
 
 }
        
diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java
new file mode 100644 (file)
index 0000000..df34d19
--- /dev/null
@@ -0,0 +1,33 @@
+package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket.Actions;
+
+public class FRMUtil {
+    private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+    public enum operation {ADD, DELETE, UPDATE, GET};
+    
+    
+    public static boolean isNameValid(String name) {
+    
+        //  Name validation 
+        if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
+            return false;
+        }
+        return true;
+        
+    }
+    
+    public static boolean areActionsValid(Actions actions) {
+     //   List<Action> actionList;
+       // Action actionRef;
+      //  if (null != actions && null != actions.getAction()) {
+       //     actionList = actions.getAction();
+            
+
+               
+       // }
+        
+        return true;
+    }
+}
index a6a3c71325ed7e644918527ef600fbe739f7faee..59c7e043de823a83a4f6b0318c2d25650bd4b384 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.controller.sal.common.util.Rpcs;
 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.service.rev130819.AddFlowInput;
+
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
@@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -61,6 +63,7 @@ public class FlowConsumerImpl {
                }
                
                listener = new FlowDataListener();
+               
                if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) {
                        logger.error("Failed to listen on flow data modifcation events");
                System.out.println("Consumer SAL Service is down or NULL.");
@@ -75,7 +78,7 @@ public class FlowConsumerImpl {
                System.out.println("Consumer SAL Service is down or NULL.");
                return;
                }
-               addFlowTest();
+               //addFlowTest();
                System.out.println("-------------------------------------------------------------------");
                allocateCaches();
                commitHandler = new FlowDataCommitHandler();
@@ -120,11 +123,19 @@ public class FlowConsumerImpl {
     private void addFlow(InstanceIdentifier<?> path, Flow dataObject) {
 
         AddFlowInputBuilder input = new AddFlowInputBuilder();
+        List<Instruction> inst = (dataObject).getInstructions().getInstruction();
         input.setNode((dataObject).getNode());
         input.setPriority((dataObject).getPriority());
         input.setMatch((dataObject).getMatch());
         input.setCookie((dataObject).getCookie());
-        input.setAction((dataObject).getAction());
+        input.setInstructions((dataObject).getInstructions());
+        dataObject.getMatch().getLayer3Match()
+        for (int i=0;i<inst.size();i++) {
+            System.out.println("i = "+ i + inst.get(i).getInstruction().toString());
+            System.out.println("i = "+ i + inst.get(i).toString());
+        }
+        
+        System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
 
         // We send flow to the sounthbound plugin
         flowService.addFlow(input.build());
@@ -132,9 +143,11 @@ public class FlowConsumerImpl {
     
     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());
         }
-        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.updates.entrySet()) {
+            System.out.println("Coming update cc in FlowDatacommitHandler");
            // updateFlow(entry.getKey(),entry.getValue());
         }
         
@@ -196,9 +209,11 @@ public class FlowConsumerImpl {
             Flow original = originalSwView.get(key);
             if (original != null) {
                 // It is update for us
+                System.out.println("Coming update  in FlowDatacommitHandler");
                 updates.put(key, flow);
             } else {
                 // It is addition for us
+                System.out.println("Coming add in FlowDatacommitHandler");
                 additions.put(key, flow);
             }
         }
@@ -273,7 +288,7 @@ public class FlowConsumerImpl {
                        for (DataObject dataObject : additions) {
                            if (dataObject instanceof NodeFlow) {
                                NodeRef nodeOne = createNodeRef("foo:node:1");
-                                       // validating the dataObject here
+                                       // validating the dataObject here                               
                                    AddFlowInputBuilder input = new AddFlowInputBuilder();
                                    input.setNode(((NodeFlow) dataObject).getNode());
                                    input.setNode(nodeOne);
@@ -300,18 +315,6 @@ public class FlowConsumerImpl {
         return new NodeRef(path);
     }
            
-         /*  private void loadFlowData() {
        
-                   DataModification modification = (DataModification) dataservice.beginTransaction();
-                   String id = "abc";
-                   FlowKey key = new FlowKey(id, new NodeRef());
-                   InstanceIdentifier<?> path1;
-                   FlowBuilder flow = new FlowBuilder();
-                   flow.setKey(key);
-                   path1 = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, key).toInstance();
-                   DataObject cls = (DataObject) modification.readConfigurationData(path);
-                   modification.putConfigurationData(path, flow.build());
-                   modification.commit();
-               }*/
 
 }
index cc42e21f2a1fc8e0199455f9d7cc65d6b3521183..acc0dc69cd4d059b074fc7691bc1b73d75130170 100644 (file)
@@ -1,7 +1,478 @@
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+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.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;
+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.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.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unused")
 public class GroupConsumerImpl {
-       public GroupConsumerImpl() {
-               
+    
+    protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
+    private GroupEventListener groupEventListener = new GroupEventListener();
+    private Registration<NotificationListener> groupListener;
+    private SalGroupService groupService;    
+    private GroupDataCommitHandler commitHandler;
+    
+    private ConcurrentMap<GroupKey, Group> originalSwGroupView;
+    private ConcurrentMap<GroupKey, Group> installedSwGroupView;
+    
+    private ConcurrentMap<Node, List<Group>> nodeGroups;
+    private ConcurrentMap<GroupKey, Group> inactiveGroups;
+    
+    private IClusterContainerServices clusterGroupContainerService = null;
+    private ISwitchManager switchGroupManager;
+    private IContainer container;
+    
+    public GroupConsumerImpl() {
+           InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class).toInstance();
+        groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
+        
+        clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
+        switchGroupManager = FRMConsumerImpl.getSwitchManager();
+        container = FRMConsumerImpl.getContainer();
+        
+        if (!(cacheStartup())) {
+            logger.error("Unanle to allocate/retrieve group cache");
+            System.out.println("Unable to allocate/retrieve group cache");
+        }
+        
+        if (null == groupService) {
+            logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended");
+            System.out.println("Consumer SAL Group Service is down or NULL.");
+            return;
+        }     
+        
+        // For switch events
+        groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener);
+        
+        if (null == groupListener) {
+            logger.error("Listener to listen on group data modifcation events");
+            System.out.println("Listener to listen on group data modifcation events.");
+            return;
+        }       
+        
+        commitHandler = new GroupDataCommitHandler();
+        FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
        }
+       
+    private boolean allocateGroupCaches() {
+        if (this.clusterGroupContainerService == null) {
+            logger.warn("Group: Un-initialized clusterGroupContainerService, can't create cache");
+            return false;
+        }       
+
+        try {
+            clusterGroupContainerService.createCache("frm.originalSwGroupView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.installedSwGroupView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.inactiveGroups",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.nodeGroups",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            
+//TODO for cluster mode
+           /* clusterGroupContainerService.createCache(WORK_STATUS_CACHE,
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
+
+            clusterGroupContainerService.createCache(WORK_ORDER_CACHE,
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/
+            
+        } catch (CacheConfigException cce) {            
+            logger.error("Group CacheConfigException");
+            return false;
+            
+        } catch (CacheExistException cce) {
+            logger.error(" Group CacheExistException");           
+        }
+        
+        return true;
+    }
+    
+    private void nonClusterGroupObjectCreate() {
+        originalSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+        installedSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+        nodeGroups = new ConcurrentHashMap<Node, List<Group>>();        
+        inactiveGroups = new ConcurrentHashMap<GroupKey, Group>();
+    }
+    
+    @SuppressWarnings({ "unchecked" })
+    private boolean retrieveGroupCaches() {
+        ConcurrentMap<?, ?> map;
+
+        if (this.clusterGroupContainerService == null) {
+            logger.warn("Group: un-initialized clusterGroupContainerService, can't retrieve cache");
+            nonClusterGroupObjectCreate();
+            return false;
+        }       
+
+        map = clusterGroupContainerService.getCache("frm.originalSwGroupView");
+        if (map != null) {
+            originalSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(originalSwGroupView) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.installedSwGroupView");
+        if (map != null) {
+            installedSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(installedSwGroupView) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.inactiveGroups");
+        if (map != null) {
+            inactiveGroups = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(inactiveGroups) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.nodeGroups");
+        if (map != null) {
+            nodeGroups = (ConcurrentMap<Node, List<Group>>) map;
+        } else {
+            logger.error("Retrieval of cache(nodeGroup) failed");
+            return false;
+        }
+        
+        return true;
+    }
+       
+    private boolean cacheStartup() {
+        if (allocateGroupCaches()) {
+            if (retrieveGroupCaches()) {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
+    public Status validateGroup(Group group, FRMUtil.operation operation) {
+        String containerName;
+        String groupName;
+        Iterator<Bucket> bucketIterator;
+        boolean returnResult;
+        Buckets groupBuckets;
+        
+        if (null != group) {
+            containerName = group.getContainerName();
+            
+            if (null == containerName) {
+                containerName = GlobalConstants.DEFAULT.toString();
+            }
+            else if (!FRMUtil.isNameValid(containerName)) {
+                logger.error("Container Name is invalid %s" + containerName);
+                return new Status(StatusCode.BADREQUEST, "Container Name is invalid");
+            }
+            
+            groupName = group.getGroupName();
+            if (!FRMUtil.isNameValid(groupName)) {
+                logger.error("Group Name is invalid %s" + groupName);
+                return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
+            }
+            
+            returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
+            
+            if (FRMUtil.operation.ADD == operation && returnResult) {
+                logger.error("Record with same Group Name exists");
+                return new Status(StatusCode.BADREQUEST, "Group record exists");
+            }
+            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())) {
+                logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
+                return new Status(StatusCode.BADREQUEST, "Invalid Group type");                
+            }
+            
+            groupBuckets = group.getBuckets();
+                    
+            if (null != groupBuckets && null != groupBuckets.getBucket()) {
+                bucketIterator = groupBuckets.getBucket().iterator();
+                
+                while (bucketIterator.hasNext()) {
+                    if(!(FRMUtil.areActionsValid(bucketIterator.next().getActions()))) {
+                        logger.error("Error in action bucket");
+                        return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents");
+                    }                                
+                }
+            }                
+        }
+        
+        return new Status(StatusCode.SUCCESS);
+        
+    }
+    
+    private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
+        if (! originalSwGroupView.containsKey(key)) {
+            return false;
+        }
+        
+        for (ConcurrentMap.Entry<GroupKey, Group> entry : originalSwGroupView.entrySet()) {
+            if (entry.getValue().getGroupName().equals(groupName)) {
+                if (entry.getValue().getContainerName().equals(containerName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    
+    /**
+     * Update Group entries to the southbound plugin/inventory and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private Status updateGroup(InstanceIdentifier<?> path, Group groupUpdateDataObject) {
+        GroupKey groupKey = groupUpdateDataObject.getKey();
+        Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE);
+        
+        if (!groupOperationStatus.isSuccess()) {
+            logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
+            return groupOperationStatus;
+        }
+            
+        originalSwGroupView.remove(groupKey);
+        originalSwGroupView.put(groupKey, groupUpdateDataObject);
+        
+        if (groupUpdateDataObject.isInstall()) {
+            UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
+            //TODO how to get original group and modified group. 
+            
+            if (installedSwGroupView.containsKey(groupKey)) {
+                installedSwGroupView.remove(groupKey);
+            }
+            
+            installedSwGroupView.put(groupKey, groupUpdateDataObject);
+            groupService.updateGroup(groupData.build());
+        }
+        
+        return groupOperationStatus;
+    }
+    
+    /**
+     * Adds Group to the southbound plugin and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private Status addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
+        GroupKey groupKey = groupAddDataObject.getKey();
+        Status groupOperationStatus = validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+        
+        if (!groupOperationStatus.isSuccess()) {
+            logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
+            return groupOperationStatus;
+        }
+        validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+        originalSwGroupView.put(groupKey, groupAddDataObject);
+        
+        if (groupAddDataObject.isInstall()) {
+            AddGroupInputBuilder groupData = new AddGroupInputBuilder();
+            groupData.setBuckets(groupAddDataObject.getBuckets());
+            groupData.setContainerName(groupAddDataObject.getContainerName());
+            groupData.setGroupId(groupAddDataObject.getGroupId());
+            groupData.setGroupType(groupAddDataObject.getGroupType());
+            groupData.setNode(groupAddDataObject.getNode());  
+            installedSwGroupView.put(groupKey, groupAddDataObject);
+            groupService.addGroup(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()) {
+                return Rpcs.getRpcResult(false, null, null);
+            }
+        }
+        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+           
+            if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+                return Rpcs.getRpcResult(false, null, null);
+            }
+        }
+        
+        for(InstanceIdentifier<?> removal : transaction.removals) {
+           // removeFlow(removal);
+        }
+        
+        return Rpcs.getRpcResult(true, null, null);
+    }
+    
+    private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
+
+         @SuppressWarnings("unchecked")
+        @Override
+         public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+             // We should verify transaction
+             System.out.println("Coming in FlowDatacommitHandler");
+             internalTransaction transaction = new internalTransaction(modification);
+             transaction.prepareUpdate();
+             return transaction;
+         }
+    }
+
+    private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+
+        private final DataModification<InstanceIdentifier<?>, DataObject> modification;
+
+        @Override
+        public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
+            return modification;
+        }
+
+        public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+            this.modification = modification;
+        }
+
+        Map<InstanceIdentifier<?>, Group> additions = new HashMap<>();
+        Map<InstanceIdentifier<?>, Group> updates = new HashMap<>();
+        Set<InstanceIdentifier<?>> removals = new HashSet<>();
+
+        /**
+         * We create a plan which flows will be added, which will be updated and
+         * which will be removed based on our internal state.
+         * 
+         */
+        void prepareUpdate() {
+
+            Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
+            for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+                if (entry.getValue() instanceof Group) {                    
+                    Group group = (Group) entry.getValue();                    
+                    preparePutEntry(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
+         * 
+         */
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            
+            RpcResult<Void> rpcStatus = commitToPlugin(this);
+            // We return true if internal transaction is successful.
+          //  return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return rpcStatus;
+        }
+
+        /**
+         * 
+         * We should rollback our preparation
+         * 
+         */
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            // NOOP - we did not modified any internal state during
+            // requestCommit phase
+           // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return Rpcs.getRpcResult(true, null, null);
+            
+        }
+        
+    }
+    
+       
+       final class GroupEventListener implements SalGroupListener {
+           
+        List<GroupAdded> addedGroups = new ArrayList<>();
+        List<GroupRemoved> removedGroups = new ArrayList<>();
+        List<GroupUpdated> updatedGroups = new ArrayList<>();
+       
+
+        @Override
+        public void onGroupAdded(GroupAdded notification) {
+            System.out.println("added Group..........................");
+            addedGroups.add(notification);            
+        }
+
+        @Override
+        public void onGroupRemoved(GroupRemoved notification) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        @Override
+        public void onGroupUpdated(GroupUpdated notification) {
+            // TODO Auto-generated method stub
+            
+        }    
+    }
 }
index 8e77d26ea4afe61eea770873fea7d05a7bbd4818..03e36924e77968ab2815f9b391055945a62dc69b 100644 (file)
@@ -41,6 +41,10 @@ module opendaylight-group-types {
             type string; 
         }
         
+        leaf barrier {
+            type boolean; 
+        }       
+        
         container buckets {
             list bucket {
                 key "order";
index 99d4588cbc85b2491c3f06a346014b9072130b2e..20353af7852bd0b46834e7ad61364b222ec89640 100644 (file)
@@ -85,6 +85,17 @@ module opendaylight-meter-types {
             type meter-id;
         }
         
+        leaf install {
+            type boolean; 
+        }
+        leaf meter-name {
+            type string;
+        }
+        
+        leaf container-name {
+            type string; 
+        }
+        
         container meter-band-headers {
             list meter-band-header {
                 key "order";
index 6a83f75959edd624c35b43bf9de08290197ba89b..8338d185cc36abbbbc34613fe1e3df84d805550a 100644 (file)
@@ -20,10 +20,10 @@ module opendaylight-port-types {
     }
     
     typedef port-state {
-            type enumeration {
-                enum link-down;
-                enum blocked;
-                enum live;
+        type enumeration {
+            enum link-down;
+            enum blocked;
+            enum live;
         }
     }
 
@@ -125,7 +125,7 @@ module opendaylight-port-types {
                 uses common-port;
                 
                 leaf mask {
-                    type uint32;
+                    type port-config;
                     description "Bitmap of OFPPC-* flags to be changed";
                 }      
                 
@@ -135,7 +135,11 @@ module opendaylight-port-types {
             
                 leaf port-name {
                     type string; 
-                }                
+                } 
+
+                leaf barrier {
+                    type boolean; 
+                } 
             }            
         }    
     }
index 579ce70c626227234f7d07fbe7a2451b9fb4f81c..111d3d60faaf29fcfff6e93f05be3bad10b089e5 100644 (file)
@@ -11,11 +11,9 @@ module meter-management {
     }
 
     grouping meter-entry {
-    
         leaf node {
             type inv:node-ref;
         }
-        
         uses meter:meter;
     }   
      
diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang
new file mode 100644 (file)
index 0000000..483c0c9
--- /dev/null
@@ -0,0 +1,46 @@
+module flow-capable-transaction {
+       namespace "urn:opendaylight:flow:transaction";
+    prefix type;
+
+    import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    
+    revision "2013-11-03" {
+        description "Initial revision";
+    }
+
+    typedef transaction-id {
+       type uint64;
+    }
+    
+    grouping transaction-aware {
+        leaf transaction-id {
+            type transaction-id;
+        }
+    }
+
+    rpc get-next-transaction-id {
+        input {
+            leaf node {
+                ext:context-reference "inv:node-context";
+                type inv:node-ref;
+            }
+        }
+        output {
+               uses transaction-aware;
+        }
+    }
+
+    // Barier request?
+    rpc finish-transaction {
+        input {
+            leaf node {
+                ext:context-reference "inv:node-context";
+                type inv:node-ref;
+            }
+            leaf transaction-id {
+                type transaction-id;
+            }
+        }
+    }
+}
\ No newline at end of file
index fba1c0829c96b032f4094f82df13198b8a124730..bb010353280b8fa281c0901dde2e8d771f62ac13 100644 (file)
@@ -6,14 +6,14 @@ module sal-group {
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import ietf-inet-types {prefix inet;revision-date 2010-09-24;}
     import opendaylight-group-types {prefix group-type;revision-date 2013-10-18;}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-09-18" {
         description "Initial revision of group service";
     }        
     
     grouping node-group {
-        uses "inv:node-context-ref";
-        
+        uses "inv:node-context-ref";        
         uses group-type:group;
     }
 
@@ -32,18 +32,30 @@ module sal-group {
     rpc add-group {
         input {
             uses node-group;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc remove-group {
         input {
             uses group-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc update-group {
         input {
             uses group-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     } 
 
index d3777ff3320468bc55b5307ae6bdff61d016ae23..c187181e5e89099cc4720031cd3fa888629d69a2 100644 (file)
@@ -5,6 +5,7 @@ module sal-meter {
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-meter-types {prefix meter-type;revision-date "2013-09-18";}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-09-18" {
         description "Initial revision of meter service";
@@ -31,18 +32,30 @@ module sal-meter {
     rpc add-meter {
         input {
             uses node-meter;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc remove-meter {
         input {
             uses node-meter;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc update-meter {
         input {
             uses meter-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
         
diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang
new file mode 100644 (file)
index 0000000..df527ef
--- /dev/null
@@ -0,0 +1,46 @@
+module sal-port {
+    namespace "urn:opendaylight:port:service";
+    prefix 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";}
+
+    revision "2013-11-07" {
+        description "Initial revision of port service";
+    }        
+    
+    grouping node-port {
+        uses "inv:node-context-ref";
+        
+        uses port-type:ofp-port-mod;
+    }
+
+    /** Base configuration structure **/
+    grouping port-update {
+        uses "inv:node-context-ref";
+
+        container original-port {
+            uses port-type:ofp-port-mod;
+        }
+        container updated-port {
+            uses port-type:ofp-port-mod;
+        }
+    }
+
+    rpc update-port {
+        input {
+            uses port-update;
+        }
+    }
+     
+    rpc get-port {
+        output {
+            uses port-type:flow-capable-port;
+        }
+    }  
+    
+    notification port-removed {
+        uses node-port;
+    }
+}
\ No newline at end of file
index e740f961d5a83d234342a94aa151d476f001b9cf..3a6f20f77d9554dda1812311e7510414d1a6658a 100644 (file)
@@ -5,13 +5,15 @@ module sal-table {
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-10-26" {
         description "Initial revision of table service";
-    }        
+    }
     
     /** Base configuration structure **/
     grouping table-update {
+        uses "inv:node-context-ref";
         container original-table {
             uses table-type:table-features;
         }
@@ -22,11 +24,11 @@ module sal-table {
     
     rpc update-table {
         input {
-            leaf node {
-                ext:context-reference "inv:node-context";
-                type inv:node-ref;
-            }
             uses table-update;
+            uses tr:transaction-aware;
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }     
 }
\ No newline at end of file
index 52f60b3cc28728a7dce4a2435bfe1e97bb6a2e0c..b34c8d4c001b505a3a8e0f4b82d9122d5b6be5ce 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.sal.core.api.model;
 
 import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -39,4 +40,6 @@ public interface SchemaService extends BrokerService {
      * @return
      */
     SchemaContext getGlobalContext();
+    
+    ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener);
 }
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java
new file mode 100644 (file)
index 0000000..d76fd4d
--- /dev/null
@@ -0,0 +1,12 @@
+package org.opendaylight.controller.sal.core.api.model;
+
+import java.util.EventListener;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface SchemaServiceListener extends EventListener {
+
+    
+    void onGlobalContextUpdated(SchemaContext context);
+    
+}
index 9383a9e2ff50ee2149d1ce034ed6f195dfb0e7e6..74dd1a99012a0565e16963149fb84f46dc5a6c7f 100644 (file)
@@ -1,79 +1,89 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
-    <modelVersion>4.0.0</modelVersion>\r
-    <parent>\r
-        <groupId>org.opendaylight.controller</groupId>\r
-        <artifactId>sal-parent</artifactId>\r
-        <version>1.0-SNAPSHOT</version>\r
-    </parent>\r
-    <artifactId>sal-broker-impl</artifactId>\r
-    <packaging>bundle</packaging>\r
-    <scm>\r
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
-    </scm>\r
-\r
-    <dependencies>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-core-api</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-util</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-                <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-impl</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-impl</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-core-spi</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.slf4j</groupId>\r
-            <artifactId>slf4j-api</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>com.google.guava</groupId>\r
-            <artifactId>guava</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.eclipse.xtend</groupId>\r
-            <artifactId>org.eclipse.xtend.lib</artifactId>\r
-        </dependency>\r
-    </dependencies>\r
-\r
-    <build>\r
-        <plugins>\r
-            <plugin>\r
-                <groupId>org.apache.felix</groupId>\r
-                <artifactId>maven-bundle-plugin</artifactId>\r
-                <extensions>true</extensions>\r
-                <configuration>\r
-                    <instructions>\r
-                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>\r
-                        <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>\r
-                        <Private-Package>\r
-                            org.opendaylight.controller.sal.dom.broker.*\r
-                        </Private-Package>\r
-                    </instructions>\r
-                </configuration>\r
-            </plugin>\r
-            <plugin>\r
-                <groupId>org.eclipse.xtend</groupId>\r
-                <artifactId>xtend-maven-plugin</artifactId>\r
-            </plugin>\r
-        </plugins>\r
-    </build>\r
-</project>\r
+<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>
+    <artifactId>sal-broker-impl</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>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-spi</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+            <version>0.2.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>
+                        <Private-Package>
+                            org.opendaylight.controller.sal.dom.broker.*
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
index e3f5e4b4cd15309d85825da7e01ed9e31084a018..2bab4dbd26ca5896f3703978171e5ff72274b9db 100644 (file)
@@ -3,6 +3,10 @@ package org.opendaylight.controller.sal.dom.broker;
 import java.util.Hashtable;
 
 import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
@@ -11,17 +15,35 @@ public class BrokerActivator implements BundleActivator {
 
     BrokerImpl broker;
     private ServiceRegistration<Broker> brokerReg;
-    
+    private ServiceRegistration<SchemaService> schemaReg;
+    private ServiceRegistration<DataBrokerService> dataReg;
+    private ServiceRegistration<DataProviderService> dataProviderReg;
+    private SchemaServiceImpl schemaService;
+    private DataBrokerImpl dataService;
+
     @Override
     public void start(BundleContext context) throws Exception {
+        Hashtable<String, String> emptyProperties = new Hashtable<String, String>();
         broker = new BrokerImpl();
         broker.setBundleContext(context);
-        brokerReg = context.registerService(Broker.class, broker, new Hashtable<String,String>());
+        brokerReg = context.registerService(Broker.class, broker, emptyProperties);
+
+        schemaService = new SchemaServiceImpl();
+        schemaService.setContext(context);
+        schemaService.setParser(new YangParserImpl());
+        schemaService.start();
+        schemaReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String, String>());
+        
+        dataService = new DataBrokerImpl();
+        dataReg = context.registerService(DataBrokerService.class, dataService, emptyProperties);
+        dataProviderReg = context.registerService(DataProviderService.class, dataService, emptyProperties);
+        
+        
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        if(brokerReg != null) {
+        if (brokerReg != null) {
             brokerReg.unregister();
         }
     }
index 855ad9bd328d19c79b30e09ba4e485e0d1918044..26fecef688d3cfc748bc1367a5a1e4e5a9d40ac1 100644 (file)
@@ -37,16 +37,13 @@ public class BrokerImpl implements Broker {
     private val Set<ConsumerContextImpl> sessions = Collections.synchronizedSet(new HashSet<ConsumerContextImpl>());
     private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
         new HashSet<ProviderContextImpl>());
-    private val Set<BrokerModule> modules = Collections.synchronizedSet(new HashSet<BrokerModule>());
-    private val Map<Class<? extends BrokerService>, BrokerModule> serviceProviders = Collections.
-        synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerModule>());
 
     // Implementation specific
     @Property
     private var ExecutorService executor = Executors.newFixedThreadPool(5);
     @Property
     private var BundleContext bundleContext;
-    
+
     @Property
     private var RpcRouter router;
 
@@ -68,29 +65,6 @@ public class BrokerImpl implements Broker {
         return session;
     }
 
-    public def addModule(BrokerModule module) {
-        log.info("Registering broker module " + module);
-        if(modules.contains(module)) {
-            log.error("Module already registered");
-            throw new IllegalArgumentException("Module already exists.");
-        }
-
-        val provServices = module.getProvidedServices();
-        for (Class<? extends BrokerService> serviceType : provServices) {
-            log.info("  Registering session service implementation: " + serviceType.getCanonicalName());
-            serviceProviders.put(serviceType, module);
-        }
-    }
-
-    public def <T extends BrokerService> T serviceFor(Class<T> service, ConsumerContextImpl session) {
-        val prov = serviceProviders.get(service);
-        if(prov == null) {
-            log.warn("Service " + service.toString() + " is not supported");
-            return null;
-        }
-        return prov.getServiceForSession(service, session);
-    }
-
     protected def Future<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
         val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
         return result;
@@ -98,20 +72,20 @@ public class BrokerImpl implements Broker {
 
     // Validation
     private def void checkPredicates(Provider prov) {
-        if(prov == null)
+        if (prov == null)
             throw new IllegalArgumentException("Provider should not be null.");
         for (ProviderContextImpl session : providerSessions) {
-            if(prov.equals(session.getProvider()))
+            if (prov.equals(session.getProvider()))
                 throw new IllegalStateException("Provider already registered");
         }
 
     }
 
     private def void checkPredicates(Consumer cons) {
-        if(cons == null)
+        if (cons == null)
             throw new IllegalArgumentException("Consumer should not be null.");
         for (ConsumerContextImpl session : sessions) {
-            if(cons.equals(session.getConsumer()))
+            if (cons.equals(session.getConsumer()))
                 throw new IllegalStateException("Consumer already registered");
         }
     }
index 6d57a4e2247392089f4a0895b439e8f2d3c84b76..9f21823e3efb33c56e841fc1ad2af52ba481ad7f 100644 (file)
@@ -1,13 +1,15 @@
 package org.opendaylight.controller.sal.dom.broker
 
-import java.util.Collections
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import java.util.HashMap
 import org.opendaylight.controller.sal.core.api.BrokerService
 import org.opendaylight.controller.sal.core.api.Consumer
 import org.osgi.framework.BundleContext
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy
+import com.google.common.collect.ClassToInstanceMap
+import com.google.common.collect.MutableClassToInstanceMap
+import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory
 
 class ConsumerContextImpl implements ConsumerSession {
 
@@ -17,8 +19,7 @@ class ConsumerContextImpl implements ConsumerSession {
     @Property
     private var BrokerImpl broker;
 
-    private val instantiatedServices = Collections.synchronizedMap(
-        new HashMap<Class<? extends BrokerService>, BrokerService>());
+    private val ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap.create();
     private boolean closed = false;
 
     private BundleContext context;
@@ -33,14 +34,20 @@ class ConsumerContextImpl implements ConsumerSession {
     }
 
     override <T extends BrokerService> T getService(Class<T> service) {
-        val potential = instantiatedServices.get(service);
-        if(potential != null) {
-            val ret = potential as T;
-            return ret;
+        val localProxy = instantiatedServices.getInstance(service);
+        if(localProxy != null) {
+            return localProxy;
         }
-        val ret = broker.serviceFor(service, this);
+        val serviceRef = context.getServiceReference(service);
+        if(serviceRef == null) {
+            return null;
+        }
+        val serviceImpl = context.getService(serviceRef);
+        
+        
+        val ret = ProxyFactory.createProxy(serviceRef,serviceImpl);
         if(ret != null) {
-            instantiatedServices.put(service, ret);
+            instantiatedServices.putInstance(service, ret);
         }
         return ret;
     }
@@ -49,7 +56,9 @@ class ConsumerContextImpl implements ConsumerSession {
         val toStop = instantiatedServices.values();
         this.closed = true;
         for (BrokerService brokerService : toStop) {
-            //brokerService.closeSession();
+            if(brokerService instanceof AbstractBrokerServiceProxy<?>) {
+                (brokerService as AutoCloseable).close();
+            } 
         }
         broker.consumerSessionClosed(this);
     }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend
new file mode 100644 (file)
index 0000000..8a17c83
--- /dev/null
@@ -0,0 +1,63 @@
+package org.opendaylight.controller.sal.dom.broker
+
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.controller.sal.common.DataStoreIdentifier
+import org.opendaylight.controller.sal.core.api.data.DataProviderService.DataRefresher
+import org.opendaylight.controller.sal.core.api.data.DataValidator
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+
+class DataBrokerImpl implements DataProviderService {
+
+    val readRouter = new DataReaderRouter();
+
+    override addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        // NOOP
+    }
+
+    override addValidator(DataStoreIdentifier store, DataValidator validator) {
+        // NOOP
+    }
+
+    override beginTransaction() {
+        // NOOP
+    }
+
+    override readConfigurationData(InstanceIdentifier path) {
+        readRouter.readConfigurationData(path)
+    }
+
+    override readOperationalData(InstanceIdentifier path) {
+        readRouter.readOperationalData(path)
+    }
+
+    override registerConfigurationReader(InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        readRouter.registerConfigurationReader(path, reader);
+    }
+
+    override registerOperationalReader(InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        readRouter.registerOperationalReader(path, reader);
+    }
+
+    override removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        // NOOP
+    }
+
+    override removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        // NOOP
+    }
+
+    override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) {
+        // NOOP
+    }
+
+    override registerCommitHandler(InstanceIdentifier path,
+        DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+        // NOOP
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend
deleted file mode 100644 (file)
index 3bccc4e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.opendaylight.controller.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-
-class DataConsumerServiceImpl implements DataBrokerService {
-    
-    override beginTransaction() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-
-    override readConfigurationData(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-    
-    override readOperationalData(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-    
-    override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java
new file mode 100644 (file)
index 0000000..ba558c5
--- /dev/null
@@ -0,0 +1,281 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.Checksum;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.*;
+
+public class SchemaServiceImpl implements SchemaService, AutoCloseable {
+    private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class);
+
+    private ListenerRegistry<SchemaServiceListener> listeners;
+    private YangModelParser parser;
+
+    private BundleContext context;
+    private BundleScanner scanner = new BundleScanner();
+
+    /**
+     * Map of currently problematic yang files that should get fixed eventually
+     * after all events are received.
+     */
+    private final Multimap<Bundle, URL> inconsistentBundlesToYangURLs = HashMultimap.create();
+    private final Multimap<Bundle, URL> consistentBundlesToYangURLs = HashMultimap.create();
+    private BundleTracker<Object> bundleTracker;
+    private final YangStoreCache cache = new YangStoreCache();
+
+    public ListenerRegistry<SchemaServiceListener> getListeners() {
+        return listeners;
+    }
+
+    public void setListeners(ListenerRegistry<SchemaServiceListener> listeners) {
+        this.listeners = listeners;
+    }
+
+    public YangModelParser getParser() {
+        return parser;
+    }
+
+    public void setParser(YangModelParser parser) {
+        this.parser = parser;
+    }
+
+    public BundleContext getContext() {
+        return context;
+    }
+
+    public void setContext(BundleContext context) {
+        this.context = context;
+    }
+
+    public void start() {
+        checkState(parser != null);
+        checkState(context != null);
+        if (listeners == null) {
+            listeners = new ListenerRegistry<>();
+        }
+
+        bundleTracker = new BundleTracker<Object>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
+        bundleTracker.open();
+    }
+
+    public SchemaContext getGlobalContext() {
+        return getSchemaContextSnapshot();
+    }
+
+    public synchronized SchemaContext getSchemaContextSnapshot() {
+        Optional<SchemaContext> yangStoreOpt = cache.getCachedSchemaContext(consistentBundlesToYangURLs);
+        if (yangStoreOpt.isPresent()) {
+            return yangStoreOpt.get();
+        }
+        SchemaContext snapshot = createSnapshot(parser, consistentBundlesToYangURLs);
+        updateCache(snapshot);
+        return snapshot;
+    }
+
+    @Override
+    public void addModule(Module module) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public SchemaContext getSessionContext() {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeModule(Module module) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    
+    @Override
+    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+        return listeners.register(listener);
+    }
+    
+    @Override
+    public void close() throws Exception {
+        bundleTracker.close();
+        // FIXME: Add listeners.close();
+
+    }
+
+    private synchronized boolean tryToUpdateState(Collection<URL> changedURLs, Multimap<Bundle, URL> proposedNewState,
+            boolean adding) {
+        Preconditions.checkArgument(changedURLs.size() > 0, "No change can occur when no URLs are changed");
+
+        try {
+            // consistent state
+            // merge into
+            SchemaContext snapshot = createSnapshot(parser, proposedNewState);
+            consistentBundlesToYangURLs.clear();
+            consistentBundlesToYangURLs.putAll(proposedNewState);
+            inconsistentBundlesToYangURLs.clear();
+            // update cache
+            updateCache(snapshot);
+            logger.info("SchemaService updated to new consistent state");
+            logger.trace("SchemaService  updated to new consistent state containing {}", consistentBundlesToYangURLs);
+
+            // notifyListeners(changedURLs, adding);
+            return true;
+        } catch (Exception e) {
+            // inconsistent state
+            logger.debug(
+                    "SchemaService is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
+                    consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, e.toString());
+            return false;
+        }
+    }
+
+    private static Collection<InputStream> fromUrlsToInputStreams(Multimap<Bundle, URL> multimap) {
+        return Collections2.transform(multimap.values(), new Function<URL, InputStream>() {
+
+            @Override
+            public InputStream apply(URL url) {
+                try {
+                    return url.openStream();
+                } catch (IOException e) {
+                    logger.warn("Unable to open stream from {}", url);
+                    throw new IllegalStateException("Unable to open stream from " + url, e);
+                }
+            }
+        });
+    }
+
+    private static SchemaContext createSnapshot(YangModelParser parser, Multimap<Bundle, URL> multimap) {
+        List<InputStream> models = new ArrayList<>(fromUrlsToInputStreams(multimap));
+        Set<Module> modules = parser.parseYangModelsFromStreams(models);
+        SchemaContext yangStoreSnapshot = parser.resolveSchemaContext(modules);
+        return yangStoreSnapshot;
+    }
+
+    private void updateCache(SchemaContext snapshot) {
+        cache.cacheYangStore(consistentBundlesToYangURLs, snapshot);
+        for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+            try {
+                listener.getInstance().onGlobalContextUpdated(snapshot);
+            } catch (Exception e) {
+                logger.error("Exception occured during invoking listener",e);
+            }
+        }
+    }
+
+    private class BundleScanner implements BundleTrackerCustomizer<Object> {
+        @Override
+        public Object addingBundle(Bundle bundle, BundleEvent event) {
+
+            // Ignore system bundle:
+            // system bundle might have config-api on classpath &&
+            // config-api contains yang files =>
+            // system bundle might contain yang files from that bundle
+            if (bundle.getBundleId() == 0)
+                return bundle;
+
+            Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
+            if (enumeration != null && enumeration.hasMoreElements()) {
+                synchronized (this) {
+                    List<URL> addedURLs = new ArrayList<>();
+                    while (enumeration.hasMoreElements()) {
+                        URL url = enumeration.nextElement();
+                        addedURLs.add(url);
+                    }
+                    logger.trace("Bundle {} has event {}, bundle state {}, URLs {}", bundle, event, bundle.getState(),
+                            addedURLs);
+                    // test that yang store is consistent
+                    Multimap<Bundle, URL> proposedNewState = HashMultimap.create(consistentBundlesToYangURLs);
+                    proposedNewState.putAll(inconsistentBundlesToYangURLs);
+                    proposedNewState.putAll(bundle, addedURLs);
+                    boolean adding = true;
+                    if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
+                        inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
+                    }
+                }
+            }
+            return bundle;
+        }
+
+        @Override
+        public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+            logger.debug("Modified bundle {} {} {}", bundle, event, object);
+        }
+
+        /**
+         * If removing YANG files makes yang store inconsistent, method
+         * {@link #getYangStoreSnapshot()} will throw exception. There is no
+         * rollback.
+         */
+
+        @Override
+        public synchronized void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+            inconsistentBundlesToYangURLs.removeAll(bundle);
+            Collection<URL> consistentURLsToBeRemoved = consistentBundlesToYangURLs.removeAll(bundle);
+
+            if (consistentURLsToBeRemoved.isEmpty()) {
+                return; // no change
+            }
+            boolean adding = false;
+            // notifyListeners(consistentURLsToBeRemoved, adding);
+        }
+    }
+
+    private static final class YangStoreCache {
+
+        Set<URL> cachedUrls;
+        SchemaContext cachedContextSnapshot;
+
+        Optional<SchemaContext> getCachedSchemaContext(Multimap<Bundle, URL> bundlesToYangURLs) {
+            Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
+            if (cachedUrls != null && cachedUrls.equals(urls)) {
+                Preconditions.checkState(cachedContextSnapshot != null);
+                return Optional.of(cachedContextSnapshot);
+            }
+            return Optional.absent();
+        }
+
+        private static Set<URL> setFromMultimapValues(Multimap<Bundle, URL> bundlesToYangURLs) {
+            Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
+            Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
+            return urls;
+        }
+
+        void cacheYangStore(Multimap<Bundle, URL> urls, SchemaContext ctx) {
+            this.cachedUrls = setFromMultimapValues(urls);
+            this.cachedContextSnapshot = ctx;
+        }
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java
new file mode 100644 (file)
index 0000000..7e3d9be
--- /dev/null
@@ -0,0 +1,68 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.osgi.framework.ServiceReference;
+import static com.google.common.base.Preconditions.*;
+
+public abstract class AbstractBrokerServiceProxy<T extends BrokerService> implements AutoCloseable, BrokerService {
+
+    private T delegate;
+    private final ServiceReference<T> reference;
+
+    public AbstractBrokerServiceProxy(ServiceReference<T> ref, T delegate) {
+        this.delegate = checkNotNull(delegate, "Delegate should not be null.");
+        this.reference = checkNotNull(ref, "Reference should not be null.");
+    }
+
+    protected final T getDelegate() {
+        checkState(delegate != null, "Proxy was closed and unregistered.");
+        return delegate;
+    }
+
+    protected final ServiceReference<T> getReference() {
+        return reference;
+    }
+
+    private Set<Registration<?>> registrations = Collections.synchronizedSet(new HashSet<Registration<?>>());
+
+    protected <R extends Registration<?>> R addRegistration(R registration) {
+        if (registration != null) {
+            registrations.add(registration);
+        }
+        return registration;
+    }
+
+    protected void closeBeforeUnregistrations() {
+        // NOOP
+    }
+
+    protected void closeAfterUnregistrations() {
+        // NOOP
+    }
+
+    @Override
+    public void close() {
+        if (delegate != null) {
+            delegate = null;
+            RuntimeException potentialException = new RuntimeException(
+                    "Uncaught exceptions occured during unregistration");
+            boolean hasSuppressed = false;
+            for (Registration<?> registration : registrations) {
+                try {
+                    registration.close();
+                } catch (Exception e) {
+                    potentialException.addSuppressed(e);
+                    hasSuppressed = true;
+                }
+            }
+            if (hasSuppressed) {
+                throw potentialException;
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java
new file mode 100644 (file)
index 0000000..3eb7e22
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataBrokerServiceProxy extends AbstractBrokerServiceProxy<DataBrokerService> implements DataBrokerService {
+
+    public DataBrokerServiceProxy(ServiceReference<DataBrokerService> ref, DataBrokerService delegate) {
+        super(ref, delegate);
+    }
+
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+            DataChangeListener listener) {
+        return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+    }
+
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return getDelegate().readConfigurationData(path);
+    }
+
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return getDelegate().readOperationalData(path);
+    }
+
+    public DataModificationTransaction beginTransaction() {
+        return getDelegate().beginTransaction();
+    }
+    
+    
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java
new file mode 100644 (file)
index 0000000..2fded87
--- /dev/null
@@ -0,0 +1,77 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataProviderServiceProxy extends AbstractBrokerServiceProxy<DataProviderService> implements
+        DataProviderService {
+
+    public DataProviderServiceProxy(ServiceReference<DataProviderService> ref, DataProviderService delegate) {
+        super(ref, delegate);
+    }
+
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+            DataChangeListener listener) {
+        return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+    }
+
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return getDelegate().readConfigurationData(path);
+    }
+
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return getDelegate().readOperationalData(path);
+    }
+
+    public DataModificationTransaction beginTransaction() {
+        return getDelegate().beginTransaction();
+    }
+
+    @Override
+    public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        getDelegate().addRefresher(store, refresher);
+    }
+
+    @Override
+    public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+        getDelegate().addValidator(store, validator);
+    }
+
+    @Override
+    public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
+            InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+        return addRegistration(getDelegate().registerCommitHandler(path, commitHandler));
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return addRegistration(getDelegate().registerConfigurationReader(path, reader));
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return addRegistration(getDelegate().registerOperationalReader(path, reader));
+    }
+
+    @Override
+    public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        getDelegate().removeRefresher(store, refresher);
+    }
+
+    @Override
+    public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        getDelegate().removeValidator(store, validator);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java
new file mode 100644 (file)
index 0000000..170517b
--- /dev/null
@@ -0,0 +1,29 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationPublishServiceProxy extends AbstractBrokerServiceProxy<NotificationPublishService> implements NotificationPublishService {
+
+    public NotificationPublishServiceProxy(ServiceReference<NotificationPublishService> ref,
+            NotificationPublishService delegate) {
+        super(ref, delegate);
+    }
+
+    public void sendNotification(CompositeNode notification) {
+        getDelegate().sendNotification(notification);
+    }
+
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        return addRegistration(getDelegate().addNotificationListener(notification, listener));
+
+    }
+
+    public void publish(CompositeNode notification) {
+        getDelegate().publish(notification);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java
new file mode 100644 (file)
index 0000000..d685370
--- /dev/null
@@ -0,0 +1,20 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationServiceProxy extends AbstractBrokerServiceProxy<NotificationService> implements
+        NotificationService {
+
+    public NotificationServiceProxy(ServiceReference<NotificationService> ref, NotificationService delegate) {
+        super(ref, delegate);
+    }
+
+    @Override
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        return addRegistration(getDelegate().addNotificationListener(notification, listener));
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend
new file mode 100644 (file)
index 0000000..eb73867
--- /dev/null
@@ -0,0 +1,41 @@
+package org.opendaylight.controller.sal.dom.broker.osgi
+
+import org.opendaylight.controller.sal.core.api.BrokerService
+import org.osgi.framework.ServiceReference
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService
+import org.opendaylight.controller.sal.core.api.notify.NotificationService
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+
+class ProxyFactory {
+
+    static def <T extends BrokerService> T createProxy(ServiceReference<T> serviceRef, T service) {
+        return createProxyImpl(serviceRef, service) as T;
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataBrokerService service) {
+        new DataBrokerServiceProxy(ref as ServiceReference<DataBrokerService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataProviderService service) {
+        new DataProviderServiceProxy(ref as ServiceReference<DataProviderService>, service);
+    }
+    
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationPublishService service) {
+        new NotificationPublishServiceProxy(ref as ServiceReference<NotificationPublishService>, service);
+    }
+    
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationService service) {
+        new NotificationServiceProxy(ref as ServiceReference<NotificationService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, SchemaService service) {
+        new SchemaServiceProxy(ref as ServiceReference<SchemaService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> reference, BrokerService service) {
+        throw new IllegalArgumentException("Not supported class");
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java
new file mode 100644 (file)
index 0000000..8938bf2
--- /dev/null
@@ -0,0 +1,45 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.framework.ServiceReference;
+
+public class SchemaServiceProxy extends AbstractBrokerServiceProxy<SchemaService> implements SchemaService {
+
+    public SchemaServiceProxy(ServiceReference<SchemaService> ref, SchemaService delegate) {
+        super(ref, delegate);
+    }
+
+    @Override
+    public void addModule(Module module) {
+        getDelegate().addModule(module);
+    }
+
+    @Override
+    public void removeModule(Module module) {
+        getDelegate().removeModule(module);
+    }
+
+    @Override
+    public SchemaContext getSessionContext() {
+        return null;
+    }
+
+    @Override
+    public SchemaContext getGlobalContext() {
+        return getDelegate().getGlobalContext();
+    }
+
+    @Override
+    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+        ListenerRegistration<SchemaServiceListener> registration = getDelegate().registerSchemaServiceListener(listener);
+        addRegistration(registration);
+        return registration;
+    }
+
+    
+    
+}
index b4cf6c985b6aa8a9995ccb43ed4c27fe6f494166..c6296eb7ea14ce82726dcd080b548dc375e26940 100644 (file)
@@ -1,15 +1,14 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import javax.ws.rs.WebApplicationException;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -18,12 +17,13 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.*;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.slf4j.Logger;
@@ -114,5 +114,135 @@ final class TestUtils {
         }
 
     }
+    
+    static String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+        String jsonResult = null;
+        Set<Module> modules = null;
+
+        try {
+            modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("modules can't be null.", modules);
+
+        InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+        CompositeNode compositeNode = null;
+        try {
+            compositeNode = TestUtils.loadCompositeNode(xmlStream);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("Composite node can't be null", compositeNode);
+
+        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+        for (Module module : modules) {
+            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+                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);
+                } catch (IOException e) {
+                    System.out.println("Output file wasn't cloased sucessfuly.");
+                }
+            }
+        }
+        return jsonResult;
+    }
+    
+    static void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+        FileOutputStream fileOS = null;
+        try {
+            String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+            File outFile = new File(path + "/data.json");
+            fileOS = new FileOutputStream(outFile);
+            try {
+                fileOS.write(outputStream.toByteArray());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            fileOS.close();
+        } catch (FileNotFoundException e1) {
+            e1.printStackTrace();
+        }
+    }    
+    
+    static String readJsonFromFile(String path,boolean removeWhiteChars) {
+        FileReader fileReader = getFileReader(path);
+
+        StringBuilder strBuilder = new StringBuilder();
+        char[] buffer = new char[1000];
+
+        while (true) {
+            int loadedCharNum;
+            try {
+                loadedCharNum = fileReader.read(buffer);
+            } catch (IOException e) {
+                break;
+            }
+            if (loadedCharNum == -1) {
+                break;
+            }
+            strBuilder.append(buffer, 0, loadedCharNum);
+        }
+        try {
+            fileReader.close();
+        } catch (IOException e) {
+            System.out.println("The file wasn't closed");
+        }
+        String rawStr = strBuilder.toString();
+        if (removeWhiteChars) {        
+            rawStr = rawStr.replace("\n", "");
+            rawStr = rawStr.replace("\r", "");
+            rawStr = rawStr.replace("\t", "");
+            rawStr = removeSpaces(rawStr);
+        }
+
+        return rawStr;
+    }
+    
+    private static FileReader getFileReader(String path) {
+        String fullPath = YangAndXmlToJsonConversionJsonReaderTest.class.getResource(path).getPath();
+        assertNotNull("Path to file can't be null.", fullPath);
+        File file = new File(fullPath);
+        assertNotNull("File can't be null", file);
+        FileReader fileReader = null;
+        try {
+            fileReader = new FileReader(file);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("File reader can't be null.", fileReader);
+        return fileReader;
+    }
+
+    private static String removeSpaces(String rawStr) {
+        StringBuilder strBuilder = new StringBuilder();
+        int i = 0;
+        int quoteCount = 0;
+        while (i < rawStr.length()) {
+            if (rawStr.substring(i, i + 1).equals("\"")) {
+                quoteCount++;
+            }
+
+            if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
+                strBuilder.append(rawStr.charAt(i));
+            }
+            i++;
+        }
+
+        return strBuilder.toString();
+    }    
+    
+    
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java
new file mode 100644 (file)
index 0000000..0f39088
--- /dev/null
@@ -0,0 +1,243 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.Test;
+
+import com.google.gson.stream.JsonReader;
+
+public class YangAndXmlToJsonConversionJsonReaderTest {
+
+    @Test
+    public void simpleYangTypesWithJsonReaderTest() {
+        String jsonOutput;
+        jsonOutput = TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
+                false);
+
+//        jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+//                "/yang-to-json-conversion/simple-yang-types");
+        
+        StringReader strReader = new StringReader(jsonOutput);
+        JsonReader jReader = new JsonReader(strReader);
+        try {
+            checkCont1(jReader);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void checkCont1(JsonReader jReader) throws IOException {
+        jReader.beginObject();
+        assertNotNull("cont1 is missing.", jReader.hasNext());
+        jReader.nextName();
+        checkCont1Elements(jReader, prepareInputData(jReader), "cont1/");
+        jReader.endObject();
+
+    }
+
+    private Map<String, String> prepareInputData(JsonReader jReader) {
+        Map<String, String> dataMap = new HashMap<>();
+        dataMap.put("cont1/lf11", "lf");
+        dataMap.put("cont1/lflst11.1", "55");
+        dataMap.put("cont1/lflst11.2", "56");
+        dataMap.put("cont1/lflst11.3", "57");
+        dataMap.put("cont1/lflst12.1", "lflst12 str1");
+        dataMap.put("cont1/lflst12.2", "lflst12 str2");
+        dataMap.put("cont1/lflst12.3", "lflst12 str3");
+
+        dataMap.put("cont1/lst11.1/lf111", "140");
+        dataMap.put("cont1/lst11.1/lf112", "lf112 str");
+        dataMap.put("cont1/lst11.1/cont111/lf1111", "lf1111 str");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.1", "2048");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.2", "1024");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.3", "4096");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111A", "lf1111A str11");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111B", "4");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111A", "lf1111A str12");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111B", "7");
+        dataMap.put("cont1/lst11.1/lst111.1/lf1111", "65");
+        dataMap.put("cont1/lst11.1/lst112.1/lf1121", "lf1121 str11");
+
+        dataMap.put("cont1/lst11.2/lf111", "141");
+        dataMap.put("cont1/lst11.2/lf112", "lf112 str2");
+        dataMap.put("cont1/lst11.2/cont111/lf1111", "lf1111 str2");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.1", "2049");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.2", "1025");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.3", "4097");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111A", "lf1111A str21");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111B", "5");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111A", "lf1111A str22");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111B", "8");
+        dataMap.put("cont1/lst11.2/lst111.1/lf1111", "55");
+        dataMap.put("cont1/lst11.2/lst111.2/lf1111", "56");
+        dataMap.put("cont1/lst11.2/lst112.1/lf1121", "lf1121 str21");
+        dataMap.put("cont1/lst11.2/lst112.2/lf1121", "lf1121 str22");
+
+        return dataMap;
+
+    }
+
+    private void checkCont1Elements(JsonReader jReader, Map<String, String> dataMap, String pthPref) throws IOException {
+        Set<String> keys = new HashSet<>();
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf11")) {
+                assertEquals("Key " + keyName + " has incorrect value.", dataMap.get(pthPref + keyName),
+                        jReader.nextString());
+                keys.add(keyName);
+            } else if (keyName.equals("lflst11")) {
+                checkLflstValues(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else if (keyName.equals("lflst12")) {
+                checkLflstValues(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else if (keyName.equals("lst11")) {
+                checkLst11(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else {
+                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+            }
+        }
+        jReader.endObject();
+        assertEquals("Incorrect number of keys in cont1", 4, keys.size());
+
+    }
+
+    private void checkLst11(JsonReader jReader, String pthPref, Map<String, String> dataMap) throws IOException {
+        jReader.beginArray();
+
+        int arrayLength = 0;
+        while (jReader.hasNext()) {
+            checkLst11Elements(jReader, pthPref + "." + ++arrayLength + "/", dataMap);
+        }
+        jReader.endArray();
+        assertEquals("Incorrect number of items in lst11 array.", 2, arrayLength);
+    }
+
+    private void checkLst11Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf111")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("lf112")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("cont111")) {
+                checkCont111(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst111")) {
+                checkLst111(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst112")) {
+                checkLst112(jReader, pthPref + keyName, data);
+            } else {
+                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+            }
+        }
+        jReader.endObject();
+    }
+
+    private void checkLst112(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst112Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst112Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        if (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+        }
+        jReader.endObject();
+
+    }
+
+    private void checkLst111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        if (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+        }
+        jReader.endObject();
+    }
+
+    private void checkCont111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        checkCont111Elements(jReader, pthPref + "/", data);
+        jReader.endObject();
+    }
+
+    private void checkCont111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf1111")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("lflst1111")) {
+                checkLflstValues(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst1111")) {
+                checkLst1111(jReader, pthPref + keyName, data);
+            }
+        }
+
+    }
+
+    private void checkLst1111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst1111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst1111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf1111A")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+
+            } else if (keyName.equals("lf1111B")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            }
+        }
+        jReader.endObject();
+    }
+
+    private void checkLflstValues(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 1;
+        String keyValue = null;
+        List<String> searchedValues = new ArrayList<>();
+        while ((keyValue = data.get(pthPref + "." + arrayIndex++)) != null) {
+            searchedValues.add(keyValue);
+        }
+
+        while (jReader.hasNext()) {
+            String value = jReader.nextString();
+            assertTrue("Value " + value + " of lflst " + pthPref + " wasn't found", searchedValues.contains(value));
+        }
+
+        jReader.endArray();
+    }
+
+
+
+}
@@ -1,22 +1,14 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
-import java.io.*;
-import java.util.Set;
-import java.util.regex.*;
+import java.util.regex.Pattern;
 
-import javax.ws.rs.WebApplicationException;
+import org.junit.Test;
 
-import org.junit.*;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.model.api.*;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+public class YangAndXmlToJsonConversionRegExTest {
 
-public class YangAndXmlToJsonConversion {
-
-    @Ignore
     @Test
     /**
      * Test for simple yang types (leaf, list, leaf-list, container and various combination of them)
@@ -25,15 +17,14 @@ public class YangAndXmlToJsonConversion {
     public void simpleYangTypesTest() {
         String jsonOutput = null;
 
-        jsonOutput = convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
-                "/yang-to-json-conversion/simple-yang-types");
+//        jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+//                "/yang-to-json-conversion/simple-yang-types");
 
-//         jsonOutput =
-//         readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/output.json");
+         jsonOutput =
+         TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",true);
 
         verifyJsonOutputForSimpleYangTypes(jsonOutput);
-
-    }
+    }    
 
     private void verifyJsonOutputForSimpleYangTypes(String jsonOutput) {
 
@@ -149,125 +140,69 @@ public class YangAndXmlToJsonConversion {
         return null;
     }
 
-    private String readJsonFromFile(String path) {
-        String fullPath = YangAndXmlToJsonConversion.class.getResource(path).getPath();
-        assertNotNull("Path to file can't be null.", fullPath);
-        File file = new File(fullPath);
-        assertNotNull("File can't be null", file);
-        FileReader fileReader = null;
-        try {
-            fileReader = new FileReader(file);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("File reader can't be null.", fileReader);
-
-        StringBuilder strBuilder = new StringBuilder();
-        char[] buffer = new char[1000];
-
-        while (true) {
-            int loadedCharNum;
-            try {
-                loadedCharNum = fileReader.read(buffer);
-            } catch (IOException e) {
-                break;
-            }
-            if (loadedCharNum == -1) {
-                break;
-            }
-            strBuilder.append(buffer, 0, loadedCharNum);
-        }
-        try {
-            fileReader.close();
-        } catch (IOException e) {
-            System.out.println("The file wasn't closed");
-            ;
-        }
-        String rawStr = strBuilder.toString();
-        rawStr = rawStr.replace("\n", "");
-        rawStr = rawStr.replace("\r", "");
-        rawStr = rawStr.replace("\t", "");
-        rawStr = removeSpaces(rawStr);
-
-        return rawStr;
-    }
-
-    private String removeSpaces(String rawStr) {
-        StringBuilder strBuilder = new StringBuilder();
-        int i = 0;
-        int quoteCount = 0;
-        while (i < rawStr.length()) {
-            if (rawStr.substring(i, i + 1).equals("\"")) {
-                quoteCount++;
-            }
 
-            if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
-                strBuilder.append(rawStr.charAt(i));
-            }
-            i++;
-        }
-
-        return strBuilder.toString();
-    }
 
-    private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
-        String jsonResult = null;
-        Set<Module> modules = null;
 
-        try {
-            modules = TestUtils.loadModules(YangAndXmlToJsonConversion.class.getResource(yangPath).getPath());
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("modules can't be null.", modules);
-
-        InputStream xmlStream = YangAndXmlToJsonConversion.class.getResourceAsStream(xmlDataPath);
-        CompositeNode compositeNode = null;
-        try {
-            compositeNode = TestUtils.loadCompositeNode(xmlStream);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("Composite node can't be null", compositeNode);
+//    private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+//        String jsonResult = null;
+//        Set<Module> modules = null;
+//
+//        try {
+//            modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+//        } catch (FileNotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        assertNotNull("modules can't be null.", modules);
+//
+//        InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+//        CompositeNode compositeNode = null;
+//        try {
+//            compositeNode = TestUtils.loadCompositeNode(xmlStream);
+//        } catch (FileNotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        assertNotNull("Composite node can't be null", compositeNode);
+//
+//        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+//        for (Module module : modules) {
+//            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+//                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+//                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+//                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);
+//                } catch (IOException e) {
+//                    System.out.println("Output file wasn't cloased sucessfuly.");
+//                }
+//            }
+//        }
+//        return jsonResult;
+//    }
+//
+//    private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+//        FileOutputStream fileOS = null;
+//        try {
+//            String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+//            File outFile = new File(path + "/data.json");
+//            fileOS = new FileOutputStream(outFile);
+//            try {
+//                fileOS.write(outputStream.toByteArray());
+//            } catch (IOException e) {
+//                e.printStackTrace();
+//            }
+//            fileOS.close();
+//        } catch (FileNotFoundException e1) {
+//            e1.printStackTrace();
+//        }
+//    }
+    
 
-        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
-        for (Module module : modules) {
-            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
-                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
-                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
-                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);
-                } catch (IOException e) {
-                    System.out.println("Output file wasn't cloased sucessfuly.");
-                }
-            }
-        }
-        return jsonResult;
-    }
-
-    private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
-        FileOutputStream fileOS = null;
-        try {
-            String path = YangAndXmlToJsonConversion.class.getResource("/yang-to-json-conversion/xml").getPath();
-            File outFile = new File(path + "/data.json");
-            fileOS = new FileOutputStream(outFile);
-            try {
-                fileOS.write(outputStream.toByteArray());
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            fileOS.close();
-        } catch (FileNotFoundException e1) {
-            e1.printStackTrace();
-        }
-    }
 }
index e76e7bd9ef4f20c5405ef8a71046fcd504047d18..a0e5f2f0f2b804d182b9b1f1c310f61e150e9718 100644 (file)
                         "lf1111B": 7
                     }
                     ]
-                }
+                },
+                "lst111" : [
+                {
+                       "lf1111" : 65
+                       }
+                       ],
+                       "lst112" : [
+                       {
+                       "lf1121" : "lf1121 str11"
+                       }
+                       ]
+                
             },
             {
                 "lf111":141,
                         "lf1111B": 8
                     }
                     ]
-                }
+                },
+                "lst111" : [
+                {
+                       "lf1111" : 55
+                       },
+                {
+                       "lf1111" : 56
+                       }
+                       ],
             }        
         ]
+                       "lst112" : [
+                       {
+                       "lf1121" : "lf1121 str21"
+                       },
+                       {
+                       "lf1121" : "lf1121 str22"
+                       }
+                       ]
+            }
+            ]
     }
 }
\ No newline at end of file