Added conflict handling between configuration and state choice nodes. 78/3578/2
authorMilos Fabian <milfabia@cisco.com>
Mon, 9 Dec 2013 14:27:45 +0000 (15:27 +0100)
committerMilos Fabian <milfabia@cisco.com>
Mon, 9 Dec 2013 14:46:15 +0000 (15:46 +0100)
-unique node naming required

Change-Id: I7db0a094d8abbd4c1616b6a01a22ac201e91ad64
Signed-off-by: Milos Fabian <milfabia@cisco.com>
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryNameConflictTest.java
opendaylight/config/yang-jmx-generator/src/test/resources/duplicates/config-test-duplicate-attribute-in-runtime-and-mxbean.yang [new file with mode: 0644]

index a7110b874c829e00cfaccf4386abf97fb9c7b556..4eba739b469d52b675b7208e0621c9ddc9f4a845 100644 (file)
@@ -7,9 +7,21 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
@@ -41,20 +53,9 @@ import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 /**
  * Represents part of yang model that describes a module.
@@ -184,8 +185,9 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     }
 
     /**
-     * @return services implemented by this module. Keys are fully qualified java names of generated
-     * ServiceInterface classes, values are identity local names.
+     * @return services implemented by this module. Keys are fully qualified
+     *         java names of generated ServiceInterface classes, values are
+     *         identity local names.
      */
     public Map<String, QName> getProvidedServices() {
         return providedServices;
@@ -360,7 +362,6 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                                     e.getConflictingName(), when.getQName(),
                                     when.getQName());
                         }
-
                         checkUniqueRuntimeBeansGeneratedClasses(
                                 uniqueGeneratedClassesNames, when, runtimeBeans);
                         Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets
@@ -415,6 +416,11 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                         .<RuntimeBeanEntry> emptyList());
             }
         }
+        // check attributes name uniqueness
+        for (Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
+            checkUniqueRuntimeBeanAttributesName(entry.getValue(),
+                    uniqueGeneratedClassesNames);
+        }
         if (unaugmentedModuleIdentities.size() > 0) {
             logger.warn("Augmentation not found for all module identities: {}",
                     unaugmentedModuleIdentities.keySet());
@@ -443,6 +449,25 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         }
     }
 
+    private static void checkUniqueRuntimeBeanAttributesName(
+            ModuleMXBeanEntry mxBeanEntry,
+            Map<String, QName> uniqueGeneratedClassesNames) {
+        for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) {
+            for (String runtimeAttName : runtimeBeanEntry
+                    .getYangPropertiesToTypesMap().keySet()) {
+                if (mxBeanEntry.getAttributes().keySet()
+                        .contains(runtimeAttName)) {
+                    QName qName1 = uniqueGeneratedClassesNames
+                            .get(runtimeBeanEntry.getJavaNameOfRuntimeMXBean());
+                    QName qName2 = uniqueGeneratedClassesNames.get(mxBeanEntry
+                            .getGloballyUniqueName());
+                    throw new NameConflictException(runtimeAttName, qName1,
+                            qName2);
+                }
+            }
+        }
+    }
+
     private static void checkUniqueAttributesWithGeneratedClass(
             Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
             Map<String, AttributeIfc> yangToAttributes) {
@@ -566,7 +591,8 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     private static AttributeIfc getAttributeValue(DataSchemaNode attrNode,
             Module currentModule,
             Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext, String packageName) {
+            TypeProviderWrapper typeProviderWrapper,
+            SchemaContext schemaContext, String packageName) {
 
         if (attrNode instanceof LeafSchemaNode) {
             // simple type
@@ -575,12 +601,14 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         } else if (attrNode instanceof ContainerSchemaNode) {
             // reference or TO
             ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
-            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(containerSchemaNode,
-                    attrNode, currentModule, qNamesToSIEs, schemaContext);
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+                    containerSchemaNode, attrNode, currentModule, qNamesToSIEs,
+                    schemaContext);
             if (dependencyAttributeOptional.isPresent()) {
                 return dependencyAttributeOptional.get();
             } else {
-                return TOAttribute.create(containerSchemaNode, typeProviderWrapper, packageName);
+                return TOAttribute.create(containerSchemaNode,
+                        typeProviderWrapper, packageName);
             }
 
         } else if (attrNode instanceof LeafListSchemaNode) {
@@ -588,12 +616,14 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                     typeProviderWrapper);
         } else if (attrNode instanceof ListSchemaNode) {
             ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode;
-            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(listSchemaNode,
-                    attrNode, currentModule, qNamesToSIEs, schemaContext);
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+                    listSchemaNode, attrNode, currentModule, qNamesToSIEs,
+                    schemaContext);
             if (dependencyAttributeOptional.isPresent()) {
                 return dependencyAttributeOptional.get();
             } else {
-                return ListAttribute.create(listSchemaNode, typeProviderWrapper, packageName);
+                return ListAttribute.create(listSchemaNode,
+                        typeProviderWrapper, packageName);
             }
         } else {
             throw new UnsupportedOperationException(
@@ -601,16 +631,15 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         }
     }
 
-    private static Optional<? extends AbstractDependencyAttribute> extractDependency(DataNodeContainer dataNodeContainer,
-                                                            DataSchemaNode attrNode,
-                                                            Module currentModule,
-                                                            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-                                                            SchemaContext schemaContext) {
+    private static Optional<? extends AbstractDependencyAttribute> extractDependency(
+            DataNodeContainer dataNodeContainer, DataSchemaNode attrNode,
+            Module currentModule,
+            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+            SchemaContext schemaContext) {
         if (dataNodeContainer.getUses().size() == 1
                 && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
             // reference
-            UsesNode usesNode = dataNodeContainer.getUses().iterator()
-                    .next();
+            UsesNode usesNode = dataNodeContainer.getUses().iterator().next();
             checkState(usesNode.getRefines().size() == 1,
                     "Unexpected 'refine' child node size of "
                             + dataNodeContainer);
@@ -618,26 +647,28 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                     .values().iterator().next();
             checkState(refine.getUnknownSchemaNodes().size() == 1,
                     "Unexpected unknown schema node size of " + refine);
-            UnknownSchemaNode requiredIdentity = refine
-                    .getUnknownSchemaNodes().iterator().next();
+            UnknownSchemaNode requiredIdentity = refine.getUnknownSchemaNodes()
+                    .iterator().next();
             checkState(
                     ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
-                            .getNodeType()),
-                    "Unexpected language extension " + requiredIdentity);
+                            .getNodeType()), "Unexpected language extension "
+                            + requiredIdentity);
             String prefixAndIdentityLocalName = requiredIdentity
                     .getNodeParameter();
             // import should point to a module
             ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
-                    prefixAndIdentityLocalName, currentModule,
-                    qNamesToSIEs, schemaContext);
+                    prefixAndIdentityLocalName, currentModule, qNamesToSIEs,
+                    schemaContext);
             boolean mandatory = refine.getConstraints().isMandatory();
             AbstractDependencyAttribute reference;
-            if (dataNodeContainer instanceof ContainerSchemaNode ){
-                reference = new DependencyAttribute(attrNode, serviceInterfaceEntry,
-                    mandatory, attrNode.getDescription());
+            if (dataNodeContainer instanceof ContainerSchemaNode) {
+                reference = new DependencyAttribute(attrNode,
+                        serviceInterfaceEntry, mandatory,
+                        attrNode.getDescription());
             } else {
-                reference = new ListDependenciesAttribute(attrNode, serviceInterfaceEntry,
-                        mandatory, attrNode.getDescription());
+                reference = new ListDependenciesAttribute(attrNode,
+                        serviceInterfaceEntry, mandatory,
+                        attrNode.getDescription());
             }
             return Optional.of(reference);
         }
index deef08a292e6d5a7853796effeaa85fc5096773e..9032a2c9306ca38f537028984f05812ca24f6e2a 100644 (file)
@@ -100,6 +100,9 @@ public class ModuleMXBeanEntryNameConflictTest extends AbstractYangTest {
         testedYangModulesToExpectedConflictingName.put(
                 "config-test-runtime-bean-name-conflict2",
                 "StateARuntimeMXBean");
+        testedYangModulesToExpectedConflictingName.put(
+                "config-test-duplicate-attribute-in-runtime-and-mxbean",
+                "port");
     }
 
     private String getYangModuleName(String name) {
diff --git a/opendaylight/config/yang-jmx-generator/src/test/resources/duplicates/config-test-duplicate-attribute-in-runtime-and-mxbean.yang b/opendaylight/config/yang-jmx-generator/src/test/resources/duplicates/config-test-duplicate-attribute-in-runtime-and-mxbean.yang
new file mode 100644 (file)
index 0000000..58c3af2
--- /dev/null
@@ -0,0 +1,57 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module config-test-duplicate-attribute-in-runtime-and-mxbean {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:jmx:duplicate:runtime";
+    prefix "th-java";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+    import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
+
+
+    description
+        "This module contains the base YANG definitions for NS-OS
+         thread services pure Java implementation.";
+
+    revision "2013-04-05" {
+        description
+            "Updated to work with new anchors.";
+    }
+
+    revision "2013-04-03" {
+        description
+            "Initial revision.";
+    }
+
+   identity async-eventbus {
+        base config:module-type;
+        config:java-name-prefix AsyncEventBus;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case async-eventbus {
+            when "/config:modules/config:module/config:type = 'async-eventbus'";
+            leaf port {
+                type string;
+            }
+            leaf core-size {
+                type uint32;
+            }
+            leaf simple-int3 {
+                type uint16;
+            }
+        }
+    }
+
+    augment "/config:modules/config:module/config:state" {
+        case async-eventbus {
+            when "/config:modules/config:module/config:type = 'async-eventbus'";
+            leaf simple-arg {
+                type uint32;
+            }
+            leaf port {
+                type inet:port-number;
+            }
+        }
+    }
+}
\ No newline at end of file