Remove yang-test
[controller.git] / opendaylight / config / yang-jmx-generator / src / main / java / org / opendaylight / controller / config / yangjmxgenerator / RuntimeBeanEntry.java
index 23b071c817022ac0103f7cc01c4cc5f5482ba995..d94c695106539a9627f1558f9bb1e3deb06171ef 100644 (file)
@@ -9,11 +9,15 @@ package org.opendaylight.controller.config.yangjmxgenerator;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
-
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Lists;
-
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -21,12 +25,12 @@ import java.util.Comparator;
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
-
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
@@ -38,15 +42,16 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 
 /**
  * Holds information about runtime bean to be generated. There are two kinds of
 
 /**
  * Holds information about runtime bean to be generated. There are two kinds of
@@ -58,6 +63,10 @@ import org.opendaylight.yangtools.yang.model.api.UsesNode;
  * lined via children so that a tree with all beans can be created.
  */
 public class RuntimeBeanEntry {
  * lined via children so that a tree with all beans can be created.
  */
 public class RuntimeBeanEntry {
+
+    private static final Function<UnknownSchemaNode, String> UNKNOWN_NODE_TO_STRING =
+            input -> input.getQName().getLocalName() + input.getNodeParameter();
+
     private final String packageName;
     private final String yangName, javaNamePrefix;
     private final boolean isRoot;
     private final String packageName;
     private final String yangName, javaNamePrefix;
     private final boolean isRoot;
@@ -74,7 +83,7 @@ public class RuntimeBeanEntry {
             final List<RuntimeBeanEntry> children, final Set<Rpc> rpcs) {
 
         checkArgument(isRoot == false || keyYangName.isPresent() == false,
             final List<RuntimeBeanEntry> children, final Set<Rpc> rpcs) {
 
         checkArgument(isRoot == false || keyYangName.isPresent() == false,
-                "Root RuntimeBeanEntry must not have key " + "set");
+                "Root RuntimeBeanEntry must not have key set");
         this.packageName = packageName;
         this.isRoot = isRoot;
         this.yangName = yangName;
         this.packageName = packageName;
         this.isRoot = isRoot;
         this.yangName = yangName;
@@ -87,16 +96,14 @@ public class RuntimeBeanEntry {
 
         for (AttributeIfc a : attributes) {
             checkState(map.containsKey(a.getAttributeYangName()) == false,
 
         for (AttributeIfc a : attributes) {
             checkState(map.containsKey(a.getAttributeYangName()) == false,
-                    "Attribute already defined: " + a.getAttributeYangName()
-                    + " in " + nodeForReporting);
+                    "Attribute already defined: %s in %s", a.getAttributeYangName(), nodeForReporting);
             map.put(a.getAttributeYangName(), a);
         }
 
         if (keyYangName.isPresent()) {
             AttributeIfc keyJavaName = map.get(keyYangName.get());
             map.put(a.getAttributeYangName(), a);
         }
 
         if (keyYangName.isPresent()) {
             AttributeIfc keyJavaName = map.get(keyYangName.get());
-            checkArgument(keyJavaName != null, "Key " + keyYangName.get()
-                    + " not found in attribute " + "list " + attributes
-                    + " in " + nodeForReporting);
+            checkArgument(keyJavaName != null, "Key %s not found in attribute list %s in %s", keyYangName.get(),
+                    attributes, nodeForReporting);
             this.keyJavaName = Optional
                     .of(keyJavaName.getUpperCaseCammelCase());
         } else {
             this.keyJavaName = Optional
                     .of(keyJavaName.getUpperCaseCammelCase());
         } else {
@@ -114,13 +121,12 @@ public class RuntimeBeanEntry {
     public static Map<String, RuntimeBeanEntry> extractClassNameToRuntimeBeanMap(
             final String packageName, final DataNodeContainer container,
             final String moduleYangName, final TypeProviderWrapper typeProviderWrapper,
     public static Map<String, RuntimeBeanEntry> extractClassNameToRuntimeBeanMap(
             final String packageName, final DataNodeContainer container,
             final String moduleYangName, final TypeProviderWrapper typeProviderWrapper,
-            final String javaNamePrefix, final Module currentModule) {
+            final String javaNamePrefix, final Module currentModule, final SchemaContext schemaContext) {
 
 
-        Map<QName, Set<RpcDefinition>> identitiesToRpcs = getIdentitiesToRpcs(currentModule);
 
         AttributesRpcsAndRuntimeBeans attributesRpcsAndRuntimeBeans = extractSubtree(
                 packageName, container, typeProviderWrapper, currentModule,
 
         AttributesRpcsAndRuntimeBeans attributesRpcsAndRuntimeBeans = extractSubtree(
                 packageName, container, typeProviderWrapper, currentModule,
-                identitiesToRpcs);
+                schemaContext);
         Map<String, RuntimeBeanEntry> result = new HashMap<>();
 
         List<AttributeIfc> attributes;
         Map<String, RuntimeBeanEntry> result = new HashMap<>();
 
         List<AttributeIfc> attributes;
@@ -152,52 +158,42 @@ public class RuntimeBeanEntry {
         return result;
     }
 
         return result;
     }
 
-    private static Map<QName/* of identity */, Set<RpcDefinition>> getIdentitiesToRpcs(
-            final Module currentModule) {
-        // currently only looks for local identities (found in currentModule)
-        Map<QName, Set<RpcDefinition>> result = new HashMap<>();
-        for (IdentitySchemaNode identity : currentModule.getIdentities()) {
-            // add all
-            result.put(identity.getQName(), new HashSet<RpcDefinition>());
-        }
-
-        for (RpcDefinition rpc : currentModule.getRpcs()) {
-            ContainerSchemaNode input = rpc.getInput();
-            if (input != null) {
-                for (UsesNode uses : input.getUses()) {
-
-                    if (uses.getGroupingPath().getPath().size() != 1) {
-                        continue;
-                    }
-
-                    // check grouping path
-                    QName qname = uses.getGroupingPath().getPath().get(0);
-                    if (false == qname
-                            .equals(ConfigConstants.RPC_CONTEXT_REF_GROUPING_QNAME)) {
-                        continue;
-                    }
+    private static Multimap<QName/* of identity */, RpcDefinition> getIdentitiesToRpcs(
+            final SchemaContext schemaCtx) {
+        Multimap<QName, RpcDefinition> result = HashMultimap.create();
+        for (Module currentModule : schemaCtx.getModules()) {
+
+            // Find all identities in current module for later identity->rpc mapping
+            Set<QName> allIdentitiesInModule =
+                    Sets.newHashSet(Collections2.transform(currentModule.getIdentities(), SchemaNode::getQName));
+
+            for (RpcDefinition rpc : currentModule.getRpcs()) {
+                ContainerSchemaNode input = rpc.getInput();
+                if (input != null) {
+                    for (UsesNode uses : input.getUses()) {
+
+                        // Check if the rpc is config rpc by looking for input argument rpc-context-ref
+                        Iterator<QName> pathFromRoot = uses.getGroupingPath().getPathFromRoot().iterator();
+                        if (!pathFromRoot.hasNext() ||
+                                !pathFromRoot.next().equals(ConfigConstants.RPC_CONTEXT_REF_GROUPING_QNAME)) {
+                            continue;
+                        }
 
 
-                    for (SchemaNode refinedNode : uses.getRefines().values()) {
-
-                        for (UnknownSchemaNode unknownSchemaNode : refinedNode
-                                .getUnknownSchemaNodes()) {
-                            if (ConfigConstants.RPC_CONTEXT_INSTANCE_EXTENSION_QNAME
-                                    .equals(unknownSchemaNode.getNodeType())) {
-                                String localIdentityName = unknownSchemaNode
-                                        .getNodeParameter();
-                                QName identityQName = QName.create(
-                                        currentModule.getNamespace(),
-                                        currentModule.getRevision(),
-                                        localIdentityName);
-                                Set<RpcDefinition> rpcDefinitions = result
-                                        .get(identityQName);
-                                if (rpcDefinitions == null) {
-                                    throw new IllegalArgumentException(
-                                            "Identity referenced by rpc not found. Identity:"
-                                                    + localIdentityName + " , rpc "
-                                                    + rpc);
+                        for (SchemaNode refinedNode : uses.getRefines().values()) {
+                            for (UnknownSchemaNode unknownSchemaNode : refinedNode
+                                    .getUnknownSchemaNodes()) {
+                                if (ConfigConstants.RPC_CONTEXT_INSTANCE_EXTENSION_QNAME
+                                        .equals(unknownSchemaNode.getNodeType())) {
+                                    String localIdentityName = unknownSchemaNode
+                                            .getNodeParameter();
+                                    QName identityQName = QName.create(
+                                            currentModule.getNamespace(),
+                                            currentModule.getRevision(),
+                                            localIdentityName);
+                                    Preconditions.checkArgument(allIdentitiesInModule.contains(identityQName),
+                                            "Identity referenced by rpc not found. Identity: %s, rpc: %s", localIdentityName, rpc);
+                                    result.put(identityQName, rpc);
                                 }
                                 }
-                                rpcDefinitions.add(rpc);
                             }
                         }
                     }
                             }
                         }
                     }
@@ -214,11 +210,11 @@ public class RuntimeBeanEntry {
     private static AttributesRpcsAndRuntimeBeans extractSubtree(
             final String packageName, final DataNodeContainer subtree,
             final TypeProviderWrapper typeProviderWrapper, final Module currentModule,
     private static AttributesRpcsAndRuntimeBeans extractSubtree(
             final String packageName, final DataNodeContainer subtree,
             final TypeProviderWrapper typeProviderWrapper, final Module currentModule,
-            final Map<QName, Set<RpcDefinition>> identitiesToRpcs) {
+            final SchemaContext ctx) {
+
+        Multimap<QName, RpcDefinition> identitiesToRpcs = getIdentitiesToRpcs(ctx);
 
         List<AttributeIfc> attributes = Lists.newArrayList();
 
         List<AttributeIfc> attributes = Lists.newArrayList();
-        // List<JavaAttribute> javaAttributes = new ArrayList<>();
-        // List<TOAttribute> toAttributes = new ArrayList<>();
         List<RuntimeBeanEntry> runtimeBeanEntries = new ArrayList<>();
         for (DataSchemaNode child : subtree.getChildNodes()) {
             // child leaves can be java attributes, TO attributes, or child
         List<RuntimeBeanEntry> runtimeBeanEntries = new ArrayList<>();
         for (DataSchemaNode child : subtree.getChildNodes()) {
             // child leaves can be java attributes, TO attributes, or child
@@ -238,7 +234,7 @@ public class RuntimeBeanEntry {
                     ListSchemaNode listSchemaNode = (ListSchemaNode) child;
                     RuntimeBeanEntry hierarchicalChild = createHierarchical(
                             packageName, listSchemaNode, typeProviderWrapper,
                     ListSchemaNode listSchemaNode = (ListSchemaNode) child;
                     RuntimeBeanEntry hierarchicalChild = createHierarchical(
                             packageName, listSchemaNode, typeProviderWrapper,
-                            currentModule, identitiesToRpcs);
+                            currentModule, ctx);
                     runtimeBeanEntries.add(hierarchicalChild);
                 } else /* ordinary list attribute */{
                     ListAttribute listAttribute = ListAttribute.create(
                     runtimeBeanEntries.add(hierarchicalChild);
                 } else /* ordinary list attribute */{
                     ListAttribute listAttribute = ListAttribute.create(
@@ -262,23 +258,16 @@ public class RuntimeBeanEntry {
             if (ConfigConstants.RPC_CONTEXT_INSTANCE_EXTENSION_QNAME
                     .equals(unknownSchemaNode.getNodeType())) {
                 String localIdentityName = unknownSchemaNode.getNodeParameter();
             if (ConfigConstants.RPC_CONTEXT_INSTANCE_EXTENSION_QNAME
                     .equals(unknownSchemaNode.getNodeType())) {
                 String localIdentityName = unknownSchemaNode.getNodeParameter();
-                QName identityQName = QName.create(currentModule.getNamespace(),
-                        currentModule.getRevision(), localIdentityName);
-                Set<RpcDefinition> rpcDefinitions = identitiesToRpcs
-                        .get(identityQName);
-                if (rpcDefinitions == null) {
-                    throw new IllegalArgumentException("Cannot find identity "
-                            + localIdentityName + " to be used as "
-                            + "context reference when resolving "
-                            + unknownSchemaNode);
-                }
+                QName identityQName = unknownSchemaNode.isAddedByUses() ?
+                        findQNameFromGrouping(subtree, ctx, unknownSchemaNode, localIdentityName) :
+                        QName.create(currentModule.getNamespace(), currentModule.getRevision(), localIdentityName);
                 // convert RpcDefinition to Rpc
                 // convert RpcDefinition to Rpc
-                for (RpcDefinition rpcDefinition : rpcDefinitions) {
+                for (RpcDefinition rpcDefinition : identitiesToRpcs.get(identityQName)) {
                     String name = TypeProviderWrapper
                             .findJavaParameter(rpcDefinition);
                     AttributeIfc returnType;
                     if (rpcDefinition.getOutput() == null
                     String name = TypeProviderWrapper
                             .findJavaParameter(rpcDefinition);
                     AttributeIfc returnType;
                     if (rpcDefinition.getOutput() == null
-                            || rpcDefinition.getOutput().getChildNodes().size() == 0) {
+                            || rpcDefinition.getOutput().getChildNodes().isEmpty()) {
                         returnType = VoidAttribute.getInstance();
                     } else if (rpcDefinition.getOutput().getChildNodes().size() == 1) {
                         DataSchemaNode returnDSN = rpcDefinition.getOutput()
                         returnType = VoidAttribute.getInstance();
                     } else if (rpcDefinition.getOutput().getChildNodes().size() == 1) {
                         DataSchemaNode returnDSN = rpcDefinition.getOutput()
@@ -314,6 +303,22 @@ public class RuntimeBeanEntry {
                 attributes, rpcs);
     }
 
                 attributes, rpcs);
     }
 
+    /**
+     * Find "proper" qname of unknown node in case it comes from a grouping
+     */
+    private static QName findQNameFromGrouping(final DataNodeContainer subtree, final SchemaContext ctx, final UnknownSchemaNode unknownSchemaNode, final String localIdentityName) {
+        QName identityQName = null;
+        for (UsesNode usesNode : subtree.getUses()) {
+            SchemaNode dataChildByName = SchemaContextUtil.findDataSchemaNode(ctx, usesNode.getGroupingPath());
+            Module m = SchemaContextUtil.findParentModule(ctx, dataChildByName);
+            List<UnknownSchemaNode> unknownSchemaNodes = dataChildByName.getUnknownSchemaNodes();
+            if(Collections2.transform(unknownSchemaNodes, UNKNOWN_NODE_TO_STRING).contains(UNKNOWN_NODE_TO_STRING.apply(unknownSchemaNode))) {
+                identityQName = QName.create(dataChildByName.getQName(), localIdentityName);
+            }
+        }
+        return identityQName;
+    }
+
     private static AttributeIfc getReturnTypeAttribute(final DataSchemaNode child, final TypeProviderWrapper typeProviderWrapper,
             final String packageName) {
         if (child instanceof LeafSchemaNode) {
     private static AttributeIfc getReturnTypeAttribute(final DataSchemaNode child, final TypeProviderWrapper typeProviderWrapper,
             final String packageName) {
         if (child instanceof LeafSchemaNode) {
@@ -332,13 +337,9 @@ public class RuntimeBeanEntry {
         }
     }
 
         }
     }
 
-    private static Collection<DataSchemaNode> sortAttributes(final Set<DataSchemaNode> childNodes) {
-        final TreeSet<DataSchemaNode> dataSchemaNodes = new TreeSet<>(new Comparator<DataSchemaNode>() {
-            @Override
-            public int compare(final DataSchemaNode o1, final DataSchemaNode o2) {
-                return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
-            }
-        });
+    private static Collection<DataSchemaNode> sortAttributes(final Collection<DataSchemaNode> childNodes) {
+        final TreeSet<DataSchemaNode> dataSchemaNodes =
+                new TreeSet<>(Comparator.comparing(o -> o.getQName().getLocalName()));
         dataSchemaNodes.addAll(childNodes);
         return dataSchemaNodes;
     }
         dataSchemaNodes.addAll(childNodes);
         return dataSchemaNodes;
     }
@@ -357,16 +358,16 @@ public class RuntimeBeanEntry {
     private static RuntimeBeanEntry createHierarchical(final String packageName,
             final ListSchemaNode listSchemaNode,
             final TypeProviderWrapper typeProviderWrapper, final Module currentModule,
     private static RuntimeBeanEntry createHierarchical(final String packageName,
             final ListSchemaNode listSchemaNode,
             final TypeProviderWrapper typeProviderWrapper, final Module currentModule,
-            final Map<QName, Set<RpcDefinition>> identitiesToRpcs) {
+            final SchemaContext ctx) {
 
         // supported are numeric types, strings, enums
         // get all attributes
         AttributesRpcsAndRuntimeBeans attributesRpcsAndRuntimeBeans = extractSubtree(
                 packageName, listSchemaNode, typeProviderWrapper,
 
         // supported are numeric types, strings, enums
         // get all attributes
         AttributesRpcsAndRuntimeBeans attributesRpcsAndRuntimeBeans = extractSubtree(
                 packageName, listSchemaNode, typeProviderWrapper,
-                currentModule, identitiesToRpcs);
+                currentModule, ctx);
 
         Optional<String> keyYangName;
 
         Optional<String> keyYangName;
-        if (listSchemaNode.getKeyDefinition().size() == 0) {
+        if (listSchemaNode.getKeyDefinition().isEmpty()) {
             keyYangName = Optional.absent();
         } else if (listSchemaNode.getKeyDefinition().size() == 1) {
             // key must be either null or one of supported key types
             keyYangName = Optional.absent();
         } else if (listSchemaNode.getKeyDefinition().size() == 1) {
             // key must be either null or one of supported key types