Merge "Reduce verbosity/criticality of inconsistent yangstore messages"
authorEd Warnicke <eaw@cisco.com>
Sun, 26 Jan 2014 03:41:33 +0000 (03:41 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sun, 26 Jan 2014 03:41:33 +0000 (03:41 +0000)
52 files changed:
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/DependencyResolver.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/IdentityAttributeRef.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/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/osgi/ConfigManagerActivator.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/ConfigRegistryImplTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImplLookupTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Field.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/IdentityRefModuleField.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleField.java
opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ModuleMXBeanEntryPluginTest.java
opendaylight/config/yang-jmx-generator/pom.xml
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java
opendaylight/config/yang-test/pom.xml
opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java [new file with mode: 0644]
opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java [new file with mode: 0644]
opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleStub.txt [new file with mode: 0644]
opendaylight/config/yang-test/src/main/yang/config-test-impl.yang
opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleBinaryAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleCompositeAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleIdentityRefAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleUnionAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleAttributeWritingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleIdentityRefAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ServiceRegistryWrapper.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_identities.xml [new file with mode: 0644]

index 3984545..b020000 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.controller.config.api;
 
-import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
 import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+
+import javax.management.ObjectName;
 
 /**
  * Each new {@link org.opendaylight.controller.config.spi.Module} can receive
@@ -49,4 +50,15 @@ public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
     <T> T resolveInstance(Class<T> expectedType, ObjectName objectName,
             JmxAttribute jmxAttribute);
 
+    // TODO finish javadoc
+
+    /**
+     * To be used during commit phase to resolve identity-ref config attributes.
+     *
+     * @return actual class object generated from identity
+     */
+    <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass);
+
+    <T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute);
+
 }
diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/IdentityAttributeRef.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/IdentityAttributeRef.java
new file mode 100644 (file)
index 0000000..7373759
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.api;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+
+import java.beans.ConstructorProperties;
+
+public final class IdentityAttributeRef {
+
+    public static final String QNAME_ATTR_NAME = "qNameOfIdentity";
+
+    private final String qNameOfIdentity;
+
+    @ConstructorProperties(QNAME_ATTR_NAME)
+    public IdentityAttributeRef(String qNameOfIdentity) {
+        if (qNameOfIdentity == null)
+            throw new NullPointerException("Parameter " + QNAME_ATTR_NAME + " is null");
+        this.qNameOfIdentity = qNameOfIdentity;
+    }
+
+    public String getqNameOfIdentity() {
+        return qNameOfIdentity;
+    }
+
+    public <T extends BaseIdentity> Class<? extends T> resolveIdentity(DependencyResolver resolver, Class<T> baseIdentity) {
+        return resolver.resolveIdentity(this, baseIdentity);
+    }
+
+    public <T extends BaseIdentity> void validateIdentity(DependencyResolver resolver, Class<T> baseIdentity, JmxAttribute jmxAttribute) {
+        resolver.validateIdentity(this, baseIdentity, jmxAttribute);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer sb = new StringBuffer("IdentityAttributeRef{");
+        sb.append("qNameOfIdentity='").append(qNameOfIdentity).append('\'');
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof IdentityAttributeRef)) return false;
+
+        IdentityAttributeRef that = (IdentityAttributeRef) o;
+
+        if (!qNameOfIdentity.equals(that.qNameOfIdentity)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return qNameOfIdentity.hashCode();
+    }
+
+}
index a8406b0..39682fa 100644 (file)
@@ -27,6 +27,7 @@ import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil;
 import org.opendaylight.controller.config.manager.impl.util.ModuleQNameUtil;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,6 +61,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
     private final ModuleFactoriesResolver resolver;
     private final MBeanServer configMBeanServer;
+    private final CodecRegistry codecRegistry;
 
     @GuardedBy("this")
     private long version = 0;
@@ -107,19 +109,20 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
     // constructor
     public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
-            MBeanServer configMBeanServer) {
+            MBeanServer configMBeanServer, CodecRegistry codecRegistry) {
         this(resolver, configMBeanServer,
-                new BaseJMXRegistrator(configMBeanServer));
+                new BaseJMXRegistrator(configMBeanServer), codecRegistry);
     }
 
     // constructor
     public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
             MBeanServer configMBeanServer,
-            BaseJMXRegistrator baseJMXRegistrator) {
+            BaseJMXRegistrator baseJMXRegistrator, CodecRegistry codecRegistry) {
         this.resolver = resolver;
         this.beanToOsgiServiceManager = new BeanToOsgiServiceManager();
         this.configMBeanServer = configMBeanServer;
         this.baseJMXRegistrator = baseJMXRegistrator;
+        this.codecRegistry = codecRegistry;
         this.registryMBeanServer = MBeanServerFactory
                 .createMBeanServer("ConfigRegistry" + configMBeanServer.getDefaultDomain());
         this.transactionsMBeanServer = MBeanServerFactory
@@ -161,7 +164,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
                 readableSRRegistry, txLookupRegistry, allCurrentFactories);
 
         ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
-                txLookupRegistry, version,
+                txLookupRegistry, version, codecRegistry,
                 versionCounter, allCurrentFactories, transactionsMBeanServer,
                 configMBeanServer, blankTransaction, writableRegistry);
         try {
index 90d2cb4..0ec6969 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXR
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -82,11 +83,10 @@ class ConfigTransactionControllerImpl implements
     private final ServiceReferenceWritableRegistry writableSRRegistry;
 
     public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
-                                           long parentVersion, long currentVersion,
-                                           Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
+                                           long parentVersion, CodecRegistry codecRegistry, long currentVersion,
+                                           Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
                                            MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
                                            boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) {
-
         this.txLookupRegistry = txLookupRegistry;
         String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
         this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
@@ -95,7 +95,7 @@ class ConfigTransactionControllerImpl implements
         this.currentlyRegisteredFactories = currentlyRegisteredFactories;
         this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
         this.transactionStatus = new TransactionStatus();
-        this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus, writableSRRegistry);
+        this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus, writableSRRegistry, codecRegistry);
         this.transactionsMBeanServer = transactionsMBeanServer;
         this.configMBeanServer = configMBeanServer;
         this.blankTransaction = blankTransaction;
index 925a57b..ec9678f 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
 import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
@@ -17,6 +18,12 @@ 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.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.annotation.concurrent.GuardedBy;
 import javax.management.ObjectName;
@@ -33,17 +40,20 @@ import static java.lang.String.format;
  */
 final class DependencyResolverImpl implements DependencyResolver,
        Comparable<DependencyResolverImpl> {
+    private static final Logger logger = LoggerFactory.getLogger(DependencyResolverImpl.class);
+
     private final ModulesHolder modulesHolder;
     private final ModuleIdentifier name;
     private final TransactionStatus transactionStatus;
     @GuardedBy("this")
     private final Set<ModuleIdentifier> dependencies = new HashSet<>();
     private final ServiceReferenceReadableRegistry readableRegistry;
+    private final CodecRegistry codecRegistry;
 
     DependencyResolverImpl(ModuleIdentifier currentModule,
-            TransactionStatus transactionStatus, ModulesHolder modulesHolder,
-            ServiceReferenceReadableRegistry readableRegistry) {
-
+                           TransactionStatus transactionStatus, ModulesHolder modulesHolder,
+                           ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
+        this.codecRegistry = codecRegistry;
         this.name = currentModule;
         this.transactionStatus = transactionStatus;
         this.modulesHolder = modulesHolder;
@@ -68,7 +78,7 @@ final class DependencyResolverImpl implements DependencyResolver,
             throw new NullPointerException("Parameter 'jmxAttribute' is null");
 
         JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
-                "is null, " + "expected dependency implementing "
+                "is null, expected dependency implementing "
                         + expectedServiceInterface, jmxAttribute);
 
 
@@ -128,7 +138,7 @@ final class DependencyResolverImpl implements DependencyResolver,
             JmxAttribute jmxAttribute) {
         if (expectedType == null || dependentReadOnlyON == null || jmxAttribute == null) {
             throw new IllegalArgumentException(format(
-                    "Null parameters not allowed, got {} {} {}", expectedType,
+                    "Null parameters not allowed, got %s %s %s", expectedType,
                     dependentReadOnlyON, jmxAttribute));
         }
         dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
@@ -162,6 +172,33 @@ final class DependencyResolverImpl implements DependencyResolver,
         }
     }
 
+    @Override
+    public <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass) {
+        final QName qName = QName.create(identityRef.getqNameOfIdentity());
+        IdentityCodec<?> identityCodec = codecRegistry.getIdentityCodec();
+        Class<? extends BaseIdentity> deserialized = identityCodec.deserialize(qName);
+        if (deserialized == null) {
+            throw new RuntimeException("Unable to retrieve identity class for " + qName + ", null response from "
+                    + codecRegistry);
+        }
+        if (expectedBaseClass.isAssignableFrom(deserialized)) {
+            return (Class<T>) deserialized;
+        } else {
+            logger.error("Cannot resolve class of identity {} : deserialized class {} is not a subclass of {}.",
+                    identityRef, deserialized, expectedBaseClass);
+            throw new IllegalArgumentException("Deserialized identity " + deserialized + " cannot be cast to " + expectedBaseClass);
+        }
+    }
+
+    @Override
+    public <T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute) {
+        try {
+            resolveIdentity(identityRef, expectedBaseClass);
+        } catch(Exception e) {
+            throw JmxAttributeValidationException.wrap(e, jmxAttribute);
+        }
+    }
+
     @Override
     public int compareTo(DependencyResolverImpl o) {
         transactionStatus.checkCommitted();
@@ -198,7 +235,7 @@ final class DependencyResolverImpl implements DependencyResolver,
                     .getOrCreate(dependencyName);
             if (chainForDetectingCycles2.contains(dependencyName)) {
                 throw new IllegalStateException(format(
-                        "Cycle detected, {} contains {}",
+                        "Cycle detected, %s contains %s",
                         chainForDetectingCycles2, dependencyName));
             }
             int subDepth;
index afd865c..c115934 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.controller.config.manager.impl.ModuleInternalTransaction
 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.yang.data.impl.codec.CodecRegistry;
 
 import javax.annotation.concurrent.GuardedBy;
 import javax.management.InstanceAlreadyExistsException;
@@ -37,12 +38,14 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
     private final ModulesHolder modulesHolder;
     private final TransactionStatus transactionStatus;
     private final ServiceReferenceReadableRegistry readableRegistry;
+    private final CodecRegistry codecRegistry;
 
     public DependencyResolverManager(String transactionName,
-            TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry) {
+                                     TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
         this.modulesHolder = new ModulesHolder(transactionName);
         this.transactionStatus = transactionStatus;
         this.readableRegistry = readableRegistry;
+        this.codecRegistry = codecRegistry;
     }
 
     @Override
@@ -54,7 +57,7 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
         DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name);
         if (dependencyResolver == null) {
             transactionStatus.checkNotCommitted();
-            dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry);
+            dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry, codecRegistry);
             moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
         }
         return dependencyResolver;
index 57aa74c..e4e0708 100644 (file)
@@ -56,7 +56,7 @@ public class ConfigManagerActivator implements BundleActivator {
         // TODO push codecRegistry/IdentityCodec to dependencyResolver
 
         configRegistry = new ConfigRegistryImpl(
-                bundleContextBackedModuleFactoriesResolver, configMBeanServer);
+                bundleContextBackedModuleFactoriesResolver, configMBeanServer, codecRegistry);
 
         // register config registry to OSGi
         configRegistryServiceRegistration = context.registerService(ConfigRegistryImpl.class, configRegistry, null);
index e6b07ba..9178dc4 100644 (file)
@@ -40,7 +40,7 @@ public class ConfigRegistryImplTest extends
                     factory, factory);
 
             configRegistry = new ConfigRegistryImpl(resolver,
-                    ManagementFactory.getPlatformMBeanServer());
+                    ManagementFactory.getPlatformMBeanServer(), null);
 
             configRegistry.beginConfig();
             fail();
index 64ce14e..d9bbeb4 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.controller.config.manager.testingservices.threadpool.Tes
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
@@ -97,7 +98,7 @@ public abstract class AbstractConfigTest extends
         baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
 
         configRegistry = new ConfigRegistryImpl(resolver,
-                platformMBeanServer, baseJmxRegistrator);
+                platformMBeanServer, baseJmxRegistrator, getCodecRegistry());
 
         try {
             configRegistryJMXRegistrator.registerToJMX(configRegistry);
@@ -208,6 +209,10 @@ public abstract class AbstractConfigTest extends
         return new ClassBasedModuleFactory(implementationName, configBeanClass);
     }
 
+    protected CodecRegistry getCodecRegistry() {
+        return mock(CodecRegistry.class);
+    }
+
 
     public static interface BundleContextServiceRegistrationHandler {
 
@@ -215,10 +220,10 @@ public abstract class AbstractConfigTest extends
 
     }
 
-    private class RegisterServiceAnswer implements Answer {
+    private class RegisterServiceAnswer implements Answer<ServiceRegistration<?>> {
 
         @Override
-        public Object answer(InvocationOnMock invocation) throws Throwable {
+        public ServiceRegistration<?> answer(InvocationOnMock invocation) throws Throwable {
             Object[] args = invocation.getArguments();
 
             Preconditions.checkArgument(args.length == 3, "Unexpected arguments size (expected 3 was %s)", args.length);
index a522356..7a4b46f 100644 (file)
@@ -67,7 +67,7 @@ public class ConfigRegistryImplLookupTest extends
     @Before
     public void setUp() throws Exception {
         configRegistryImpl = new ConfigRegistryImpl(null,
-                ManagementFactory.getPlatformMBeanServer());
+                ManagementFactory.getPlatformMBeanServer(), null);
         Field field = configRegistryImpl.getClass().getDeclaredField(
                 "baseJMXRegistrator");
         field.setAccessible(true);
index 50f5742..09aea08 100644 (file)
@@ -75,7 +75,7 @@ public class ConfigTransactionControllerImplTest extends
 
 
         testedTxController = new ConfigTransactionControllerImpl(
-                txLookupRegistry, 1, 1,
+                txLookupRegistry, 1, null, 1,
                 currentlyRegisteredFactories, transactionsMBeanServer,
                 ManagementFactory.getPlatformMBeanServer(), false, writableRegistry);
         TransactionModuleJMXRegistrator transactionModuleJMXRegistrator123 = testedTxController
index 31e70bd..63a66e9 100644 (file)
@@ -42,7 +42,7 @@ public class DependencyResolverManagerTest {
     public void setUp() {
         transactionStatus = mock(TransactionStatus.class);
         ServiceReferenceReadableRegistry mockedRegistry = mock(ServiceReferenceReadableRegistry.class);
-        tested = new DependencyResolverManager("txName", transactionStatus, mockedRegistry);
+        tested = new DependencyResolverManager("txName", transactionStatus, mockedRegistry, null);
         doNothing().when(transactionStatus).checkCommitStarted();
         doNothing().when(transactionStatus).checkNotCommitted();
     }
index 49a20bd..fea9a79 100644 (file)
@@ -12,6 +12,8 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
 import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
 import org.opendaylight.controller.config.api.runtime.RuntimeBean;
@@ -35,6 +37,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Anno
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Constructor;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Header;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.IdentityRefModuleField;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.MethodDeclaration;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.MethodDefinition;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField;
@@ -42,6 +45,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQual
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 
 import javax.management.openmbean.SimpleType;
 import java.util.ArrayList;
@@ -153,12 +157,12 @@ public class TemplateFactory {
     }
 
     // FIXME: put into Type.toString
-    static String serializeType(Type type) {
+    static String serializeType(Type type, boolean addWildcards) {
         if (type instanceof ParameterizedType){
             ParameterizedType parameterizedType = (ParameterizedType) type;
             StringBuffer sb = new StringBuffer();
             sb.append(parameterizedType.getRawType().getFullyQualifiedName());
-            sb.append("<");
+            sb.append(addWildcards ? "<? extends " : "<");
             boolean first = true;
             for(Type parameter: parameterizedType.getActualTypeArguments()) {
                 if (first) {
@@ -175,6 +179,14 @@ public class TemplateFactory {
         }
     }
 
+    static String serializeType(Type type) {
+        return serializeType(type, false);
+    }
+
+    private static boolean isIdentityRefType(Type type) {
+        return type instanceof IdentityrefTypeDefinition;
+    }
+
 
     private static String getReturnType(AttributeIfc attributeIfc) {
         String returnType;
@@ -424,10 +436,19 @@ public class TemplateFactory {
                 processAttrs(attrs, packageName);
             }
 
+            private final static String dependencyResolverVarName = "dependencyResolver";
+            private final static String dependencyResolverInjectMethodName = "injectDependencyResolver";
+
             private void processAttrs(Map<String, AttributeIfc> attrs, String packageName) {
                 fields = Lists.newArrayList();
                 methods = Lists.newArrayList();
 
+                // FIXME conflict if "dependencyResolver" field from yang
+                Field depRes = new Field(DependencyResolver.class.getName(), dependencyResolverVarName);
+                fields.add(depRes);
+                methods.add(new MethodDefinition("void", dependencyResolverInjectMethodName, Lists.newArrayList(depRes),
+                        "this." + dependencyResolverVarName + " = " + dependencyResolverVarName + ";"));
+
                 for (Entry<String, AttributeIfc> attrEntry : attrs.entrySet()) {
                     String innerName = attrEntry.getKey();
                     String varName = BindingGeneratorUtil
@@ -436,15 +457,23 @@ public class TemplateFactory {
                     String fullyQualifiedName, nullableDefault = null;
                     if (attrEntry.getValue() instanceof TypedAttribute) {
                         Type type = ((TypedAttribute) attrEntry.getValue()).getType();
-                        fullyQualifiedName = serializeType(type);
                         if(attrEntry.getValue() instanceof JavaAttribute) {
                             nullableDefault = ((JavaAttribute)attrEntry.getValue()).getNullableDefaultWrappedForCode();
+                            if(((JavaAttribute)attrEntry.getValue()).isIdentityRef()) {
+
+                                String fieldType = serializeType(type, true);
+                                String innerType = getInnerTypeFromIdentity(type);
+                                methods.add(new MethodDefinition(fieldType, "resolve" + attrEntry.getKey(), Collections.<Field>emptyList(),
+                                        "return " + varName + ".resolveIdentity(" + dependencyResolverVarName + "," +  innerType + ".class);"));
+                                type = identityRefType;
+                            }
                         }
+                        fullyQualifiedName = serializeType(type);
                     } else {
                         fullyQualifiedName = FullyQualifiedNameHelper
                                 .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
                     }
-                    fields.add(new Field(fullyQualifiedName, varName, nullableDefault));
+                    fields.add(new Field(fullyQualifiedName, varName, nullableDefault, needsDepResolver(attrEntry.getValue())));
 
                     String getterName = "get" + innerName;
                     MethodDefinition getter = new MethodDefinition(
@@ -481,6 +510,7 @@ public class TemplateFactory {
         }
     }
 
+
     private static class MXBeanInterfaceAttributesProcessor {
         private final List<MethodDeclaration> methods = Lists.newArrayList();
 
@@ -489,9 +519,15 @@ public class TemplateFactory {
                 String returnType;
                 AttributeIfc attributeIfc = attrEntry.getValue();
 
+                boolean isIdentityRef = false;
                 if (attributeIfc instanceof TypedAttribute) {
                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
                     returnType = serializeType(typedAttribute.getType());
+
+                    if (attributeIfc instanceof JavaAttribute && ((JavaAttribute)attrEntry.getValue()).isIdentityRef()) {
+                        returnType = serializeType(identityRefType);
+                    }
+
                 } else {
                     throw new UnsupportedOperationException(
                             "Attribute not supported: "
@@ -510,6 +546,7 @@ public class TemplateFactory {
                 MethodDeclaration setter = new MethodDeclaration("void",
                         setterName, Lists.newArrayList(new Field(returnType,
                                 varName)));
+
                 methods.add(getter);
                 methods.add(setter);
 
@@ -525,10 +562,28 @@ public class TemplateFactory {
         }
     }
 
+    private static final Type identityRefType = new Type() {
+        public final Class<IdentityAttributeRef> IDENTITY_ATTRIBUTE_REF_CLASS = IdentityAttributeRef.class;
+
+        @Override
+        public String getPackageName() {
+            return IDENTITY_ATTRIBUTE_REF_CLASS.getPackage().getName();
+        }
+
+        @Override
+        public String getName() {
+            return IDENTITY_ATTRIBUTE_REF_CLASS.getSimpleName();
+        }
+
+        @Override
+        public String getFullyQualifiedName() {
+            return IDENTITY_ATTRIBUTE_REF_CLASS.getName();
+        }
+    };
+
     private static class AbstractFactoryAttributesProcessor {
 
         private final List<Field> fields = Lists.newArrayList();
-        private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
 
         void processAttributes(Map<String, AttributeIfc> attributes,
                 String packageName) {
@@ -540,27 +595,6 @@ public class TemplateFactory {
                 if (attributeIfc instanceof TypedAttribute) {
                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
                     type = serializeType(typedAttribute.getType());
-                } else if (attributeIfc instanceof TOAttribute) {
-                    String fullyQualifiedName = FullyQualifiedNameHelper
-                            .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
-
-                    type = fullyQualifiedName;
-                } else if (attributeIfc instanceof ListAttribute) {  //FIXME: listAttribute might extend TypedAttribute
-                    String fullyQualifiedName = null;
-                    AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
-                            .getInnerAttribute();
-                    if (innerAttr instanceof JavaAttribute) {
-                        fullyQualifiedName = ((JavaAttribute) innerAttr)
-                                .getType().getFullyQualifiedName();
-                        nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
-                    } else if (innerAttr instanceof TOAttribute) {
-                        fullyQualifiedName = FullyQualifiedNameHelper
-                                .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
-                    }
-
-                    type = STRING_FULLY_QUALIFIED_NAME.concat("<")
-                            .concat(fullyQualifiedName).concat(">");
-
                 } else {
                     throw new UnsupportedOperationException(
                             "Attribute not supported: "
@@ -579,8 +613,6 @@ public class TemplateFactory {
 
     private static class AbstractModuleAttributesProcessor {
 
-        private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
-
         private final List<ModuleField> moduleFields = Lists.newArrayList();
         private final List<MethodDefinition> methods = Lists.newArrayList();
 
@@ -589,34 +621,19 @@ public class TemplateFactory {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 String type, nullableDefaultWrapped = null;
                 AttributeIfc attributeIfc = attrEntry.getValue();
+                boolean isIdentity = false;
+                boolean needsDepResolver = needsDepResolver(attrEntry.getValue());
 
                 if (attributeIfc instanceof TypedAttribute) {
                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
                     type = serializeType(typedAttribute.getType());
                     if (attributeIfc instanceof JavaAttribute) {
                         nullableDefaultWrapped = ((JavaAttribute) attributeIfc).getNullableDefaultWrappedForCode();
+                        if(((JavaAttribute)attrEntry.getValue()).isIdentityRef()) {
+                            isIdentity = true;
+                            type = serializeType(typedAttribute.getType(), true);
+                        }
                     }
-
-                } else if (attributeIfc instanceof TOAttribute) {
-                    String fullyQualifiedName = FullyQualifiedNameHelper
-                            .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
-
-                    type = fullyQualifiedName;
-                } else if (attributeIfc instanceof ListAttribute) {
-                    String fullyQualifiedName = null;
-                    AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
-                            .getInnerAttribute();
-                    if (innerAttr instanceof JavaAttribute) {
-                        fullyQualifiedName = ((JavaAttribute) innerAttr)
-                                .getType().getFullyQualifiedName();
-                        nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
-                    } else if (innerAttr instanceof TOAttribute) {
-                        fullyQualifiedName = FullyQualifiedNameHelper
-                                .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
-                    }
-
-                    type = STRING_FULLY_QUALIFIED_NAME.concat("<")
-                            .concat(fullyQualifiedName).concat(">");
                 } else {
                     throw new UnsupportedOperationException(
                             "Attribute not supported: "
@@ -644,15 +661,49 @@ public class TemplateFactory {
 
                 String varName = BindingGeneratorUtil
                         .parseToValidParamName(attrEntry.getKey());
-                moduleFields.add(new ModuleField(type, varName, attributeIfc
-                        .getUpperCaseCammelCase(), nullableDefaultWrapped, isDependency, dependency, isListOfDependencies));
+
+                ModuleField field;
+
+                if (isIdentity) {
+                    String identityBaseClass = getInnerTypeFromIdentity(((TypedAttribute) attributeIfc).getType());
+                    IdentityRefModuleField identityField = new IdentityRefModuleField(type, varName,
+                            attributeIfc.getUpperCaseCammelCase(), identityBaseClass);
+
+                    String getterName = "get"
+                            + attributeIfc.getUpperCaseCammelCase() + "Identity";
+                    MethodDefinition additionalGetter = new MethodDefinition(type, getterName, Collections.<Field> emptyList(),
+                            Collections.<Annotation> emptyList(), "return " + identityField.getIdentityClassName()
+                                    + ";");
+                    methods.add(additionalGetter);
+
+                    String setterName = "set"
+                            + attributeIfc.getUpperCaseCammelCase();
+
+                    String setterBody = "this." + identityField.getIdentityClassName() + " = " + identityField.getIdentityClassName() + ";";
+                    MethodDefinition additionalSetter = new MethodDefinition("void",
+                            setterName,
+                            Lists.newArrayList(new Field(type, identityField.getIdentityClassName())),
+                            Collections.<Annotation> emptyList(), setterBody);
+                    additionalSetter.setJavadoc(attributeIfc.getNullableDescription());
+
+                    methods.add(additionalSetter);
+
+                    type = serializeType(identityRefType);
+                    field = identityField;
+                } else {
+                    field = new ModuleField(type, varName, attributeIfc.getUpperCaseCammelCase(),
+                            nullableDefaultWrapped, isDependency, dependency, isListOfDependencies, needsDepResolver);
+                }
+                moduleFields.add(field);
 
                 String getterName = "get"
                         + attributeIfc.getUpperCaseCammelCase();
                 MethodDefinition getter = new MethodDefinition(type,
                         getterName, Collections.<Field> emptyList(),
                         Lists.newArrayList(overrideAnnotation), "return "
-                                + varName + ";");
+                        + varName + ";");
+
+                methods.add(getter);
 
                 String setterName = "set"
                         + attributeIfc.getUpperCaseCammelCase();
@@ -674,7 +725,6 @@ public class TemplateFactory {
                         annotations, setterBody);
                 setter.setJavadoc(attributeIfc.getNullableDescription());
 
-                methods.add(getter);
                 methods.add(setter);
             }
         }
@@ -689,4 +739,22 @@ public class TemplateFactory {
 
     }
 
+
+    private static boolean needsDepResolver(AttributeIfc value) {
+        if(value instanceof TOAttribute)
+            return true;
+        if(value instanceof ListAttribute) {
+            AttributeIfc innerAttribute = ((ListAttribute) value).getInnerAttribute();
+            return needsDepResolver(innerAttribute);
+        }
+
+        return false;
+    }
+
+    private static String getInnerTypeFromIdentity(Type type) {
+        Preconditions.checkArgument(type instanceof ParameterizedType);
+        Type[] args = ((ParameterizedType) type).getActualTypeArguments();
+        Preconditions.checkArgument(args.length ==1);
+        return serializeType(args[0]);
+    }
 }
index 0857ec6..ad5cbb2 100644 (file)
@@ -16,25 +16,40 @@ public class Field {
     private final String name;
     private final String definition;
     private final List<String> modifiers;
+    private final boolean needsDepResolver;
 
     public Field(String type, String name) {
-        this(Lists.<String> newArrayList(), type, name, null);
+        this(Lists.<String> newArrayList(), type, name, null, false);
     }
 
     public Field(String type, String name, String definition) {
-        this(Lists.<String> newArrayList(), type, name, definition);
+        this(Lists.<String> newArrayList(), type, name, definition, false);
     }
 
     public Field(List<String> modifiers, String type, String name) {
-        this(modifiers, type, name, null);
+        this(modifiers, type, name, null, false);
     }
 
     public Field(List<String> modifiers, String type, String name,
             String definition) {
+        this(modifiers, type, name, definition, false);
+    }
+
+    public Field(List<String> modifiers, String type, String name,
+            String definition, boolean needsDepResolver) {
         this.modifiers = modifiers;
         this.type = type;
         this.name = name;
         this.definition = definition;
+        this.needsDepResolver = needsDepResolver;
+    }
+
+    public Field(String type, String name, String definition, boolean needsDepResolver) {
+        this(Lists.<String> newArrayList(), type, name, definition, needsDepResolver);
+    }
+
+    public boolean isNeedsDepResolver() {
+        return needsDepResolver;
     }
 
     public String getType() {
diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/IdentityRefModuleField.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/IdentityRefModuleField.java
new file mode 100644 (file)
index 0000000..f50bdb9
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model;
+
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
+
+public class IdentityRefModuleField extends ModuleField {
+
+    public static final String IDENTITY_CLASS_FIELD_SUFFIX = "IdentityClass";
+    private final String identityBaseClass;
+
+    public IdentityRefModuleField(String type, String name, String attributeName, String identityBaseClass) {
+        super(type, name, attributeName, null, false, null, false, false);
+        this.identityBaseClass = identityBaseClass;
+    }
+
+    public String getIdentityBaseClass() {
+        return identityBaseClass;
+    }
+
+    @Override
+    public boolean isIdentityRef() {
+        return true;
+    }
+
+    public String getType() {
+        return IdentityAttributeRef.class.getName();
+    }
+
+    public String getIdentityClassType() {
+        return super.getType();
+    }
+
+    public String getIdentityClassName() {
+        return addIdentityClassFieldSuffix(getName());
+    }
+
+    public static String addIdentityClassFieldSuffix(String prefix) {
+        return prefix + IDENTITY_CLASS_FIELD_SUFFIX;
+    }
+}
index aff7af2..74e5bb0 100644 (file)
@@ -20,10 +20,9 @@ public class ModuleField extends Field {
     private final boolean dependent, isListOfDependencies;
     private final Dependency dependency;
 
-    private ModuleField(List<String> modifiers, String type, String name,
-            String attributeName, String nullableDefault, boolean isDependency,
-            Dependency dependency, boolean isListOfDependencies) {
-        super(modifiers, type, name);
+    private ModuleField(List<String> modifiers, String type, String name, String attributeName, String nullableDefault,
+            boolean isDependency, Dependency dependency, boolean isListOfDependencies, boolean needsDepResolver) {
+        super(modifiers, type, name, null, needsDepResolver);
         this.dependent = isDependency;
         this.dependency = dependency;
         this.attributeName = attributeName;
@@ -35,10 +34,14 @@ public class ModuleField extends Field {
         this.isListOfDependencies = isListOfDependencies;
     }
 
-    public ModuleField(String type, String name, String attributeName,
-            String nullableDefault, boolean isDependency, Dependency dependency, boolean isListOfDependencies) {
-        this(Collections.<String> emptyList(), type, name, attributeName,
-                nullableDefault, isDependency, dependency, isListOfDependencies);
+    public ModuleField(String type, String name, String attributeName, String nullableDefault, boolean isDependency,
+            Dependency dependency, boolean isListOfDependencies, boolean needsDepResolve) {
+        this(Collections.<String> emptyList(), type, name, attributeName, nullableDefault, isDependency, dependency,
+                isListOfDependencies, needsDepResolve);
+    }
+
+    public boolean isIdentityRef() {
+        return false;
     }
 
     public Dependency getDependency() {
index 7192ac6..848fcfe 100644 (file)
@@ -85,6 +85,12 @@ package ${packageName};
     </#if>
     </#list>
 
+    // caches of resolved IdentityRefs
+    <#list moduleFields as field>
+    <#if field.identityRef==true>
+        private ${field.identityClassType} ${field.identityClassName};
+    </#if>
+    </#list>
 
     @Override
     public final ${instanceType} getInstance(){
@@ -109,6 +115,24 @@ package ${packageName};
                         }
                     </#if>
                 </#if>
+
+                <#if field.needsDepResolver==true>
+            if(${field.name} != null) {
+                    <#if field.type?starts_with("java.util.List")>
+                for(${field.type?substring(field.type?index_of("<") + 1, field.type?index_of(">"))} candidate : ${field.name}) {
+                    candidate.injectDependencyResolver(dependencyResolver);
+                }
+                    <#else>
+                ${field.name}.injectDependencyResolver(dependencyResolver);
+                    </#if>
+            }
+                </#if>
+
+                <#if field.identityRef==true>
+            if(${field.name} != null) {
+                set${field.attributeName}(${field.name}.resolveIdentity(dependencyResolver, ${field.identityBaseClass}.class));
+            }
+                </#if>
             </#list>
 
             if(oldInstance!=null && canReuseInstance(oldModule)) {
index b457216..473b245 100644 (file)
@@ -130,7 +130,7 @@ public class ModuleMXBeanEntryPluginTest extends ModuleMXBeanEntryTest {
                         is(true));
                 assertThat(peerTO.getFullyQualifiedName(), is(PACKAGE_NAME
                         + ".Peer"));
-                assertThat(peerTO.getMethods().size(), is(4));
+                assertThat(peerTO.getMethods().size(), is(5));
                 Method getPort = findFirstMethodByName(peerTO.getMethods(),
                         "getPort");
                 assertNotNull(getPort);
index b5069a1..9993c2f 100644 (file)
@@ -44,7 +44,6 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>config-api</artifactId>
-            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
index e01063e..5b0196c 100644 (file)
@@ -8,11 +8,13 @@
 package org.opendaylight.controller.config.yangjmxgenerator.attribute;
 
 import com.google.common.base.Preconditions;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 
 import javax.management.openmbean.ArrayType;
@@ -36,6 +38,7 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
             TypeProviderWrapper typeProviderWrapper) {
         super(leaf);
         this.type = typeProviderWrapper.getType(leaf);
+
         this.typeDefinition = leaf.getType();
         this.typeProviderWrapper = typeProviderWrapper;
         this.nullableDefault = leaf.getDefault();
@@ -147,11 +150,17 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
             return getCompositeTypeForUnion(baseTypeDefinition);
         } else if (isDerivedType(baseType, getType())) {
             return getCompositeType(baseType, baseTypeDefinition);
+        } else if (isIdentityRef()) {
+            return getCompositeTypeForIdentity();
         }
 
         return getSimpleType(getType());
     }
 
+    public boolean isIdentityRef() {
+        return typeDefinition instanceof IdentityrefTypeDefinition;
+    }
+
     private OpenType<?> getCompositeTypeForUnion(TypeDefinition<?> baseTypeDefinition) {
         Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
                 "Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
@@ -233,6 +242,19 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         }
     }
 
+    public OpenType<?> getCompositeTypeForIdentity() {
+        String[] itemNames = new String[]{IdentityAttributeRef.QNAME_ATTR_NAME};
+        String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
+        OpenType<?>[] itemTypes = new OpenType[]{SimpleType.STRING};
+
+        try {
+            return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
+        } catch (OpenDataException e) {
+            throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
+                    + itemTypes, e);
+        }
+    }
+
     private OpenType<?> getArrayType() {
         String innerTypeFullyQName = getInnerType(getType());
         SimpleType<?> innerSimpleType = SimpleTypeResolver.getSimpleType(innerTypeFullyQName);
@@ -263,7 +285,7 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
     }
 
     private boolean isDerivedType(Type baseType, Type currentType) {
-        return  baseType.equals(currentType) == false;
+        return baseType.equals(currentType) == false;
     }
 
     private static String getInnerType(Type type) {
index b9f9235..10d62ed 100644 (file)
@@ -12,6 +12,7 @@
     </parent>
 
     <artifactId>yang-test</artifactId>
+    <packaging>bundle</packaging>
 
     <description>Artifact that contains only generated code from yang files. Suitable for testing.
     </description>
                     </execution>
                 </executions>
             </plugin>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                    </instructions>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 </project>
diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java
new file mode 100644 (file)
index 0000000..b000f11
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.yang.test.impl;
+
+/**
+*
+*/
+public final class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule
+ {
+
+    public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            IdentityTestModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    protected void customValidation(){
+        // Add custom validation for module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        System.err.println(getAfi());
+        System.err.println(getAfiIdentity());
+
+        getAfiIdentity();
+        for (Identities identities : getIdentities()) {
+            identities.resolveAfi();
+            identities.resolveSafi();
+        }
+        getIdentitiesContainer().resolveAfi();
+
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+            }
+        };
+
+    }
+}
diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java
new file mode 100644 (file)
index 0000000..9de3e0b
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.yang.test.impl;
+
+/**
+*
+*/
+public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory
+{
+
+
+}
diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleStub.txt b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleStub.txt
new file mode 100644 (file)
index 0000000..a81159e
--- /dev/null
@@ -0,0 +1,15 @@
+        System.err.println(getAfi());
+        System.err.println(getAfiIdentity());
+
+        getAfiIdentity();
+        for (Identities identities : getIdentities()) {
+            identities.resolveAfi();
+            identities.resolveSafi();
+        }
+        getIdentitiesContainer().resolveAfi();
+
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+            }
+        };
index f7cea0a..6ee3796 100644 (file)
@@ -35,6 +35,69 @@ module config-test-impl {
         config:java-name-prefix NetconfTestImpl;
     }
 
+    identity impl-identity-test {
+        base config:module-type;
+        config:provided-service test:testing;
+        config:java-name-prefix IdentityTest;
+    }
+
+    identity test-identity1 {
+
+    }
+
+    identity test-identity2 {
+        base test-identity1;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+            case impl-identity-test {
+                when "/config:modules/config:module/config:type = 'impl-identity-test'";
+
+                leaf afi {
+                    type identityref {
+                        base test-identity1;
+                    }
+                }
+
+                container identities-container {
+                    leaf afi {
+                        type identityref {
+                            base test-identity1;
+                        }
+                    }
+                }
+
+                list identities {
+                    leaf afi {
+                        type identityref {
+                            base test-identity1;
+                        }
+                    }
+                    leaf safi {
+                        type identityref {
+                            base test-identity1;
+                        }
+                    }
+
+                    container identities-inner {
+                        leaf afi {
+                            type identityref {
+                                base test-identity1;
+                            }
+                        }
+                    }
+                }
+
+            }
+        }
+
+        augment "/config:modules/config:module/config:state" {
+            case impl-identity-test {
+                when "/config:modules/config:module/config:type = 'impl-identity-test'";
+
+            }
+        }
+
 
     augment "/config:modules/config:module/config:configuration" {
         case impl {
index 41ceab0..5a4cfc1 100644 (file)
@@ -1,17 +1,25 @@
 package org.opendaylight.controller.config.yang.test.impl;
 
 import com.google.common.collect.Lists;
+
 import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity2;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
 
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.ObjectName;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -20,6 +28,8 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
 public class NetconfTestImplModuleTest  extends AbstractConfigTest {
 
@@ -32,7 +42,31 @@ public class NetconfTestImplModuleTest  extends AbstractConfigTest {
 
         factory = new NetconfTestImplModuleFactory();
         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
-                new DepTestImplModuleFactory()));
+                new DepTestImplModuleFactory(), new IdentityTestModuleFactory()));
+    }
+
+    @Override
+    protected CodecRegistry getCodecRegistry() {
+        final IdentityCodec<?> codec = mock(IdentityCodec.class);
+        doReturn(TestIdentity1.class).when(codec).deserialize(TestIdentity1.QNAME);
+        doReturn(TestIdentity2.class).when(codec).deserialize(TestIdentity2.QNAME);
+
+        final CodecRegistry ret = super.getCodecRegistry();
+        doReturn(codec).when(ret).getIdentityCodec();
+        return ret;
+    }
+
+    @Test
+    public void testIdentities() throws Exception {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        ObjectName nameCreated = transaction.createModule(IdentityTestModuleFactory.NAME, instanceName);
+        IdentityTestModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, IdentityTestModuleMXBean.class);
+
+        final IdentitiesContainer c = new IdentitiesContainer();
+        c.setAfi(new IdentityAttributeRef(TestIdentity2.QNAME.toString()));
+        mxBean.setIdentitiesContainer(c);
+        transaction.commit();
     }
 
     @Test
index 35c641c..8039156 100644 (file)
@@ -141,7 +141,7 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
     }
     
     override onFlowRemoved(FlowRemoved notification) {
-        flowProgrammerPublisher.flowRemoved(notification.node.toADNode,notification.toFlow());
+        flowProgrammerPublisher.flowRemoved(notification.node.toADNode,notification.toFlow(notification.node.toADNode));
     }
     
     override onFlowUpdated(FlowUpdated notification) {
index 39d224b..6d209f3 100644 (file)
@@ -146,7 +146,7 @@ class InventoryAndReadAdapter implements IPluginInReadService,
                        
                        for(flow : table.flow){
                                
-                               val adsalFlow = ToSalConversionsUtils.toFlow(flow);
+                               val adsalFlow = ToSalConversionsUtils.toFlow(flow,node);
                                val statsFromDataStore = flow.getAugmentation(FlowStatisticsData);
                                
                                if(statsFromDataStore != null){
@@ -517,14 +517,14 @@ class InventoryAndReadAdapter implements IPluginInReadService,
        override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
                
                val adsalFlowsStatistics = new ArrayList<FlowOnNode>();
+               val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
                
                for(flowStats : notification.flowAndStatisticsMapList){
                        if(flowStats.tableId == 0)
-                               adsalFlowsStatistics.add(toFlowOnNode(flowStats));
+                               adsalFlowsStatistics.add(toFlowOnNode(flowStats,nodeRef.toADNode));
                }
                
                for (statsPublisher : statisticsPublisher){
-                       val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
                        statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics);
                }
                
@@ -569,9 +569,9 @@ class InventoryAndReadAdapter implements IPluginInReadService,
                
        }
        
-       private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap){
+       private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap,Node node){
                
-               val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap));
+               val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap,node));
                
                byteCount = flowAndStatsMap.byteCount.value.longValue;
                packetCount = flowAndStatsMap.packetCount.value.longValue;
index 46fd62f..baf10ef 100644 (file)
@@ -43,7 +43,8 @@ import org.opendaylight.controller.sal.action.SetVlanCfi;
 import org.opendaylight.controller.sal.action.SetVlanId;
 import org.opendaylight.controller.sal.action.SetVlanPcp;
 import org.opendaylight.controller.sal.action.SwPath;
-import org.opendaylight.controller.sal.core.Capabilities;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.Match;
@@ -86,7 +87,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
@@ -116,7 +116,7 @@ public class ToSalConversionsUtils {
 
     }
 
-    public static Flow toFlow(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source) {
+    public static Flow toFlow(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source, Node node) {
         final Flow target = new Flow();
 
         Integer hardTimeout = source.getHardTimeout();
@@ -138,7 +138,7 @@ public class ToSalConversionsUtils {
 
         List<Action> actions = getAction(source);
         if (actions != null) {
-            target.setActions(actionFrom(actions));
+            target.setActions(actionFrom(actions, node));
         }
 
         target.setId(source.getCookie().longValue());
@@ -158,7 +158,7 @@ public class ToSalConversionsUtils {
         return Collections.emptyList();
     }
 
-    public static List<org.opendaylight.controller.sal.action.Action> actionFrom(List<Action> actions) {
+    public static List<org.opendaylight.controller.sal.action.Action> actionFrom(List<Action> actions, Node node) {
         List<org.opendaylight.controller.sal.action.Action> targetAction = new ArrayList<>();
         for (Action action : actions) {
                org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action sourceAction = action
@@ -171,7 +171,7 @@ public class ToSalConversionsUtils {
                 Uri nodeConnector = ((OutputActionCase) sourceAction).getOutputAction().getOutputNodeConnector();
                 if (nodeConnector != null) {
                     //for (Uri uri : nodeConnectors) {
-                        targetAction.add(new Output(fromNodeConnectorRef(nodeConnector)));
+                        targetAction.add(new Output(fromNodeConnectorRef(nodeConnector, node)));
                     //}
                 }
             } else if (sourceAction instanceof PopMplsActionCase) {
@@ -339,9 +339,14 @@ public class ToSalConversionsUtils {
         return null;
     }
 
-    private static NodeConnector fromNodeConnectorRef(Uri uri) {
-        // TODO: Define mapping
-        return null;
+    private static NodeConnector fromNodeConnectorRef(Uri uri, Node node) {
+        NodeConnector nodeConnector = null;
+        try {
+            nodeConnector = new NodeConnector(NodeMapping.MD_SAL_TYPE,node.getNodeIDString()+":"+uri.getValue(),node);
+        } catch (ConstructionException e) {
+            e.printStackTrace();
+        }
+        return nodeConnector;
     }
 
     public static Match toMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match source) {
index fd03ea4..c5ea267 100644 (file)
@@ -56,7 +56,7 @@ public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListen
     @Override
     public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
 
-        Flow flow = ToSalConversionsUtils.toFlow(input);
+        Flow flow = ToSalConversionsUtils.toFlow(input, null);
         @SuppressWarnings("unchecked")
         org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier<Node>) input
                 .getNode().getValue());
@@ -70,7 +70,7 @@ public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListen
     @Override
     public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
 
-        Flow flow = ToSalConversionsUtils.toFlow(input);
+        Flow flow = ToSalConversionsUtils.toFlow(input, null);
         @SuppressWarnings("unchecked")
         org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier<Node>) input
                 .getNode().getValue());
@@ -87,8 +87,8 @@ public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListen
         @SuppressWarnings("unchecked")
         org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier<Node>) input
                 .getNode().getValue());
-        Flow originalFlow = ToSalConversionsUtils.toFlow(input.getOriginalFlow());
-        Flow updatedFlow = ToSalConversionsUtils.toFlow(input.getUpdatedFlow());
+        Flow originalFlow = ToSalConversionsUtils.toFlow(input.getOriginalFlow(), null);
+        Flow updatedFlow = ToSalConversionsUtils.toFlow(input.getUpdatedFlow(), null);
         Status status = delegate.modifyFlowAsync(node, originalFlow, updatedFlow);
         UpdateFlowOutputBuilder builder = new UpdateFlowOutputBuilder();
         builder.setTransactionId(new TransactionId(BigInteger.valueOf(status.getRequestId())));
index 149544b..c7af602 100644 (file)
@@ -135,7 +135,7 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
 
         try {
             Node node = NodeMapping.toADNode(input.getNode());
-            Flow flow = ToSalConversionsUtils.toFlow(input);
+            Flow flow = ToSalConversionsUtils.toFlow(input, null);
             FlowOnNode readFlow = readDelegate.readFlow(node, flow);
             List<FlowAndStatisticsMapList> flowOnNodeToFlowStatistics = new ArrayList<FlowAndStatisticsMapList>();
             flowOnNodeToFlowStatistics.add(toOdFlowStatistics(readFlow));
index 793f3cc..ca16c65 100644 (file)
@@ -9,6 +9,10 @@ package org.opendaylight.controller.sal.compatibility.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
 
 import java.math.BigInteger;
 import java.net.Inet4Address;
@@ -19,53 +23,95 @@ import java.util.Collections;
 import java.util.List;
 
 import org.junit.Test;
-import org.opendaylight.controller.sal.action.*;
+import org.opendaylight.controller.sal.action.Flood;
+import org.opendaylight.controller.sal.action.FloodAll;
+import org.opendaylight.controller.sal.action.HwPath;
+import org.opendaylight.controller.sal.action.Loopback;
+import org.opendaylight.controller.sal.action.Output;
+import org.opendaylight.controller.sal.action.PopVlan;
+import org.opendaylight.controller.sal.action.PushVlan;
+import org.opendaylight.controller.sal.action.SetDlDst;
+import org.opendaylight.controller.sal.action.SetDlSrc;
+import org.opendaylight.controller.sal.action.SetDlType;
+import org.opendaylight.controller.sal.action.SetNextHop;
+import org.opendaylight.controller.sal.action.SetNwDst;
+import org.opendaylight.controller.sal.action.SetNwSrc;
+import org.opendaylight.controller.sal.action.SetNwTos;
+import org.opendaylight.controller.sal.action.SetTpDst;
+import org.opendaylight.controller.sal.action.SetTpSrc;
+import org.opendaylight.controller.sal.action.SetVlanCfi;
+import org.opendaylight.controller.sal.action.SetVlanId;
+import org.opendaylight.controller.sal.action.SetVlanPcp;
+import org.opendaylight.controller.sal.action.SwPath;
 import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.Node.NodeIDType;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.controller.action._case.ControllerActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.action._case.FloodActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.all.action._case.FloodAllActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.hw.path.action._case.HwPathActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.loopback.action._case.LoopbackActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetMplsTtlActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTtlActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.mpls.action._case.PushMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.pbb.action._case.PushPbbActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.type.action._case.SetDlTypeActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.mpls.ttl.action._case.SetMplsTtlActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.next.hop.action._case.SetNextHopActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.tos.action._case.SetNwTosActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.ttl.action._case.SetNwTtlActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.queue.action._case.SetQueueActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.dst.action._case.SetTpDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.src.action._case.SetTpSrcActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.cfi.action._case.SetVlanCfiActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.pcp.action._case.SetVlanPcpActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.sw.path.action._case.SwPathActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
@@ -73,8 +119,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
@@ -82,17 +140,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
 
 import com.google.common.net.InetAddresses;
 
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
-
 public class TestToSalConversionsUtils {
     // prefix:
     // od|Od = Open Daylight
@@ -101,29 +151,31 @@ public class TestToSalConversionsUtils {
     }
 
     @Test
-    public void testToSalConversion() {
+    public void testToSalConversion() throws ConstructionException {
         FlowAddedBuilder odNodeFlowBuilder = new FlowAddedBuilder();
         odNodeFlowBuilder = prepareOdFlowCommon();
-
-        Flow salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.other));
+        
+        Node node = new Node(NodeIDType.OPENFLOW,(long)1);
+        
+        Flow salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.other), node);
         checkSalMatch(salFlow.getMatch(), MtchType.other);
 
-        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.ipv4));
+        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.ipv4), node);
         checkSalMatch(salFlow.getMatch(), MtchType.ipv4);
 
-        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.ipv6));
+        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.ipv6), node);
         checkSalMatch(salFlow.getMatch(), MtchType.ipv6);
 
-        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.arp));
+        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.arp), node);
         checkSalMatch(salFlow.getMatch(), MtchType.arp);
 
-        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.sctp));
+        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.sctp), node);
         checkSalMatch(salFlow.getMatch(), MtchType.sctp);
 
-        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.tcp));
+        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.tcp), node);
         checkSalMatch(salFlow.getMatch(), MtchType.tcp);
 
-        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.udp));
+        salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.udp), node);
         checkSalMatch(salFlow.getMatch(), MtchType.udp);
 
         checkSalFlow(salFlow);
@@ -503,7 +555,7 @@ public class TestToSalConversionsUtils {
 
     private void prepareActionOutput(OutputActionCaseBuilder wrapper) {
         OutputActionBuilder outputActionBuilder = new OutputActionBuilder();
-        outputActionBuilder.setOutputNodeConnector(new Uri("uri1"));
+        outputActionBuilder.setOutputNodeConnector(new Uri("1"));
         wrapper.setOutputAction(outputActionBuilder.build());
     }
 
index cf0e71e..502d581 100644 (file)
@@ -37,6 +37,8 @@ public abstract class AttributeIfcSwitchStatement<T> {
                     return caseJavaBinaryAttribute(openType);
                 } else if(((JavaAttribute)attributeIfc).isUnion()) {
                     return caseJavaUnionAttribute(openType);
+                } else if(((JavaAttribute)attributeIfc).isIdentityRef()) {
+                    return caseJavaIdentityRefAttribute(openType);
                 } else
                     return caseJavaAttribute(openType);
             } catch (UnknownOpenTypeException e) {
@@ -56,6 +58,10 @@ public abstract class AttributeIfcSwitchStatement<T> {
         throw getIllegalArgumentException(attributeIfc);
     }
 
+    protected T caseJavaIdentityRefAttribute(OpenType<?> openType) {
+        return caseJavaAttribute(openType);
+    }
+
     protected T caseJavaUnionAttribute(OpenType<?> openType) {
         return caseJavaAttribute(openType);
     }
index 97c0f4d..61db74f 100644 (file)
@@ -16,20 +16,25 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribu
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 
 import javax.management.openmbean.ArrayType;
 import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.OpenType;
 import javax.management.openmbean.SimpleType;
+import java.util.Date;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 
 public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadingStrategy> {
 
     private String key;
+    private Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
 
-    public Map<String, AttributeReadingStrategy> prepareReading(Map<String, AttributeIfc> yangToAttrConfig) {
+    public Map<String, AttributeReadingStrategy> prepareReading(Map<String, AttributeIfc> yangToAttrConfig, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
         Map<String, AttributeReadingStrategy> strategies = Maps.newHashMap();
+        this.identityMap = identityMap;
 
         for (Entry<String, AttributeIfc> attributeEntry : yangToAttrConfig.entrySet()) {
             AttributeReadingStrategy strat = prepareReadingStrategy(attributeEntry.getKey(), attributeEntry.getValue());
@@ -72,6 +77,15 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadin
         return new SimpleCompositeAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
     }
 
+    @Override
+    protected AttributeReadingStrategy caseJavaIdentityRefAttribute(OpenType<?> openType) {
+        Preconditions.checkState(openType instanceof CompositeType);
+        Set<String> keys = ((CompositeType) openType).keySet();
+        Preconditions.checkState(keys.size() == 1, "Unexpected number of elements for open type %s, should be 1", openType);
+        String mappingKey = keys.iterator().next();
+        return new SimpleIdentityRefAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey, identityMap);
+    }
+
     @Override
     protected AttributeReadingStrategy caseDependencyAttribute(SimpleType<?> openType) {
         return new ObjectNameAttributeReadingStrategy(lastAttribute.getNullableDefault());
index 625e4ab..3765a13 100644 (file)
@@ -31,7 +31,7 @@ public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStra
 
         String textContent = "";
         try{
-            textContent = xmlElement.getTextContent();
+            textContent = readElementContent(xmlElement);
         }catch(IllegalStateException | NullPointerException e) {
             // yuma sends <attribute /> for empty value instead of <attribute></attribute>
             logger.warn("Ignoring exception caused by failure to read text element", e);
@@ -42,6 +42,10 @@ public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStra
                 postprocessParsedValue(textContent));
     }
 
+    protected String readElementContent(XmlElement xmlElement) {
+        return xmlElement.getTextContent();
+    }
+
     @Override
     protected Object postprocessNullableDefault(String nullableDefault) {
         return nullableDefault;
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleIdentityRefAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleIdentityRefAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..1205597
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.yangtools.yang.common.QName;
+
+
+public class SimpleIdentityRefAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
+
+    private final String key;
+    private final Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
+
+    public SimpleIdentityRefAttributeReadingStrategy(String nullableDefault, String key, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
+        super(nullableDefault);
+        this.key = key;
+        this.identityMap = identityMap;
+    }
+
+    @Override
+    protected String readElementContent(XmlElement xmlElement) {
+        // TODO test
+        Map.Entry<String, String> namespaceOfTextContent = xmlElement.findNamespaceOfTextContent();
+        String content = xmlElement.getTextContent();
+
+        String prefix = namespaceOfTextContent.getKey() + ":";
+        Preconditions.checkArgument(content.startsWith(prefix), "Identity ref should be prefixed");
+
+        String localName = content.substring(prefix.length());
+        String namespace = namespaceOfTextContent.getValue();
+
+        Date revision = null;
+        Map<Date, EditConfig.IdentityMapping> revisions = identityMap.get(namespace);
+        if(revisions.keySet().size() > 1) {
+            for (Date date : revisions.keySet()) {
+                if(revisions.get(date).containsIdName(localName)) {
+                    Preconditions.checkState(revision == null, "Duplicate identity %s, in namespace %s, with revisions: %s, %s detected. Cannot map attribute",
+                            localName, namespace, revision, date);
+                    revision = date;
+                }
+            }
+        } else
+            revision = revisions.keySet().iterator().next();
+
+
+        return QName.create(URI.create(namespace), revision, localName).toString();
+    }
+
+    @Override
+    protected Object postprocessParsedValue(String textContent) {
+        HashMap<String,String> map = Maps.newHashMap();
+        map.put(key, textContent);
+        return map;
+    }
+
+    @Override
+    protected Object postprocessNullableDefault(String nullableDefault) {
+        return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+    }
+}
index 4e870f0..8d63bb0 100644 (file)
@@ -68,6 +68,11 @@ public class ObjectXmlWriter extends AttributeIfcSwitchStatement<AttributeWritin
         return new ArrayAttributeWritingStrategy(innerStrategy);
     }
 
+    @Override
+    protected AttributeWritingStrategy caseJavaIdentityRefAttribute(OpenType<?> openType) {
+        return new SimpleIdentityRefAttributeWritingStrategy(document, key);
+    }
+
     @Override
     protected AttributeWritingStrategy caseJavaCompositeAttribute(CompositeType openType) {
         return new SimpleCompositeAttributeWritingStrategy(document, key);
index 62ff682..b327f8e 100644 (file)
@@ -31,11 +31,15 @@ public class SimpleAttributeWritingStrategy implements AttributeWritingStrategy
     public void writeElement(Element parentElement, String namespace, Object value) {
         value = preprocess(value);
         Util.checkType(value, String.class);
-        Element innerNode = XmlUtil.createTextElement(document, key, (String) value);
+        Element innerNode = createElement(document, key, (String) value);
         XmlUtil.addNamespaceAttr(innerNode, namespace);
         parentElement.appendChild(innerNode);
     }
 
+    protected Element createElement(Document document, String key, String value) {
+        return XmlUtil.createTextElement(document, key, (String) value);
+    }
+
     protected Object preprocess(Object value) {
         return value;
     }
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleIdentityRefAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleIdentityRefAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..7c90355
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import java.util.Map;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.w3c.dom.Document;
+
+import com.google.common.base.Preconditions;
+import org.w3c.dom.Element;
+
+public class SimpleIdentityRefAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
+
+    private static final char QNAME_SEPARATOR = ':';
+    private static final String PREFIX = "prefix";
+
+    /**
+     * @param document
+     * @param key
+     */
+    public SimpleIdentityRefAttributeWritingStrategy(Document document, String key) {
+        super(document, key);
+    }
+
+    protected Object preprocess(Object value) {
+        Util.checkType(value, Map.class);
+        Preconditions.checkArgument(((Map)value).size() == 1, "Unexpected number of values in %s, expected 1", value);
+        Object stringValue = ((Map) value).values().iterator().next();
+        Util.checkType(stringValue, String.class);
+
+        return stringValue;
+    }
+
+    @Override
+    protected Element createElement(Document doc, String key, String value) {
+        QName qName = QName.create(value);
+        String identity = qName.getLocalName();
+        Element element = XmlUtil.createPrefixedTextElement(doc, key, PREFIX, identity);
+
+        String identityNamespace = qName.getNamespace().toString();
+        XmlUtil.addPrefixedNamespaceAttr(element, PREFIX, identityNamespace);
+        return element;
+    }
+}
index ec73cd6..449cfbb 100644 (file)
@@ -15,6 +15,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
@@ -27,6 +28,7 @@ import org.w3c.dom.Element;
 import javax.management.ObjectName;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -43,13 +45,20 @@ public class Config {
             Map<String /* Name of module entry from yang file */, ModuleConfig>> moduleConfigs;
     private final Map<String, ModuleConfig> moduleNamesToConfigs;
 
+    private final Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
+
     public Config(Map<String, Map<String, ModuleConfig>> moduleConfigs) {
+        this(moduleConfigs, Collections.<String, Map<Date, EditConfig.IdentityMapping>>emptyMap());
+    }
+
+    public Config(Map<String, Map<String, ModuleConfig>> moduleConfigs, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
         this.moduleConfigs = moduleConfigs;
         Map<String, ModuleConfig> moduleNamesToConfigs = new HashMap<>();
         for (Entry<String, Map<String, ModuleConfig>> entry : moduleConfigs.entrySet()) {
             moduleNamesToConfigs.putAll(entry.getValue());
         }
         this.moduleNamesToConfigs = Collections.unmodifiableMap(moduleNamesToConfigs);
+        this.identityMap = identityMap;
     }
 
     public static Map<String, Map<String, Collection<ObjectName>>> getMappedInstances(Set<ObjectName> instancesToMap,
@@ -149,7 +158,7 @@ public class Config {
                 @Override
                 public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) {
                     return moduleMapping.fromXml(moduleElement, serviceTracker,
-                            instanceName, moduleNamespace, defaultStrategy);
+                            instanceName, moduleNamespace, defaultStrategy, identityMap);
                 }
             };
 
index b8870e5..a940be7 100644 (file)
@@ -25,6 +25,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.ObjectResolver;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.AttributeWritingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.ObjectXmlWriter;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
@@ -35,6 +36,7 @@ import org.w3c.dom.Element;
 
 import javax.management.ObjectName;
 import javax.management.openmbean.OpenType;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -129,10 +131,10 @@ public final class InstanceConfig {
     }
 
     public InstanceConfigElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper services, String moduleNamespace,
-            EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
+                                                 EditStrategyType defaultStrategy, Multimap<String, String> providedServices, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
         Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
 
-        Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
+        Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig, identityMap);
         List<XmlElement> recognisedChildren = Lists.newArrayList();
 
         XmlElement type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
index 48ff835..bf625ea 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.confi
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
@@ -21,6 +22,8 @@ import org.w3c.dom.Element;
 
 import javax.management.ObjectName;
 import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
 
 public class ModuleConfig {
 
@@ -85,9 +88,9 @@ public class ModuleConfig {
     }
 
     public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName,
-            String moduleNamespace, EditStrategyType defaultStrategy) {
+                                         String moduleNamespace, EditStrategyType defaultStrategy, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
 
-        InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices);
+        InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices, identityMap);
         return new ModuleElementResolved(instanceName, ice);
     }
 
index 7df6712..8d2d149 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+import org.opendaylight.yangtools.yang.common.QName;
 
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
@@ -19,8 +20,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 public class ServiceRegistryWrapper {
 
@@ -77,27 +76,15 @@ public class ServiceRegistryWrapper {
                 ObjectName on = serviceMapping.get(serviceQName).get(refName);
                 Services.ServiceInstance si = Services.ServiceInstance.fromObjectName(on);
 
-                // FIXME use QName's new String constructor, after it is fixed
-//                QName qname;
-//                try {
-//                    qname = new QName(serviceQName);
-//                } catch (ParseException e) {
-//                    throw new IllegalStateException("Unable to parse qname of a service " + serviceQName, e);
-//                }
-                Pattern p = Pattern.compile("\\(([^\\(\\?]+)\\?[^\\?\\)]*\\)([^\\)]+)");
-                Matcher matcher = p.matcher(serviceQName);
-                Preconditions.checkArgument(matcher.matches());
-                String namespace = matcher.group(1);
-                String localName = matcher.group(2);
-
-//                String namespace = qname.getNamespace().toString();
+                QName qname = QName.create(serviceQName);
+                String namespace = qname.getNamespace().toString();
                 Map<String, Map<String, String>> serviceToRefs = retVal.get(namespace);
                 if(serviceToRefs==null) {
                     serviceToRefs = Maps.newHashMap();
                     retVal.put(namespace, serviceToRefs);
                 }
 
-//                String localName = qname.getLocalName();
+                String localName = qname.getLocalName();
                 Map<String, String> refsToSis = serviceToRefs.get(localName);
                 if(refsToSis==null) {
                     refsToSis = Maps.newHashMap();
index 4b05135..b7f5fc7 100644 (file)
@@ -17,9 +17,12 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.ObjectResolver;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 
 import javax.management.openmbean.OpenType;
+import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -67,7 +70,9 @@ public final class InstanceRuntimeRpc {
     public Map<String, AttributeConfigElement> fromXml(XmlElement configRootNode) {
         Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
 
-        Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
+        // FIXME add identity map to runtime data
+        Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig,
+                Collections.<String, Map<Date, EditConfig.IdentityMapping>> emptyMap());
 
         for (Entry<String, AttributeReadingStrategy> readStratEntry : strats.entrySet()) {
             List<XmlElement> configNodes = configRootNode.getChildElements(readStratEntry.getKey());
index a61d463..97535ba 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
@@ -33,6 +34,8 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.edi
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -40,9 +43,11 @@ import org.w3c.dom.Element;
 
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 
 public class EditConfig extends AbstractConfigNetconfOperation {
 
@@ -207,12 +212,64 @@ public class EditConfig extends AbstractConfigNetconfOperation {
         }
     }
 
-    public static Config getConfigMapping(ConfigRegistryClient configRegistryClient,
-            Map<String/* Namespace from yang file */,
-                    Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> mBeanEntries) {
-        Map<String, Map<String, ModuleConfig>> factories = transformMbeToModuleConfigs(configRegistryClient, mBeanEntries);
+    public static Config getConfigMapping(ConfigRegistryClient configRegistryClient, YangStoreSnapshot yangStoreSnapshot) {
+        Map<String, Map<String, ModuleConfig>> factories = transformMbeToModuleConfigs(configRegistryClient,
+                yangStoreSnapshot.getModuleMXBeanEntryMap());
+        Map<String, Map<Date, IdentityMapping>> identitiesMap = transformIdentities(yangStoreSnapshot.getModules());
+        return new Config(factories, identitiesMap);
+    }
+
+
+    public static class IdentityMapping {
+        private final Map<String, IdentitySchemaNode> identityNameToSchemaNode;
+
+        IdentityMapping() {
+            this.identityNameToSchemaNode = Maps.newHashMap();
+        }
 
-        return new Config(factories);
+        void addIdSchemaNode(IdentitySchemaNode node) {
+            String name = node.getQName().getLocalName();
+            Preconditions.checkState(identityNameToSchemaNode.containsKey(name) == false);
+            identityNameToSchemaNode.put(name, node);
+        }
+
+        public boolean containsIdName(String idName) {
+            return identityNameToSchemaNode.containsKey(idName);
+        }
+
+        public IdentitySchemaNode getIdentitySchemaNode(String idName) {
+            Preconditions.checkState(identityNameToSchemaNode.containsKey(idName), "No identity under name %s", idName);
+            return identityNameToSchemaNode.get(idName);
+        }
+    }
+
+    private static Map<String, Map<Date, IdentityMapping>> transformIdentities(Set<Module> modules) {
+        Map<String, Map<Date, IdentityMapping>> mappedIds = Maps.newHashMap();
+        for (Module module : modules) {
+            String namespace = module.getNamespace().toString();
+            Map<Date, IdentityMapping> revisionsByNamespace= mappedIds.get(namespace);
+            if(revisionsByNamespace == null) {
+                revisionsByNamespace = Maps.newHashMap();
+                mappedIds.put(namespace, revisionsByNamespace);
+            }
+
+            Date revision = module.getRevision();
+            Preconditions.checkState(revisionsByNamespace.containsKey(revision) == false,
+                    "Duplicate revision %s for namespace %s", revision, namespace);
+
+            IdentityMapping identityMapping = revisionsByNamespace.get(revision);
+            if(identityMapping == null) {
+                identityMapping = new IdentityMapping();
+                revisionsByNamespace.put(revision, identityMapping);
+            }
+
+            for (IdentitySchemaNode identitySchemaNode : module.getIdentities()) {
+                identityMapping.addIdSchemaNode(identitySchemaNode);
+            }
+
+        }
+
+        return mappedIds;
     }
 
     public static Map<String/* Namespace from yang file */,
@@ -253,7 +310,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
     protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
 
         EditConfigXmlParser.EditConfigExecution editConfigExecution;
-        Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
+        Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot);
         try {
             editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, configRegistryClient);
         } catch (IllegalStateException e) {
@@ -278,4 +335,5 @@ public class EditConfig extends AbstractConfigNetconfOperation {
 
         return getResponseInternal(document, editConfigExecution);
     }
+
 }
index f236a8d..d699d22 100644 (file)
@@ -8,11 +8,33 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.commons.lang3.StringUtils;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -35,6 +57,7 @@ import org.opendaylight.controller.config.yang.test.impl.DtoAInner;
 import org.opendaylight.controller.config.yang.test.impl.DtoAInnerInner;
 import org.opendaylight.controller.config.yang.test.impl.DtoC;
 import org.opendaylight.controller.config.yang.test.impl.DtoD;
+import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
 import org.opendaylight.controller.config.yang.test.impl.Peers;
@@ -55,6 +78,13 @@ import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity2;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -62,30 +92,11 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 
 public class NetconfMappingTest extends AbstractConfigTest {
@@ -95,6 +106,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
     private static final String NETCONF_SESSION_ID = "foo";
     private NetconfTestImplModuleFactory factory;
     private DepTestImplModuleFactory factory2;
+    private IdentityTestModuleFactory factory3;
 
     @Mock
     YangStoreSnapshot yangStoreSnapshot;
@@ -107,9 +119,13 @@ public class NetconfMappingTest extends AbstractConfigTest {
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap();
+        doReturn(getModules()).when(this.yangStoreSnapshot).getModules();
+
         this.factory = new NetconfTestImplModuleFactory();
         this.factory2 = new DepTestImplModuleFactory();
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.factory, this.factory2));
+        this.factory3 = new IdentityTestModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.factory, this.factory2,
+                this.factory3));
 
         transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID);
     }
@@ -133,6 +149,25 @@ public class NetconfMappingTest extends AbstractConfigTest {
         return on;
     }
 
+    @Test
+    public void testIdentityRefs() throws Exception {
+        edit("netconfMessages/editConfig_identities.xml");
+
+        commit();
+        getConfigRunning();
+    }
+
+    @Override
+    protected CodecRegistry getCodecRegistry() {
+        IdentityCodec<?> idCodec = mock(IdentityCodec.class);
+        doReturn(TestIdentity1.class).when(idCodec).deserialize(TestIdentity1.QNAME);
+        doReturn(TestIdentity2.class).when(idCodec).deserialize(TestIdentity2.QNAME);
+
+        CodecRegistry codecReg = super.getCodecRegistry();
+        doReturn(idCodec).when(codecReg).getIdentityCodec();
+        return codecReg;
+    }
+
     @Test
     public void testServicePersistance() throws Exception {
         createModule(INSTANCE_NAME);
@@ -236,7 +271,6 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         edit("netconfMessages/editConfig.xml");
         Element configCandidate = getConfigCandidate();
-        System.err.println(XmlUtil.toString(configCandidate));
         checkBinaryLeafEdited(configCandidate);
 
 
@@ -554,6 +588,21 @@ public class NetconfMappingTest extends AbstractConfigTest {
         return mBeanEntries;
     }
 
+    private Set<org.opendaylight.yangtools.yang.model.api.Module> getModules() throws Exception {
+        SchemaContext resolveSchemaContext = getSchemaContext();
+        return resolveSchemaContext.getModules();
+    }
+
+    private SchemaContext getSchemaContext() throws Exception {
+        final List<InputStream> yangDependencies = getYangs();
+        YangParserImpl parser = new YangParserImpl();
+
+        Set<Module> allYangModules = parser.parseYangModelsFromStreams(yangDependencies);
+
+        return parser.resolveSchemaContext(Sets
+                .newHashSet(allYangModules));
+    }
+
     @Test
     public void testConfigNetconfRuntime() throws Exception {
 
index 5e3a7ac..137e215 100644 (file)
@@ -111,8 +111,8 @@ public class XmlUtil {
         root.setAttribute(concat(XMLNS_ATTRIBUTE_KEY, prefix), namespace);
     }
 
-    public static Element createPrefixedTextElement(Document document, String key, String prefix, String moduleName) {
-        return createTextElement(document, key, concat(prefix, moduleName));
+    public static Element createPrefixedTextElement(Document document, String key, String prefix, String content) {
+        return createTextElement(document, key, concat(prefix, content));
     }
 
     private static String concat(String prefix, String value) {
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_identities.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_identities.xml
new file mode 100644 (file)
index 0000000..62c6a20
--- /dev/null
@@ -0,0 +1,37 @@
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>merge</default-operation>
+        <config>
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        test-impl:impl-identity-test
+                    </type>
+                    <name>id-test</name>
+                    <identities>
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</afi>
+                        <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</safi>
+                    </identities>
+                    <identities>
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</afi>
+                        <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</safi>
+                    </identities>
+                    <identities-container>
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</afi>
+                    </identities-container>
+                    <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</afi>
+                </module>
+            </modules>
+
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+            </services>
+        </config>
+    </edit-config>
+</rpc>