Merge "Fixed deserialization of IdentityRefs in Restconf URI."
[controller.git] / opendaylight / config / yang-jmx-generator / src / main / java / org / opendaylight / controller / config / yangjmxgenerator / RuntimeBeanEntry.java
index 6d1eca11933cea8216588d6a94fab9955b173c49..f19a46d0f461e35a1ecf9dd97e05aa1500a821df 100644 (file)
@@ -7,24 +7,14 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
 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.TOAttribute;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -33,6 +23,7 @@ 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;
@@ -41,9 +32,21 @@ 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 com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
 
 /**
  * Holds information about runtime bean to be generated. There are two kinds of
@@ -64,7 +67,7 @@ public class RuntimeBeanEntry {
     private final Set<Rpc> rpcs;
 
     @VisibleForTesting
-    public RuntimeBeanEntry(String packageName,
+    RuntimeBeanEntry(String packageName,
             DataSchemaNode nodeForReporting, String yangName,
             String javaNamePrefix, boolean isRoot,
             Optional<String> keyYangName, List<AttributeIfc> attributes,
@@ -225,7 +228,7 @@ public class RuntimeBeanEntry {
                 ContainerSchemaNode container = (ContainerSchemaNode) child;
                 // this can be either TO or hierarchical RB
                 TOAttribute toAttribute = TOAttribute.create(container,
-                        typeProviderWrapper);
+                        typeProviderWrapper, packageName);
                 attributes.add(toAttribute);
             } else if (child instanceof ListSchemaNode) {
                 if (isInnerStateBean(child)) {
@@ -236,13 +239,17 @@ public class RuntimeBeanEntry {
                     runtimeBeanEntries.add(hierarchicalChild);
                 } else /* ordinary list attribute */{
                     ListAttribute listAttribute = ListAttribute.create(
-                            (ListSchemaNode) child, typeProviderWrapper);
+                            (ListSchemaNode) child, typeProviderWrapper, packageName);
                     attributes.add(listAttribute);
                 }
 
+            } else if (child instanceof LeafListSchemaNode) {
+                ListAttribute listAttribute = ListAttribute.create(
+                        (LeafListSchemaNode) child, typeProviderWrapper);
+                attributes.add(listAttribute);
             } else {
-                throw new IllegalStateException("Unknown running-data node "
-                        + child + " , " + "" + "expected leaf or container");
+                throw new IllegalStateException("Unexpected running-data node "
+                        + child);
             }
         }
         Set<Rpc> rpcs = new HashSet<>();
@@ -266,37 +273,23 @@ public class RuntimeBeanEntry {
                 for (RpcDefinition rpcDefinition : rpcDefinitions) {
                     String name = ModuleMXBeanEntry
                             .findJavaParameter(rpcDefinition);
-                    String returnType;
+                    AttributeIfc returnType;
                     if (rpcDefinition.getOutput() == null
                             || rpcDefinition.getOutput().getChildNodes().size() == 0) {
-                        returnType = "void";
+                        returnType = VoidAttribute.getInstance();
                     } else if (rpcDefinition.getOutput().getChildNodes().size() == 1) {
                         DataSchemaNode returnDSN = rpcDefinition.getOutput()
                                 .getChildNodes().iterator().next();
-                        checkArgument(
-                                returnDSN instanceof LeafSchemaNode,
-                                "Unexpected type of rpc return type. "
-                                        + "Currently only leafs and empty output nodes are supported, got "
-                                        + returnDSN);
-                        LeafSchemaNode returnLeaf = (LeafSchemaNode) returnDSN;
-                        // We currently expect leaf defined in output element in yang to be named result
-                        // FIXME: value of result is fully qualified name - should be extended to accept TOs
-                        String localName = returnLeaf.getQName().getLocalName();
-                        checkArgument(
-                                localName.equals("result"),
-                                "Unexpected name of leaf in output element, expected leaf named result, was %s at %s",
-                                localName, currentModule.getName());
-
-                        returnType = typeProviderWrapper.getType(returnLeaf)
-                                .getFullyQualifiedName();
+                        returnType = getReturnTypeAttribute(returnDSN, typeProviderWrapper, packageName);
+
                     } else {
                         throw new IllegalArgumentException(
                                 "More than one child node in rpc output is not supported. "
                                         + "Error occured in " + rpcDefinition);
                     }
                     List<JavaAttribute> parameters = new ArrayList<>();
-                    for (DataSchemaNode childNode : rpcDefinition.getInput()
-                            .getChildNodes()) {
+                    for (DataSchemaNode childNode : sortAttributes(rpcDefinition.getInput()
+                            .getChildNodes())) {
                         if (childNode.isAddedByUses() == false) { // skip
                                                                   // refined
                                                                   // context-instance
@@ -318,6 +311,35 @@ public class RuntimeBeanEntry {
                 attributes, rpcs);
     }
 
+    private static AttributeIfc getReturnTypeAttribute(DataSchemaNode child, TypeProviderWrapper typeProviderWrapper,
+                                                       String packageName) {
+        if (child instanceof LeafSchemaNode) {
+            LeafSchemaNode leaf = (LeafSchemaNode) child;
+            return new JavaAttribute(leaf, typeProviderWrapper);
+        } else if (child instanceof ContainerSchemaNode) {
+            ContainerSchemaNode container = (ContainerSchemaNode) child;
+            TOAttribute toAttribute = TOAttribute.create(container, typeProviderWrapper, packageName);
+            return toAttribute;
+        } else if (child instanceof ListSchemaNode) {
+            return ListAttribute.create((ListSchemaNode) child, typeProviderWrapper, packageName);
+        } else if (child instanceof LeafListSchemaNode) {
+            return ListAttribute.create((LeafListSchemaNode) child, typeProviderWrapper);
+        } else {
+            throw new IllegalStateException("Unknown output data node " + child + " for rpc");
+        }
+    }
+
+    private static Collection<DataSchemaNode> sortAttributes(Set<DataSchemaNode> childNodes) {
+        final TreeSet<DataSchemaNode> dataSchemaNodes = new TreeSet<>(new Comparator<DataSchemaNode>() {
+            @Override
+            public int compare(DataSchemaNode o1, DataSchemaNode o2) {
+                return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
+            }
+        });
+        dataSchemaNodes.addAll(childNodes);
+        return dataSchemaNodes;
+    }
+
     private static boolean isInnerStateBean(DataSchemaNode child) {
         for (UnknownSchemaNode unknownSchemaNode : child
                 .getUnknownSchemaNodes()) {
@@ -448,10 +470,10 @@ public class RuntimeBeanEntry {
     public static class Rpc {
         private final String name;
         private final List<JavaAttribute> parameters;
-        private final String returnType;
+        private final AttributeIfc returnType;
         private final String yangName;
 
-        Rpc(String returnType, String name, String yangName,
+        Rpc(AttributeIfc returnType, String name, String yangName,
                 List<JavaAttribute> parameters) {
             this.returnType = returnType;
             this.name = name;
@@ -471,7 +493,7 @@ public class RuntimeBeanEntry {
             return parameters;
         }
 
-        public String getReturnType() {
+        public AttributeIfc getReturnType() {
             return returnType;
         }
     }