Merge "Bug 735 - Part 1: Update ietf-restconf and ietf-yangtypes to newer versions"
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / BindingGeneratorImpl.xtend
index 94d4812cd039f3c5e72b6f46d85f503d51f761fb..b4362fbd8cb4a1fdc2ab107cb92347a995228cdb 100644 (file)
@@ -69,7 +69,6 @@ import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder
 import org.opendaylight.yangtools.yang.model.api.ModuleImport
 import org.opendaylight.yangtools.yang.binding.DataContainer
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
@@ -80,8 +79,6 @@ import org.opendaylight.yangtools.yang.binding.BindingMapping
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase
 
 import com.google.common.collect.Sets
-import java.net.URI
-import java.util.Date
 
 public class BindingGeneratorImpl implements BindingGenerator {
 
@@ -255,6 +252,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }
         val packageName = packageNameForGeneratedType(basePackageName, node.path)
         val genType = addDefaultInterfaceDefinition(packageName, node, childOf)
+        genType.addComment(node.getDescription());
         if (node instanceof DataNodeContainer) {
             genCtx.get(module).addChildNodeType(node.path, genType)
             groupingsToGenTypes(module, (node as DataNodeContainer).groupings)
@@ -399,6 +397,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
         addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
         moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
+        moduleDataTypeBuilder.addComment(module.getDescription());
         return moduleDataTypeBuilder;
     }
 
@@ -436,7 +435,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
             if (rpc !== null) {
                 val rpcName = BindingMapping.getClassName(rpc.QName);
                 val rpcMethodName = parseToValidParamName(rpcName);
+                val rpcComment = rpc.getDescription();
                 val method = interfaceBuilder.addMethod(rpcMethodName);
+
                 val input = rpc.input;
                 val output = rpc.output;
 
@@ -463,7 +464,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 }
 
                 val rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult), outTypeInstance);
+                method.setComment(rpcComment);
                 method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes));
+
             }
         }
 
@@ -516,7 +519,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
                 listenerInterface.addMethod("on" + notificationInterface.name) //
                 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification").
-                    setReturnType(Types.VOID);
+                    setComment(notification.getDescription()).setReturnType(Types.VOID);
             }
         }
 
@@ -583,6 +586,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             newType.setExtendsType(gto);
         }
         newType.setAbstract(true);
+        newType.addComment(identity.getDescription());
         val qname = identity.QName;
         
         newType.qnameConstant(BindingMapping.QNAME_STATIC_FIELD_NAME,qname);
@@ -745,7 +749,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
         if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
-            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
+            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode, schemaContext);
             if (targetSchemaNode == null) {
                 throw new NullPointerException(
                     "Failed to find target node from grouping in augmentation " + augSchema + " in module " +
@@ -766,10 +770,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         if (!(targetSchemaNode instanceof ChoiceNode)) {
             var packageName = augmentPackageName;
-            val augTypeBuilder = addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
-                targetTypeBuilder.toInstance, augSchema);
-            genCtx.get(module).addAugmentType(augTypeBuilder)
-            genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
+            val targetType = new ReferencedTypeImpl(targetTypeBuilder.packageName,targetTypeBuilder.name);
+            addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,targetType, augSchema);
+            
         } else {
             generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
                 targetSchemaNode as ChoiceNode, augSchema.childNodes);
@@ -804,238 +807,14 @@ public class BindingGeneratorImpl implements BindingGenerator {
             if (usesNodeParent instanceof SchemaNode) {
                 packageName = packageNameForGeneratedType(augmentPackageName, (usesNodeParent as SchemaNode).path, true)
             }
-            val augTypeBuilder = addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
+            addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
                 targetTypeBuilder.toInstance, augSchema);
-            genCtx.get(module).addAugmentType(augTypeBuilder)
-            genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
         } else {
             generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
                 targetSchemaNode as ChoiceNode, augSchema.childNodes);
         }
     }
 
-    /**
-     * Utility method which search for original node defined in grouping.
-     */
-    private def DataSchemaNode findOriginal(DataSchemaNode node) {
-        var DataSchemaNode result = findCorrectTargetFromGrouping(node);
-        if (result == null) {
-            result = findCorrectTargetFromAugment(node);
-            if (result != null) {
-                if (result.addedByUses) {
-                    result = findOriginal(result);
-                }
-            }
-        }
-        return result;
-    }
-
-    private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {
-        if (!node.augmenting) {
-            return null
-        }
-
-        var QName currentName = node.QName
-        var Object currentNode = node
-        var Object parent = node;
-        val tmpPath = new ArrayList<QName>()
-        val tmpTree = new ArrayList<SchemaNode>()
-
-        var AugmentationSchema augment = null;
-        do {
-            val SchemaPath sp = (parent as SchemaNode).path
-            val List<QName> names = sp.path
-            val List<QName> newNames = new ArrayList(names)
-            newNames.remove(newNames.size - 1)
-            val SchemaPath newSp = new SchemaPath(newNames, sp.absolute)
-            parent = findDataSchemaNode(schemaContext, newSp)
-            if (parent instanceof AugmentationTarget) {
-                tmpPath.add(currentName);
-                tmpTree.add(currentNode as SchemaNode)
-                augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);
-                if (augment == null) {
-                    currentName = (parent as DataSchemaNode).QName
-                    currentNode = parent
-                }
-            }
-        } while ((parent as DataSchemaNode).augmenting && augment == null);
-
-        if (augment == null) {
-            return null;
-        } else {
-            Collections.reverse(tmpPath);
-            Collections.reverse(tmpTree);
-            var Object actualParent = augment;
-            var DataSchemaNode result = null;
-            for (name : tmpPath) {
-                if (actualParent instanceof DataNodeContainer) {
-                    result = (actualParent as DataNodeContainer).getDataChildByName(name.localName);
-                    actualParent = (actualParent as DataNodeContainer).getDataChildByName(name.localName);
-                } else {
-                    if (actualParent instanceof ChoiceNode) {
-                        result = (actualParent as ChoiceNode).getCaseNodeByName(name.localName);
-                        actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name.localName);
-                    }
-                }
-            }
-
-            if (result.addedByUses) {
-                result = findCorrectTargetFromAugmentGrouping(result, augment, tmpTree);
-            }
-
-            return result;
-        }
-    }
-
-    private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, QName name) {
-        for (augment : augments) {
-            val DataSchemaNode node = augment.getDataChildByName(name);
-            if (node != null) {
-                return augment;
-            }
-        }
-        return null;
-    }
-
-    private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {
-        if (node.path.path.size == 1) {
-            // uses is under module statement
-            val Module m = findParentModule(schemaContext, node);
-            var DataSchemaNode result = null;
-            for (u : m.uses) {
-                var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
-                if (!(targetGrouping instanceof GroupingDefinition)) {
-                    throw new IllegalArgumentException("Failed to generate code for augment in " + u);
-                }
-                var gr = targetGrouping as GroupingDefinition;
-                result = gr.getDataChildByName(node.QName.localName);
-            }
-            if (result == null) {
-                throw new IllegalArgumentException("Failed to generate code for augment")
-            }
-            return result
-        } else {
-            var DataSchemaNode result = null;
-            var QName currentName = node.QName
-            var tmpPath = new ArrayList<QName>()
-            var Object parent = null
-
-            val SchemaPath sp = node.path
-            val List<QName> names = sp.path
-            val List<QName> newNames = new ArrayList(names)
-            newNames.remove(newNames.size - 1)
-            val SchemaPath newSp = new SchemaPath(newNames, sp.absolute)
-            parent = findDataSchemaNode(schemaContext, newSp)
-
-            do {
-                tmpPath.add(currentName);
-                if (parent instanceof DataNodeContainer) {
-                    val dataNodeParent = parent as DataNodeContainer;
-                    for (u : dataNodeParent.uses) {
-                        if (result == null) {
-                            result = getResultFromUses(u, currentName.localName)
-                        }
-                    }
-                }
-                if (result == null) {
-                    currentName = (parent as SchemaNode).QName
-                    if (parent instanceof SchemaNode) {
-                        val SchemaPath nodeSp = (parent as SchemaNode).path
-                        val List<QName> nodeNames = nodeSp.path
-                        val List<QName> nodeNewNames = new ArrayList(nodeNames)
-                        nodeNewNames.remove(nodeNewNames.size - 1)
-                        if (nodeNewNames.empty) {
-                            parent = getParentModule(parent as SchemaNode)
-                        } else {
-                            val SchemaPath nodeNewSp = new SchemaPath(nodeNewNames, nodeSp.absolute)
-                            parent = findDataSchemaNode(schemaContext, nodeNewSp)
-                        }
-                    } else {
-                        throw new IllegalArgumentException("Failed to generate code for augment")
-                    }
-                }
-            } while (result == null && !(parent instanceof Module));
-
-            if (result != null) {
-                result = getTargetNode(tmpPath, result)
-            }
-            return result;
-        }
-    }
-
-    private def DataSchemaNode findCorrectTargetFromAugmentGrouping(DataSchemaNode node, AugmentationSchema parentNode,
-        List<SchemaNode> dataTree) {
-
-        var DataSchemaNode result = null;
-        var QName currentName = node.QName
-        var tmpPath = new ArrayList<QName>()
-        tmpPath.add(currentName)
-        var int i = 1;
-        var Object parent = null
-
-        do {
-            if (dataTree.size < 2 || dataTree.size == i) {
-                parent = parentNode
-            } else {
-                parent = dataTree.get(dataTree.size - (i+1))
-                tmpPath.add((parent as SchemaNode).QName)
-            }
-
-            val dataNodeParent = parent as DataNodeContainer;
-            for (u : dataNodeParent.uses) {
-                if (result == null) {
-                    result = getResultFromUses(u, currentName.localName)
-                }
-            }
-            if (result == null) {
-                i = i + 1
-                currentName = (parent as SchemaNode).QName
-            }
-        } while (result == null);
-
-        if (result != null) {
-            result = getTargetNode(tmpPath, result)
-        }
-        return result;
-    }
-
-    private def getResultFromUses(UsesNode u, String currentName) {
-        var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path)
-        if (!(targetGrouping instanceof GroupingDefinition)) {
-            throw new IllegalArgumentException("Failed to generate code for augment in " + u)
-        }
-        var gr = targetGrouping as GroupingDefinition
-        return gr.getDataChildByName(currentName)
-    }
-
-    private def getTargetNode(List<QName> tmpPath, DataSchemaNode node) {
-        var DataSchemaNode result = node
-        if (tmpPath.size == 1) {
-            if (result != null && result.addedByUses) {
-                result = findOriginal(result);
-            }
-            return result;
-        } else {
-            var DataSchemaNode newParent = result;
-            Collections.reverse(tmpPath);
-
-            tmpPath.remove(0);
-            for (name : tmpPath) {
-                // searching by local name is must, because node has different namespace in its original location
-                if (newParent instanceof DataNodeContainer) {
-                    newParent = (newParent as DataNodeContainer).getDataChildByName(name.localName);
-                } else {
-                    newParent = (newParent as ChoiceNode).getCaseNodeByName(name.localName);
-                }
-            }
-            if (newParent != null && newParent.addedByUses) {
-                newParent = findOriginal(newParent);
-            }
-            return newParent;
-        }
-    }
-
-
     /**
      * Convenient method to find node added by uses statement.
      */
@@ -1119,6 +898,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.childNodes);
         augmentBuilders.put(augTypeName, augTypeBuilder);
+        
+        genCtx.get(module).addTargetToAugmentation(targetTypeRef,augTypeBuilder);
+        genCtx.get(module).addAugmentType(augTypeBuilder);
+        genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
         return augTypeBuilder;
     }
 
@@ -1356,7 +1139,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                         var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath)
                         if (targetSchemaNode instanceof DataSchemaNode &&
                             (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
-                            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
+                            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode, schemaContext);
                             if (targetSchemaNode == null) {
                                 throw new NullPointerException(
                                     "Failed to find target node from grouping for augmentation " + augSchema +
@@ -1478,7 +1261,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *         <li>true - in other cases</li>
      *         </ul>
      */
-    private def boolean resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
+    private def Type resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
+        var Type returnType = null;
         if ((leaf !== null) && (typeBuilder !== null)) {
             val leafName = leaf.QName.localName;
             var String leafDesc = leaf.description;
@@ -1490,7 +1274,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
             if (leafName !== null && !leaf.isAddedByUses()) {
                 val TypeDefinition<?> typeDef = leaf.type;
 
-                var Type returnType = null;
                 var GeneratedTOBuilder genTOBuilder;
                 if (typeDef instanceof EnumTypeDefinition) {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
@@ -1518,11 +1301,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 if (returnType !== null) {
                     val MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
                     processContextRefExtension(leaf, getter, parentModule);
-                    return true;
                 }
             }
         }
-        return false;
+        return returnType;
     }
 
     private def void processContextRefExtension(LeafSchemaNode leaf, MethodSignatureBuilder getter, Module module) {
@@ -1581,25 +1363,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return null;
     }
 
-    /**
-     * Converts <code>leaf</code> schema node to property of generated TO
-     * builder.
-     *
-     * @param toBuilder
-     *            generated TO builder to which is <code>leaf</code> added as
-     *            property
-     * @param leaf
-     *            leaf schema node which is added to <code>toBuilder</code> as
-     *            property
-     * @param isReadOnly
-     *            boolean value which says if leaf property is|isn't read only
-     * @return boolean value
-     *         <ul>
-     *         <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
-     *         name equals null or if leaf is added by <i>uses</i>.</li>
-     *         <li>true - other cases</li>
-     *         </ul>
-     */
     private def boolean resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf,
         boolean isReadOnly, Module module) {
         if ((leaf !== null) && (toBuilder !== null)) {
@@ -1626,22 +1389,49 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 } else {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
                 }
-
-                if (returnType !== null) {
-                    val propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
-                    propBuilder.setReadOnly(isReadOnly);
-                    propBuilder.setReturnType(returnType);
-                    propBuilder.setComment(leafDesc);
-                    toBuilder.addEqualsIdentity(propBuilder);
-                    toBuilder.addHashIdentity(propBuilder);
-                    toBuilder.addToStringProperty(propBuilder);
-                    return true;
-                }
+                return resolveLeafSchemaNodeAsProperty(toBuilder, leaf, returnType, isReadOnly)
             }
         }
         return false;
     }
 
+    /**
+     * Converts <code>leaf</code> schema node to property of generated TO
+     * builder.
+     *
+     * @param toBuilder
+     *            generated TO builder to which is <code>leaf</code> added as
+     *            property
+     * @param leaf
+     *            leaf schema node which is added to <code>toBuilder</code> as
+     *            property
+     * @param returnType property type
+     * @param isReadOnly
+     *            boolean value which says if leaf property is|isn't read only
+     * @return boolean value
+     *         <ul>
+     *         <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
+     *         name equals null or if leaf is added by <i>uses</i>.</li>
+     *         <li>true - other cases</li>
+     *         </ul>
+     */
+    private def resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf, Type returnType,
+        boolean isReadOnly) {
+        if (returnType == null) {
+            return false;
+        }
+        val leafName = leaf.QName.localName
+        val leafDesc = leaf.description
+        val propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
+        propBuilder.setReadOnly(isReadOnly);
+        propBuilder.setReturnType(returnType);
+        propBuilder.setComment(leafDesc);
+        toBuilder.addEqualsIdentity(propBuilder);
+        toBuilder.addHashIdentity(propBuilder);
+        toBuilder.addToStringProperty(propBuilder);
+        return true;
+    }
+
     /**
      * Converts <code>node</code> leaf list schema node to getter method of
      * <code>typeBuilder</code>.
@@ -1826,6 +1616,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         //FIXME: Validation of name conflict
         val newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
+        newType.addComment(schemaNode.getDescription());
         if (!genTypeBuilders.containsKey(packageName)) {
             val Map<String, GeneratedTypeBuilder> builders = new HashMap();
             builders.put(genTypeName, newType);
@@ -1840,9 +1631,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
     }
 
     /**
-     * Creates the name of the getter method from <code>methodName</code>.
+     * Creates the name of the getter method name from <code>localName</code>.
      *
-     * @param methodName
+     * @param localName
      *            string with the name of the getter method
      * @param returnType return type
      * @return string with the name of the getter method for
@@ -1919,9 +1710,13 @@ public class BindingGeneratorImpl implements BindingGenerator {
         if (schemaNode instanceof LeafSchemaNode) {
             val leaf = schemaNode as LeafSchemaNode;
             val leafName = leaf.QName.localName;
-            resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
+            val Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
             if (listKeys.contains(leafName)) {
-                resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module)
+                if (type == null) {
+                    resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module)
+                } else {
+                    resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, type, true)
+                }
             }
         } else if (!schemaNode.addedByUses) {
             if (schemaNode instanceof LeafListSchemaNode) {
@@ -2079,6 +1874,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                         "Grouping " + usesNode.groupingPath + "is not resolved for " + builder.name);
                 }
                 builder.addImplementsType(genType);
+                builder.addComment(genType.getComment());
             }
         }
         return builder;
@@ -2114,13 +1910,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return null
     }
 
-    private def Module getParentModule(SchemaNode node) {
-        val QName qname = node.getPath().getPath().get(0);
-        val URI namespace = qname.getNamespace();
-        val Date revision = qname.getRevision();
-        return schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
-    }
-
     public def getModuleContexts() {
         genCtx;
     }