Added getParent() method to DataSchemaNode and DataNodeContainer. Fixed Bugs.
authorMartin Vitez <mvitez@cisco.com>
Tue, 22 Oct 2013 20:54:19 +0000 (22:54 +0200)
committerMartin Vitez <mvitez@cisco.com>
Tue, 22 Oct 2013 21:09:26 +0000 (23:09 +0200)
Fix for Bug 119.
Fix for Bug 120.
Fix for Bug 121.

Added more tests.

Change-Id: I7a88a1dc4b0ff8c277afab0560c89e91c8ff1a21
Signed-off-by: Martin Vitez <mvitez@cisco.com>
14 files changed:
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.xtend
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/SupportTestUtil.java
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/baz.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/test.yang [deleted file]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/baz.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/foo.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java

index 1cc3fb6a37d7d641953a01cc80b81af2b44948d7..c0802aecc5be43e0d8d794bc13be66a219966724 100644 (file)
@@ -61,13 +61,15 @@ import static org.opendaylight.yangtools.binding.generator.util.BindingGenerator
 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.*;\r
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*;\r
 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort\r
-import org.opendaylight.yangtools.yang.model.util.ExtendedType;\rimport org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.model.api.UsesNode
-import java.util.HashSet
-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.util.ExtendedType;\r
+import org.opendaylight.yangtools.yang.model.api.UsesNode\r
+import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext\r
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder\r
+import org.opendaylight.yangtools.yang.model.api.ModuleImport\r
+import org.opendaylight.yangtools.yang.binding.DataContainer\rimport java.util.Iterator
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
+import java.util.Collection
+import org.opendaylight.yangtools.yang.model.api.YangNode
 
 public class BindingGeneratorImpl implements BindingGenerator {\r
     /**\r
@@ -225,7 +227,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
     private def List<Type> allTypeDefinitionsToGenTypes(Module module) {\r
         checkArgument(module !== null, "Module reference cannot be NULL.");\r
         checkArgument(module.name !== null, "Module name cannot be NULL.");\r
-        val Set<TypeDefinition<?>> typeDefinitions = module.typeDefinitions;\r
+        val it = new DataNodeIterator(module);\r
+        val List<TypeDefinition<?>> typeDefinitions = it.allTypedefs;\r
         checkState(typeDefinitions !== null, '''Type Definitions for module «module.name» cannot be NULL.''');\r
 \r
         val List<Type> generatedTypes = new ArrayList();\r
@@ -284,7 +287,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 \r
         for (usesNode : node.uses) {\r
             for (augment : usesNode.augmentations) {\r
-                result.addAll(augmentationToGenTypes(basePackageName, augment, module, true));\r
+                result.addAll(augmentationToGenTypes(basePackageName, augment, module, usesNode));\r
                 result.addAll(processUsesAugments(augment, module));\r
             }\r
         }\r
@@ -433,7 +436,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val basePackageName = moduleNamespaceToPackageName(module);\r
         val List<AugmentationSchema> augmentations = resolveAugmentations(module);\r
         for (augment : augmentations) {\r
-            generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment, module, false));\r
+            generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment, module, null));\r
         }\r
         return generatedTypes;\r
     }\r
@@ -916,90 +919,225 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             <li>if target path of <code>augSchema</code> equals null</li>\r
      *             </ul>\r
      */\r
-    private def List<Type> augmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module, boolean addedByUses) {\r
-        checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");\r
-        checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");\r
-        checkState(augSchema.targetPath !== null,\r
-            "Augmentation Schema does not contain Target Path (Target Path is NULL).");\r
-        val List<Type> genTypes = new ArrayList();\r
-        genTypes.addAll(processUsesAugments(augSchema, module));\r
-\r
+    private def List<Type> augmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module,
+        UsesNode parentUsesNode) {
+        checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");
+        checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");
+        checkState(augSchema.targetPath !== null,
+            "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+        val List<Type> genTypes = new ArrayList();
+        genTypes.addAll(processUsesAugments(augSchema, module));
+
         // EVERY augmented interface will extends Augmentation<T> interface\r
         // and DataObject interface!!!\r
-        val targetPath = augSchema.targetPath;\r
-        var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);\r
+        val targetPath = augSchema.targetPath;
+        var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
         if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {\r
-                       targetSchemaNode = findOriginalTargetFromGrouping(targetPath, module, targetSchemaNode as DataSchemaNode);\r
-        }\r
-\r
-        if(targetSchemaNode !== null) {\r
-            var targetType = yangToJavaMapping.get(targetSchemaNode.path);\r
-            if(targetType == null) {\r
-\r
+            if (parentUsesNode == null) {\r
+                targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);\r
+            } else {\r
+                targetSchemaNode = findOriginalTargetFromGrouping(targetSchemaNode.QName.localName, parentUsesNode);\r
+            }\r
+            if (targetSchemaNode == null) {\r
+                throw new NullPointerException(\r
+                    "Failed to find target node from grouping for augmentation " + augSchema + " in module " + module.name);\r
+            }
+        }
+\r
+        if (targetSchemaNode !== null) {
+            var targetType = yangToJavaMapping.get(targetSchemaNode.path);
+            if (targetType == null) {
                 // FIXME: augmentation should be added as last, all types should already be generated\r
                 // and have assigned Java Types,\r
-                val targetModule = findParentModule(schemaContext, targetSchemaNode);\r
-                val targetBasePackage = moduleNamespaceToPackageName(targetModule);\r
-                val typePackage = packageNameForGeneratedType(targetBasePackage, targetSchemaNode.getPath());\r
-                val targetSchemaNodeName = targetSchemaNode.getQName().getLocalName();\r
-                val typeName = parseToClassName(targetSchemaNodeName);\r
-                targetType = new ReferencedTypeImpl(typePackage, typeName);\r
-            }\r
-            val augChildNodes = augSchema.childNodes;\r
+                val targetModule = findParentModule(schemaContext, targetSchemaNode);
+                val targetBasePackage = moduleNamespaceToPackageName(targetModule);
+                val typePackage = packageNameForGeneratedType(targetBasePackage, targetSchemaNode.getPath());
+                val targetSchemaNodeName = targetSchemaNode.getQName().getLocalName();
+                val typeName = parseToClassName(targetSchemaNodeName);
+                targetType = new ReferencedTypeImpl(typePackage, typeName);
+            }
+            val augChildNodes = augSchema.childNodes;
+
+            if (!(targetSchemaNode instanceof ChoiceNode)) {
+                var packageName = augmentPackageName;
+                if (parentUsesNode != null) {
+                    packageName = packageNameForGeneratedType(augmentPackageName, augSchema.targetPath);
+                }
+                val augTypeBuilder = addRawAugmentGenTypeDefinition(packageName, augmentPackageName, targetType,
+                    augSchema);
+                val augType = augTypeBuilder.toInstance();
+                genTypes.add(augType);
+            } else {
+                genTypes.addAll(
+                    generateTypesFromAugmentedChoiceCases(augmentPackageName, targetType, augChildNodes,
+                        targetSchemaNode as ChoiceNode));
+            }
+            genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes, module));
+        }
+
+        return genTypes;
+    }\r
 \r
-            if(!(targetSchemaNode instanceof ChoiceNode)) {\r
-                var packageName = augmentPackageName;\r
-                if (addedByUses) {\r
-                    packageName = packageNameForGeneratedType(augmentPackageName, augSchema.targetPath);\r
+    /**\r
+     * Utility method which search for original node defined in grouping.\r
+     */\r
+    private def DataSchemaNode findOriginal(DataSchemaNode node) {\r
+        var DataSchemaNode result = findCorrectTargetFromGrouping(node);\r
+        if (result == null) {\r
+            result = findCorrectTargetFromAugment(node);\r
+            if (result != null) {\r
+                if (result.addedByUses) {\r
+                    result = findOriginal(result);\r
                 }\r
-                val augTypeBuilder = addRawAugmentGenTypeDefinition(packageName, augmentPackageName, targetType, augSchema);\r
-                val augType = augTypeBuilder.toInstance();\r
-                genTypes.add(augType);\r
-            } else {\r
-                genTypes.addAll(generateTypesFromAugmentedChoiceCases(augmentPackageName, targetType, augChildNodes, targetSchemaNode as ChoiceNode));\r
             }\r
-            genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes, module));\r
         }\r
-               \r
-        return genTypes;\r
+        return result;\r
     }\r
 \r
-    private def DataSchemaNode findOriginalTargetFromGrouping(SchemaPath targetPath, Module module, DataSchemaNode targetSchemaNode) {\r
-        val path = new ArrayList<QName>(targetPath.getPath());\r
-        path.remove(path.size()-1);\r
-        var DataNodeContainer parent = null;\r
+    private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {\r
+        if (!node.augmenting) {\r
+            return null;\r
+        }\r
 \r
-        if (path.isEmpty()) {\r
-            parent = module;\r
+        var String currentName = node.QName.localName;\r
+        var tmpPath = new ArrayList<String>();\r
+        var YangNode parent = node;\r
+        var AugmentationSchema augment = null;\r
+        do {\r
+            parent = (parent as DataSchemaNode).parent;\r
+            if (parent instanceof AugmentationTarget) {\r
+                tmpPath.add(currentName);\r
+                augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);\r
+                if (augment == null) {\r
+                    currentName = (parent as DataSchemaNode).QName.localName; \r
+                }\r
+            }\r
+        } while ((parent as DataSchemaNode).augmenting && augment == null);\r
+\r
+        if (augment == null) {\r
+            return null;\r
         } else {\r
-            parent = findNodeInSchemaContext(schemaContext, path) as DataNodeContainer;\r
+            Collections.reverse(tmpPath);\r
+            var Object actualParent = augment;\r
+            var DataSchemaNode result = null;\r
+            for (name : tmpPath) {\r
+                if (actualParent instanceof DataNodeContainer) {\r
+                    result = (actualParent as DataNodeContainer).getDataChildByName(name);\r
+                    actualParent = (actualParent as DataNodeContainer).getDataChildByName(name);\r
+                } else {\r
+                    if (actualParent instanceof ChoiceNode) {\r
+                        result = (actualParent as ChoiceNode).getCaseNodeByName(name);\r
+                        actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name); \r
+                    }\r
+                }\r
+            }\r
+\r
+            if (result.addedByUses) {\r
+                result = findCorrectTargetFromGrouping(result);\r
+            }\r
+\r
+            return result;\r
         }\r
+    }\r
 \r
-        val Set<UsesNode> usesNodes = parent.getUses();\r
-        if (usesNodes == null || usesNodes.isEmpty()) {\r
-            return targetSchemaNode;\r
+    private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, String name) {\r
+        for (augment : augments) {\r
+            if (augment.getDataChildByName(name) != null) {\r
+                return augment;\r
+            }\r
         }\r
-        val Set<SchemaPath> groupingPaths = new HashSet<SchemaPath>();\r
-        for (uses : usesNodes) {\r
-            groupingPaths.add(uses.getGroupingPath());\r
+        return null;\r
+    }\r
+\r
+    private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {\r
+        if (node.path.path.size == 1) {\r
+            // uses is under module statement\r
+            val Module m = findParentModule(schemaContext, node);\r
+            var DataSchemaNode result = null;\r
+            for (u : m.uses) {\r
+                var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);\r
+                if (!(targetGrouping instanceof GroupingDefinition)) {\r
+                    throw new IllegalArgumentException("Failed to generate code for augment in " + u);\r
+                }\r
+                var gr = targetGrouping as GroupingDefinition;\r
+                result = gr.getDataChildByName(node.QName.localName);\r
+            }\r
+            if (result == null) {\r
+                throw new IllegalArgumentException("Failed to generate code for augment");\r
+            }\r
+            return result;\r
+        } else {\r
+            var DataSchemaNode result = null;\r
+            var String currentName = node.QName.localName;\r
+            var tmpPath = new ArrayList<String>();\r
+            var YangNode parent = node.parent; \r
+            do {\r
+                tmpPath.add(currentName);\r
+                val dataNodeParent = parent as DataNodeContainer;\r
+                for (u : dataNodeParent.uses) {\r
+                    var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);\r
+                    if (!(targetGrouping instanceof GroupingDefinition)) {\r
+                        throw new IllegalArgumentException("Failed to generate code for augment in " + u);\r
+                    }\r
+                    var gr = targetGrouping as GroupingDefinition;\r
+                    result = gr.getDataChildByName(currentName);\r
+                }\r
+                if (result == null) {\r
+                    currentName = (parent as SchemaNode).QName.localName;\r
+                    if (parent instanceof DataSchemaNode) {\r
+                        parent = (parent as DataSchemaNode).parent;\r
+                    } else {\r
+                        parent = (parent as DataNodeContainer).parent;\r
+                    }\r
+                }\r
+            } while (result == null && !(parent instanceof Module));\r
+\r
+            if (result != null) {\r
+                if (tmpPath.size == 1) {\r
+                    return result;\r
+                } else {\r
+                    var DataSchemaNode newParent = result;\r
+                    Collections.reverse(tmpPath);\r
+                    tmpPath.remove(0);\r
+                    for (name : tmpPath) {\r
+                        newParent = (newParent as DataNodeContainer).getDataChildByName(name);\r
+                    }\r
+                    return newParent;\r
+                }\r
+            }\r
+\r
+            return result;\r
         }\r
-        val Set<GroupingDefinition> groupings = new HashSet<GroupingDefinition>();\r
-        for (gp : groupingPaths) {\r
-            groupings.add(findGrouping(schemaContext, module, gp.getPath()));\r
+    }\r
+\r
+    /**\r
+     * Convenient method to find node added by uses statement.\r
+     */\r
+    private def DataSchemaNode findOriginalTargetFromGrouping(String targetSchemaNodeName, UsesNode parentUsesNode) {\r
+        var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.groupingPath.path);\r
+        if (!(targetGrouping instanceof GroupingDefinition)) {\r
+            throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);\r
         }\r
 \r
-        var DataSchemaNode result = findNodeInGroupings(groupings, targetSchemaNode.getQName().localName);\r
-        return result;\r
-    }\r
+        var grouping = targetGrouping as GroupingDefinition;\r
+        var result = grouping.getDataChildByName(targetSchemaNodeName);\r
+        if (result == null) {\r
+            return null;\r
+        }\r
+        var boolean fromUses = result.addedByUses;\r
 \r
-    private def DataSchemaNode findNodeInGroupings(Set<GroupingDefinition> groupings, String name) {\r
-        for (gr : groupings) {\r
-            var DataSchemaNode node = gr.getDataChildByName(name);\r
-            if (node != null) {\r
-               return node;\r
+        var Iterator<UsesNode> groupingUses = grouping.uses.iterator;\r
+        while (fromUses) {\r
+            if (groupingUses.hasNext()) {\r
+                grouping = findNodeInSchemaContext(schemaContext, groupingUses.next().groupingPath.path) as GroupingDefinition;\r
+                result = grouping.getDataChildByName(targetSchemaNodeName);\r
+                fromUses = result.addedByUses;\r
+            } else {\r
+                throw new NullPointerException("Failed to generate code for augment in " + parentUsesNode);\r
             }\r
         }\r
-        return null;\r
+\r
+        return result;\r
     }\r
 \r
     /**\r
@@ -1021,31 +1159,31 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *            and uses of augment\r
      * @return generated type builder for augment\r
      */\r
-    private def GeneratedTypeBuilder addRawAugmentGenTypeDefinition(String augmentPackageName, String basePackageName,
-               Type targetTypeRef, AugmentationSchema augSchema) {
-               var Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
-               if (augmentBuilders === null) {
-                       augmentBuilders = new HashMap();
-                       genTypeBuilders.put(augmentPackageName, augmentBuilders);
-               }
-               val augIdentifier = getAugmentIdentifier(augSchema.unknownSchemaNodes);
-
-               val augTypeName = if (augIdentifier !== null) {
-                               parseToClassName(augIdentifier)
-                       } else {
-                               augGenTypeName(augmentBuilders, targetTypeRef.name);
-                       }
-
-               val augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
-
-               augTypeBuilder.addImplementsType(DATA_OBJECT);
-               augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
-               addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
-
-               augSchemaNodeToMethods(basePackageName, augTypeBuilder, augSchema.childNodes);
-               augmentBuilders.put(augTypeName, augTypeBuilder);
-               return augTypeBuilder;
-       }\r
+    private def GeneratedTypeBuilder addRawAugmentGenTypeDefinition(String augmentPackageName, String basePackageName,\r
+        Type targetTypeRef, AugmentationSchema augSchema) {\r
+        var Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);\r
+        if (augmentBuilders === null) {\r
+            augmentBuilders = new HashMap();\r
+            genTypeBuilders.put(augmentPackageName, augmentBuilders);\r
+        }\r
+        val augIdentifier = getAugmentIdentifier(augSchema.unknownSchemaNodes);\r
+\r
+        val augTypeName = if (augIdentifier !== null) {\r
+                parseToClassName(augIdentifier)\r
+            } else {\r
+                augGenTypeName(augmentBuilders, targetTypeRef.name);\r
+            }\r
+\r
+        val augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);\r
+\r
+        augTypeBuilder.addImplementsType(DATA_OBJECT);\r
+        augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));\r
+        addImplementedInterfaceFromUses(augSchema, augTypeBuilder);\r
+\r
+        augSchemaNodeToMethods(basePackageName, augTypeBuilder, augSchema.childNodes);\r
+        augmentBuilders.put(augTypeName, augTypeBuilder);\r
+        return augTypeBuilder;\r
+    }\r
 \r
     /**\r
      *\r
@@ -1080,6 +1218,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val List<Type> genTypes = new ArrayList();\r
         val List<DataNodeIterator> augSchemaIts = new ArrayList();\r
         for (childNode : augChildNodes) {\r
+            if (!childNode.addedByUses) {\r
+                \r
+            \r
             if(childNode instanceof DataNodeContainer) {\r
                 augSchemaIts.add(new DataNodeIterator(childNode as DataNodeContainer));\r
 \r
@@ -1095,6 +1236,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 }\r
                 genTypes.addAll(choiceToGeneratedType(augBasePackageName, childNode as ChoiceNode, module));\r
             }\r
+            \r
+            \r
+            }\r
         }\r
 \r
         for (it : augSchemaIts) {\r
@@ -1916,14 +2060,16 @@ public class BindingGeneratorImpl implements BindingGenerator {
             } else {\r
                 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);\r
             }\r
-        } else if(schemaNode instanceof LeafListSchemaNode) {\r
-            resolveLeafListSchemaNode(typeBuilder, schemaNode as LeafListSchemaNode);\r
-        } else if(schemaNode instanceof ContainerSchemaNode) {\r
-            resolveContainerSchemaNode(basePackageName, typeBuilder, schemaNode as ContainerSchemaNode);\r
-        } else if(schemaNode instanceof ChoiceNode) {\r
-            resolveChoiceSchemaNode(basePackageName,typeBuilder,schemaNode as ChoiceNode);\r
-        } else if(schemaNode instanceof ListSchemaNode) {\r
-            resolveListSchemaNode(basePackageName, typeBuilder, schemaNode as ListSchemaNode);\r
+        } else if (!schemaNode.addedByUses) {\r
+            if (schemaNode instanceof LeafListSchemaNode) {\r
+                resolveLeafListSchemaNode(typeBuilder, schemaNode as LeafListSchemaNode);\r
+            } else if(schemaNode instanceof ContainerSchemaNode) {\r
+                resolveContainerSchemaNode(basePackageName, typeBuilder, schemaNode as ContainerSchemaNode);\r
+            } else if(schemaNode instanceof ChoiceNode) {\r
+                resolveChoiceSchemaNode(basePackageName,typeBuilder,schemaNode as ChoiceNode);\r
+            } else if(schemaNode instanceof ListSchemaNode) {\r
+                resolveListSchemaNode(basePackageName, typeBuilder, schemaNode as ListSchemaNode);\r
+            }\r
         }\r
     }\r
 \r
index 3068f46fe6939d5403f14a22beaf86f00d97799b..048de43e7172392168cb1099a1be75430a4ca2ba 100644 (file)
@@ -8,7 +8,8 @@
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
 import static org.junit.Assert.*;
-import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.*;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsInterface;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsMethods;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -70,6 +71,7 @@ public class ChoiceCaseGenTypesTest {
     public void choiceCaseResolvingTypeTest() {
         final YangModelParser parser = new YangParserImpl();
         final Set<Module> modules = parser.parseYangModels(yangModels);
+
         final SchemaContext context = parser.resolveSchemaContext(modules);
 
         assertNotNull("context is null", context);
@@ -141,6 +143,7 @@ public class ChoiceCaseGenTypesTest {
 
         genType = checkGeneratedType(genTypes, "LeafAugCase", pcgPref
                 + ".netconf.state.datastores.datastore.locks.lock.type"); // choice
+        // FIXME
         containsMethods(genType, new NameTypePattern("getLeafAugCase", "String"));
         containsInterface("LockType", genType);
 
index acaf426cf981eebdca10e8a061c6da7318e0981d..aee0c431d94451b80921790753d5dea6bc8ea783 100644 (file)
@@ -117,7 +117,7 @@ public class SupportTestUtil {
                 break;
             }
         }
-        assertTrue("Generated type " + genType.getName() + " doesn't implement inrerface " + interfaceNameSearched,
+        assertTrue("Generated type " + genType.getName() + " doesn't implement interface " + interfaceNameSearched,
                 interfaceFound);
     }
 
index 0581b95ddc96f73d50f2923ac41f0c55fcc83230..59d4523affb5e4e93104a1f994350b16f8c5c70c 100644 (file)
@@ -43,14 +43,17 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
 /**
  * Test correct code generation.
- * 
+ *
  */
 public class CompilationTest {
     private static final String FS = File.separator;
-    private static final String NS_TEST = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1" + FS
-            + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
-    private static final String NS_FOO = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1" + FS
-            + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
+    private static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
+    private static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
+    private static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
+    private static final String NS_BAR = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "bar" + FS + "rev131008";
+    private static final String NS_BAZ = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "baz" + FS + "rev131008";
+
+    private static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
 
     private static final String TEST_PATH = "target" + FS + "test";
     private static final File TEST_DIR = new File(TEST_PATH);
@@ -62,6 +65,8 @@ public class CompilationTest {
 
     private YangParserImpl parser;
     private BindingGenerator bindingGenerator;
+    private JavaCompiler compiler;
+    private StandardJavaFileManager fileManager;
 
     @BeforeClass
     public static void createTestDirs() {
@@ -76,6 +81,8 @@ public class CompilationTest {
     public void init() {
         parser = new YangParserImpl();
         bindingGenerator = new BindingGeneratorImpl();
+        compiler = ToolProvider.getSystemJavaCompiler();
+        fileManager = compiler.getStandardFileManager(null, null, null);
     }
 
     /**
@@ -107,32 +114,63 @@ public class CompilationTest {
 
         // Test if all sources are generated
         File parent = new File(sourcesOutputDir, NS_TEST);
-        File linksKeyFile = new File(parent, "LinksKey.java");
-        assertTrue(new File(parent, "KeyArgs.java").exists());
-        assertTrue(new File(parent, "Links.java").exists());
-        assertTrue(new File(parent, "LinksBuilder.java").exists());
-        assertTrue(linksKeyFile.exists());
-        assertTrue(new File(parent, "TestData.java").exists());
-        assertTrue(new File(parent, "links" + FS + "Level.java").exists());
-        assertTrue(new File(parent, "links" + FS + "LinkGroup.java").exists());
-        assertTrue(new File(parent, "links" + FS + "Node.java").exists());
-        assertTrue(new File(parent, "links" + FS + "NodeBuilder.java").exists());
-        assertTrue(new File(parent, "links" + FS + "NodeList.java").exists());
-        assertTrue(new File(parent, "links" + FS + "NodeListBuilder.java").exists());
-        assertTrue(linksKeyFile.exists());
+        assertEquals(6, parent.listFiles().length);
+        File keyArgs = new File(parent, "KeyArgs.java");
+        File links = new File(parent, "Links.java");
+        File linksBuilder = new File(parent, "LinksBuilder.java");
+        File linksKey = new File(parent, "LinksKey.java");
+        File testData = new File(parent, "TestData.java");
+        assertTrue(keyArgs.exists());
+        assertTrue(links.exists());
+        assertTrue(linksBuilder.exists());
+        assertTrue(linksKey.exists());
+        assertTrue(testData.exists());
+
+        parent = new File(sourcesOutputDir, NS_TEST + FS + "links");
+        assertEquals(7, parent.listFiles().length);
+        File level = new File(parent, "Level.java");
+        File linkGroup = new File(parent, "LinkGroup.java");
+        File node = new File(parent, "Node.java");
+        File nodeBuilder = new File(parent, "NodeBuilder.java");
+        File nodeList = new File(parent, "NodeList.java");
+        File nodeListBuilder = new File(parent, "NodeListBuilder.java");
+        File nodesType = new File(parent, "NodesType.java");
+        assertTrue(level.exists());
+        assertTrue(linkGroup.exists());
+        assertTrue(node.exists());
+        assertTrue(nodeBuilder.exists());
+        assertTrue(nodeList.exists());
+        assertTrue(nodeListBuilder.exists());
+        assertTrue(nodesType.exists());
 
         // Test if sources are compilable
-        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
-        List<File> filesList = getJavaFiles(sourcesOutputDir);
-        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
-        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
-        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
-        assertTrue(compiled);
+        testCompilation(sourcesOutputDir, compiledOutputDir);
 
         ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
-        Class<?> linksKeyClass = Class.forName("org.opendaylight.yang.gen.v1.urn.opendaylight.test.rev131008.LinksKey",
-                true, loader);
+        Class<?> keyArgsClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.KeyArgs", true, loader);
+        Class<?> linksClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Links", true, loader);
+        Class<?> linksKeyClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksKey", true, loader);
+
+        // Test generated 'grouping key-args'
+        try {
+            assertTrue(keyArgsClass.isInterface());
+            assertEquals(3, keyArgsClass.getDeclaredMethods().length);
+
+            Method getId = keyArgsClass.getMethod("getId");
+            assertEquals(Byte.class, getId.getReturnType());
+            Method getName = keyArgsClass.getMethod("getName");
+            assertEquals(String.class, getName.getReturnType());
+            Method getSize = keyArgsClass.getMethod("getSize");
+            assertEquals(Integer.class, getSize.getReturnType());
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("Required method not found in " + keyArgsClass, e);
+        }
+
+        // test generated 'list links'
+        assertTrue(linksClass.isInterface());
+        // FIXME: anyxml
+        assertEquals(5, linksClass.getDeclaredMethods().length);
+        testImplementIfc(linksClass, keyArgsClass);
 
         // Test list key constructor arguments ordering
         try {
@@ -158,26 +196,218 @@ public class CompilationTest {
         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
         generator.generateToFile(sourcesOutputDir);
 
-        // Test if all sources are generated
-        File parent = new File(sourcesOutputDir, NS_TEST);
+        // Test if all sources were generated from 'module foo'
+        File parent = new File(sourcesOutputDir, NS_FOO);
+        assertEquals(7, parent.listFiles().length);
         assertTrue(new File(parent, "Object.java").exists());
         assertTrue(new File(parent, "OpenObject.java").exists());
-        assertTrue(new File(parent, "object" + FS + "Nodes.java").exists());
-        assertTrue(new File(parent, "object" + FS + "NodesBuilder.java").exists());
-        assertTrue(new File(parent, "open" + FS + "object" + FS + "Nodes1.java").exists());
-        assertTrue(new File(parent, "open" + FS + "object" + FS + "Nodes1Builder.java").exists());
-        assertTrue(new File(parent, "open" + FS + "object" + FS + "nodes" + FS + "Links.java").exists());
-        assertTrue(new File(parent, "open" + FS + "object" + FS + "nodes" + FS + "LinksBuilder.java").exists());
+        assertTrue(new File(parent, "ExplicitRouteObject.java").exists());
+        assertTrue(new File(parent, "PathKeySubobject.java").exists());
+
+        parent = new File(parent, "object");
+        assertEquals(2, parent.listFiles().length);
+        assertTrue(new File(parent, "Nodes.java").exists());
+        assertTrue(new File(parent, "NodesBuilder.java").exists());
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "open");
+        assertEquals(1, parent.listFiles().length);
+
+        parent = new File(parent, "object");
+        assertEquals(3, parent.listFiles().length);
+        assertTrue(new File(parent, "Nodes1.java").exists());
+        assertTrue(new File(parent, "Nodes1Builder.java").exists());
+
+        parent = new File(parent, "nodes");
+        assertEquals(2, parent.listFiles().length);
+        assertTrue(new File(parent, "Links.java").exists());
+        assertTrue(new File(parent, "LinksBuilder.java").exists());
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "explicit");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "route");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "object");
+        assertEquals(3, parent.listFiles().length);
+        assertTrue(new File(parent, "Subobjects.java").exists());
+        assertTrue(new File(parent, "SubobjectsBuilder.java").exists());
+
+        parent = new File(parent, "subobjects");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "subobject");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "type");
+        assertEquals(3, parent.listFiles().length);
+        assertTrue(new File(parent, "PathKey.java").exists());
+        assertTrue(new File(parent, "PathKeyBuilder.java").exists());
+
+        parent = new File(parent, "path");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "key");
+        assertEquals(2, parent.listFiles().length);
+        assertTrue(new File(parent, "PathKey.java").exists());
+        assertTrue(new File(parent, "PathKeyBuilder.java").exists());
+
+        // Test if all sources were generated from 'module bar'
+        parent = new File(sourcesOutputDir, NS_BAR);
+        assertEquals(3, parent.listFiles().length);
+        assertTrue(new File(parent, "BasicExplicitRouteSubobjects.java").exists());
+        assertTrue(new File(parent, "ExplicitRouteSubobjects.java").exists());
+
+        parent = new File(parent, "basic");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "explicit");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "route");
+        assertEquals(1, parent.listFiles().length);
+
+        parent = new File(parent, "subobjects");
+        assertEquals(2, parent.listFiles().length);
+        assertTrue(new File(parent, "SubobjectType.java").exists());
+
+        parent = new File(parent, "subobject");
+        assertEquals(1, parent.listFiles().length);
+
+        parent = new File(parent, "type");
+        assertEquals(4, parent.listFiles().length);
+        assertTrue(new File(parent, "IpPrefix.java").exists());
+        assertTrue(new File(parent, "IpPrefixBuilder.java").exists());
+        assertTrue(new File(parent, "Label.java").exists());
+        assertTrue(new File(parent, "LabelBuilder.java").exists());
 
         // Test if sources are compilable
-        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+        testCompilation(sourcesOutputDir, compiledOutputDir);
 
-        List<File> filesList = getJavaFiles(sourcesOutputDir);
-        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
-        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
-        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
-        assertTrue(compiled);
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void testAugmentOfAugmentGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "aug-of-aug");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "aug-of-aug");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/augment-of-augment");
+        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        // Test if all sources were generated from 'module foo'
+        File parent = new File(sourcesOutputDir, NS_FOO);
+        assertEquals(6, parent.listFiles().length);
+        File fooListener = new File(parent, "FooListener.java");
+        File pathAttributes = new File(parent, "PathAttributes.java");
+        File update = new File(parent, "Update.java");
+        File updateBuilder = new File(parent, "UpdateBuilder.java");
+        assertTrue(fooListener.exists());
+        assertTrue(pathAttributes.exists());
+        assertTrue(update.exists());
+        assertTrue(updateBuilder.exists());
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "path");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "attributes");
+        assertEquals(2, parent.listFiles().length);
+        File origin = new File(parent, "Origin.java");
+        File originBuilder = new File(parent, "OriginBuilder.java");
+        assertTrue(origin.exists());
+        assertTrue(originBuilder.exists());
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "update");
+        assertEquals(2, parent.listFiles().length);
+        pathAttributes = new File(parent, "PathAttributes.java");
+        File pathAttributesBuilder = new File(parent, "PathAttributesBuilder.java");
+        assertTrue(pathAttributes.exists());
+        assertTrue(pathAttributesBuilder.exists());
+
+        // Test if all sources were generated from 'module bar'
+        parent = new File(sourcesOutputDir, NS_BAR);
+        assertEquals(5, parent.listFiles().length);
+        File destination = new File(parent, "Destination.java");
+        File pathAttributes1 = new File(parent, "PathAttributes1.java");
+        File pathAttributes1Builder = new File(parent, "PathAttributes1Builder.java");
+        assertTrue(destination.exists());
+        assertTrue(pathAttributes1.exists());
+        assertTrue(pathAttributes1Builder.exists());
+
+        parent = new File(sourcesOutputDir, NS_BAR + FS + "destination");
+        assertEquals(2, parent.listFiles().length);
+        File destinationType = new File(parent, "DestinationType.java");
+        assertTrue(destinationType.exists());
+
+        parent = new File(parent, "destination");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "type");
+        assertEquals(2, parent.listFiles().length);
+        File destinationIpv4 = new File(parent, "DestinationIp.java");
+        File destinationIpv4Builder = new File(parent, "DestinationIpBuilder.java");
+        assertTrue(destinationIpv4.exists());
+        assertTrue(destinationIpv4Builder.exists());
+
+        parent = new File(sourcesOutputDir, NS_BAR + FS + "update");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "path");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "attributes");
+        assertEquals(3, parent.listFiles().length);
+        File mpUnreachNlri = new File(parent, "MpUnreachNlri.java");
+        File mpUnreachNlriBuilder = new File(parent, "MpUnreachNlriBuilder.java");
+        assertTrue(mpUnreachNlri.exists());
+        assertTrue(mpUnreachNlriBuilder.exists());
+
+        parent = new File(parent, "mp");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "unreach");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "nlri");
+        assertEquals(3, parent.listFiles().length);
+        File withdrawnRoutes = new File(parent, "WithdrawnRoutes.java");
+        File withdrawnRoutesBuilder = new File(parent, "WithdrawnRoutesBuilder.java");
+        assertTrue(withdrawnRoutes.exists());
+        assertTrue(withdrawnRoutesBuilder.exists());
+
+        parent = new File(parent, "withdrawn");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "routes");
+        assertEquals(1, parent.listFiles().length);
+        destinationType = new File(parent, "DestinationType.java");
+        assertTrue(destinationType.exists());
+
+        // Test if all sources were generated from 'module baz'
+        parent = new File(sourcesOutputDir, NS_BAZ);
+        assertEquals(2, parent.listFiles().length);
+        File linkstateDestination = new File(parent, "LinkstateDestination.java");
+        assertTrue(linkstateDestination.exists());
+
+        parent = new File(sourcesOutputDir, NS_BAZ + FS + "update");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "path");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "attributes");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "mp");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "unreach");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "nlri");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "withdrawn");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "routes");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "destination");
+        assertEquals(1, parent.listFiles().length);
+        parent = new File(parent, "type");
+        assertEquals(2, parent.listFiles().length);
+        File destinationLinkstate = new File(parent, "DestinationLinkstate.java");
+        File destinationLinkstateBuilder = new File(parent, "DestinationLinkstateBuilder.java");
+        assertTrue(destinationLinkstate.exists());
+        assertTrue(destinationLinkstateBuilder.exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
 
         cleanUp(sourcesOutputDir, compiledOutputDir);
     }
@@ -202,40 +432,34 @@ public class CompilationTest {
         assertTrue(new File(parent, "NodesBuilder.java").exists());
         assertTrue(new File(parent, "Alg.java").exists());
 
-        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
-
-        List<File> filesList = getJavaFiles(sourcesOutputDir);
-        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
-        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
-        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
-        assertTrue(compiled);
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
 
-        String pkg = "org.opendaylight.yang.gen.v1.urn.opendaylight.test.rev131008";
+        String pkg = BASE_PKG + ".urn.opendaylight.test.rev131008";
         ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
         Class<?> nodesClass = Class.forName(pkg + ".Nodes", true, loader);
 
         // Test methods return type
         byte[] b = new byte[] {};
         testReturnType(nodesClass, "getIdBinary", b.getClass());
-        testReturnType(loader, nodesClass, "getIdBits", pkg + ".Nodes$IdBits");
-        testReturnType(loader, nodesClass, "isIdBoolean", "java.lang.Boolean");
-        testReturnType(loader, nodesClass, "getIdDecimal64", "java.math.BigDecimal");
-        testReturnType(loader, nodesClass, "isIdEmpty", "java.lang.Boolean");
-        testReturnType(loader, nodesClass, "getIdEnumeration", pkg + ".Nodes$IdEnumeration");
+        testReturnType(nodesClass, "getIdBits", pkg + ".Nodes$IdBits", loader);
+        testReturnType(nodesClass, "isIdBoolean", "java.lang.Boolean", loader);
+        testReturnType(nodesClass, "getIdDecimal64", "java.math.BigDecimal", loader);
+        testReturnType(nodesClass, "isIdEmpty", "java.lang.Boolean", loader);
+        testReturnType(nodesClass, "getIdEnumeration", pkg + ".Nodes$IdEnumeration", loader);
         testReturnTypeIdentityref(nodesClass, "getIdIdentityref", pkg + ".Alg");
         testReturnTypeInstanceIdentitifer(loader, nodesClass, "getIdInstanceIdentifier");
-        testReturnType(loader, nodesClass, "getId8", "java.lang.Byte");
-        testReturnType(loader, nodesClass, "getId16", "java.lang.Short");
-        testReturnType(loader, nodesClass, "getId32", "java.lang.Integer");
-        testReturnType(loader, nodesClass, "getId64", "java.lang.Long");
-        testReturnType(loader, nodesClass, "getIdLeafref", "java.lang.Long");
-        testReturnType(loader, nodesClass, "getIdString", "java.lang.String");
-        testReturnType(loader, nodesClass, "getIdU8", "java.lang.Short");
-        testReturnType(loader, nodesClass, "getIdU16", "java.lang.Integer");
-        testReturnType(loader, nodesClass, "getIdU32", "java.lang.Long");
-        testReturnType(loader, nodesClass, "getIdU64", "java.math.BigInteger");
-        testReturnType(loader, nodesClass, "getIdUnion", pkg + ".Nodes$IdUnion");
+        testReturnType(nodesClass, "getId8", "java.lang.Byte", loader);
+        testReturnType(nodesClass, "getId16", "java.lang.Short", loader);
+        testReturnType(nodesClass, "getId32", "java.lang.Integer", loader);
+        testReturnType(nodesClass, "getId64", "java.lang.Long", loader);
+        testReturnType(nodesClass, "getIdLeafref", "java.lang.Long", loader);
+        testReturnType(nodesClass, "getIdString", "java.lang.String", loader);
+        testReturnType(nodesClass, "getIdU8", "java.lang.Short", loader);
+        testReturnType(nodesClass, "getIdU16", "java.lang.Integer", loader);
+        testReturnType(nodesClass, "getIdU32", "java.lang.Long", loader);
+        testReturnType(nodesClass, "getIdU64", "java.math.BigInteger", loader);
+        testReturnType(nodesClass, "getIdUnion", pkg + ".Nodes$IdUnion", loader);
 
         cleanUp(sourcesOutputDir, compiledOutputDir);
     }
@@ -256,25 +480,31 @@ public class CompilationTest {
 
         // Test if all sources are generated
         File fooParent = new File(sourcesOutputDir, NS_FOO);
-        File nodes = new File(fooParent, "Nodes.java");
-        File nodesBuilder = new File(fooParent, "NodesBuilder.java");
+        assertEquals(3, fooParent.listFiles().length);
         assertTrue(new File(fooParent, "FooData.java").exists());
-        assertTrue(nodes.exists());
-        assertTrue(nodesBuilder.exists());
+        assertTrue(new File(fooParent, "Nodes.java").exists());
+        assertTrue(new File(fooParent, "NodesBuilder.java").exists());
 
-        // Test if sources are compilable
-        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+        File barParent = new File(sourcesOutputDir, NS_BAR);
+        assertEquals(1, barParent.listFiles().length);
+        assertTrue(new File(barParent, "IdentityClass.java").exists());
 
-        List<File> filesList = getJavaFiles(sourcesOutputDir);
-        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
-        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
-        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
-        assertTrue(compiled);
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
 
         ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
-        Class<?> nodesClass = Class.forName("org.opendaylight.yang.gen.v1.urn.opendaylight.foo.rev131008.Nodes", true,
-                loader);
+        Class<?> nodesClass = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.Nodes", true, loader);
+        Class<?> identityClass = Class
+                .forName(BASE_PKG + ".urn.opendaylight.bar.rev131008.IdentityClass", true, loader);
+
+        // test identity
+        try {
+            identityClass.getConstructor();
+            Class<?> baseIdentity = Class.forName("org.opendaylight.yangtools.yang.binding.BaseIdentity", true, loader);
+            assertEquals(baseIdentity, identityClass.getSuperclass());
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("IdentityClass must have no-arg constructor");
+        }
 
         // Test annotation
         try {
@@ -290,6 +520,37 @@ public class CompilationTest {
         cleanUp(sourcesOutputDir, compiledOutputDir);
     }
 
+    @Test
+    public void testAugmentToUsesInAugment() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-uses-to-augment");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-uses-to-augment");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/augment-uses-to-augment");
+        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        // Test if all sources are generated
+        File fooParent = new File(sourcesOutputDir, NS_FOO);
+        assertEquals(4, fooParent.listFiles().length);
+        assertTrue(new File(fooParent, "IgpLinkAttributes.java").exists());
+        assertTrue(new File(fooParent, "Link1.java").exists());
+        assertTrue(new File(fooParent, "Link1Builder.java").exists());
+
+        File bazParent = new File(sourcesOutputDir, NS_BAZ);
+        assertEquals(4, bazParent.listFiles().length);
+        assertTrue(new File(bazParent, "IgpLinkAttributes1.java").exists());
+        assertTrue(new File(bazParent, "IgpLinkAttributes1Builder.java").exists());
+        assertTrue(new File(bazParent, "LinkAttributes.java").exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+    }
+
     @Test
     public void compilationTest() throws Exception {
         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "yang");
@@ -304,16 +565,41 @@ public class CompilationTest {
         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
         generator.generateToFile(sourcesOutputDir);
 
-        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
 
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    /**
+     * Test if source code is compilable.
+     *
+     * @param sourcesOutputDir
+     *            directory containing source files
+     * @param compiledOutputDir
+     *            compiler output directory
+     */
+    private void testCompilation(File sourcesOutputDir, File compiledOutputDir) {
         List<File> filesList = getJavaFiles(sourcesOutputDir);
         Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
         Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
         boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
         assertTrue(compiled);
+    }
 
-        cleanUp(sourcesOutputDir, compiledOutputDir);
+    private void testImplementIfc(Class<?> classToTest, String ifc, ClassLoader loader) throws ClassNotFoundException {
+        Class<?>[] interfaces = classToTest.getInterfaces();
+        List<Class<?>> ifcsList = Arrays.asList(interfaces);
+        Class<?> ifcClass = Class.forName(ifc, true, loader);
+        testImplementIfc(classToTest, ifcClass);
+    }
+
+    private void testImplementIfc(Class<?> classToTest, Class<?> ifcClass) throws ClassNotFoundException {
+        Class<?>[] interfaces = classToTest.getInterfaces();
+        List<Class<?>> ifcsList = Arrays.asList(interfaces);
+        if (!ifcsList.contains(ifcClass)) {
+            throw new AssertionError(classToTest + " should implement " + ifcClass);
+        }
     }
 
     private void testReturnType(Class<?> clazz, String methodName, Class<?> returnType) throws Exception {
@@ -326,7 +612,7 @@ public class CompilationTest {
         }
     }
 
-    private void testReturnType(ClassLoader loader, Class<?> clazz, String methodName, String returnTypeStr)
+    private void testReturnType(Class<?> clazz, String methodName, String returnTypeStr, ClassLoader loader)
             throws Exception {
         Class<?> returnType;
         try {
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/bar.yang
new file mode 100644 (file)
index 0000000..231bb42
--- /dev/null
@@ -0,0 +1,29 @@
+module bar {
+    yang-version 1;
+    namespace "urn:opendaylight:bar";
+    prefix "bar";
+
+    import foo { prefix fo; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    augment "/fo:update/fo:path-attributes" {
+        container mp-unreach-nlri {
+            container withdrawn-routes {
+                uses destination;
+            }
+        }
+    }
+
+    grouping destination {
+        choice destination-type {
+            case destination-ip {
+                leaf-list prefixes {
+                    type string;
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/baz.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/baz.yang
new file mode 100644 (file)
index 0000000..f361b34
--- /dev/null
@@ -0,0 +1,27 @@
+module baz {
+    yang-version 1;
+    namespace "urn:opendaylight:baz";
+    prefix "baz";
+
+    import foo { prefix fo; revision-date 2013-10-08; }
+    import bar { prefix br; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    augment "/fo:update/fo:path-attributes/br:mp-unreach-nlri/br:withdrawn-routes/br:destination-type" {
+        case destination-linkstate {
+            uses linkstate-destination;
+        }
+    }
+
+    grouping linkstate-destination {
+        leaf nlri-type {
+            type string;
+        }
+        leaf protocol-id {
+            type string;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/foo.yang
new file mode 100644 (file)
index 0000000..502b29b
--- /dev/null
@@ -0,0 +1,23 @@
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight:foo";
+    prefix "foo";
+
+    revision "2013-10-08" {
+    }
+
+    grouping path-attributes {
+        container origin {
+            leaf value {
+                type string;
+            }
+        }
+    }
+
+    notification update {
+        container path-attributes {
+            uses path-attributes;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/bar.yang
new file mode 100644 (file)
index 0000000..e1735b4
--- /dev/null
@@ -0,0 +1,22 @@
+module bar {
+    yang-version 1;
+    namespace "urn:opendaylight:bar";
+    prefix "bar";
+
+    revision "2013-10-08" {
+    }
+
+    grouping basic-explicit-route-subobjects {
+        choice subobject-type {
+            case ip-prefix {
+            }
+            case label {
+            }
+        }
+    }
+
+    grouping explicit-route-subobjects {
+        uses basic-explicit-route-subobjects;
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/foo.yang
new file mode 100644 (file)
index 0000000..e0d60ac
--- /dev/null
@@ -0,0 +1,51 @@
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight:foo";
+    prefix "foo";
+
+    import bar { prefix b; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    grouping object {
+        container nodes {
+        }
+    }
+
+    grouping open-object {
+        uses object {
+            augment "nodes" {
+                container links {
+                    leaf id {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    grouping explicit-route-object {
+        list subobjects {
+            leaf loose {
+                type boolean;
+            }
+            uses b:explicit-route-subobjects {
+                augment "subobject-type" {
+                    case path-key {
+                        container path-key {
+                            uses path-key-subobject;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    grouping path-key-subobject {
+        leaf path-key {
+            type string;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/test.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/test.yang
deleted file mode 100644 (file)
index a13c39e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-module test {
-    yang-version 1;
-    namespace "urn:opendaylight:test";
-    prefix "t";
-
-    revision "2013-10-08" {
-    }
-
-    grouping object {
-        container nodes {
-        }
-    }
-
-    grouping open-object {
-        uses object {
-            augment "nodes" {
-                container links {
-                    leaf id {
-                        type string;
-                    }
-                }
-            }
-        }
-    }
-
-}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/bar.yang
new file mode 100644 (file)
index 0000000..c4fd4ea
--- /dev/null
@@ -0,0 +1,28 @@
+module bar {
+    yang-version 1;
+    namespace "urn:opendaylight.bar";
+    prefix "bar";
+
+    revision "2013-10-08" {
+    }
+
+    container network-topology {
+        list topology {
+            key "topology-id";
+            leaf topology-id {
+                type int32;
+            }
+            list link {
+                key "link-id";
+                uses link-attributes;
+            }
+        }
+    }
+
+    grouping link-attributes {
+        leaf link-id {
+            type int8;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/baz.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/baz.yang
new file mode 100644 (file)
index 0000000..0cf07cb
--- /dev/null
@@ -0,0 +1,35 @@
+module baz {
+    yang-version 1;
+    namespace "urn:opendaylight.baz";
+    prefix "baz";
+
+    import foo {
+        prefix "fo";
+        revision-date 2013-10-08;
+    }
+
+    import bar {
+        prefix "br";
+        revision-date 2013-10-08;
+    }
+
+    revision "2013-10-08" {
+    }
+
+
+
+    augment "/br:network-topology/br:topology/br:link/fo:igp-link-attributes" {
+        uses link-attributes;
+    }
+
+    grouping link-attributes {
+        container ospf-link-attributes {
+            leaf multi-topology-id {
+                type uint8 {
+                    range "0..127";
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/foo.yang
new file mode 100644 (file)
index 0000000..e982011
--- /dev/null
@@ -0,0 +1,36 @@
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight.foo";
+    prefix "foo";
+
+    import bar {
+        prefix "br";
+        revision-date 2013-10-08;
+    }
+
+    revision "2013-10-08" {
+    }
+
+
+    augment "/br:network-topology/br:topology/br:link" {
+        uses igp-link-attributes;
+    }
+
+    grouping igp-link-attributes {
+        container igp-link-attributes {
+            leaf name {
+                type string;
+            }
+            leaf-list flag {
+                type string;
+            }
+            leaf metric {
+                type uint32 {
+                    range "0..16777215"  {
+                    }
+                }
+            }
+        }
+    }
+
+}
index a8abe38c70729cefc93c05a9e8c2e06e3b9c73a1..63486ce810c85f25c457a578e232335fef6c95b7 100644 (file)
@@ -11,6 +11,7 @@ import static org.opendaylight.yangtools.binding.generator.util.BindingGenerator
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -50,6 +51,7 @@ import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
 import org.opendaylight.yangtools.yang.model.util.StringType;
 import org.opendaylight.yangtools.yang.model.util.UnionType;
@@ -561,7 +563,8 @@ public final class TypeProviderImpl implements TypeProvider {
             final String moduleName = module.getName();
             final String basePackageName = moduleNamespaceToPackageName(module);
 
-            final Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();
+            final DataNodeIterator it = new DataNodeIterator(module);
+            final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
             final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
 
             final Map<String, Type> typeMap = new HashMap<>();
@@ -1108,7 +1111,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *         definitions are in list behind them).
      */
     private List<TypeDefinition<?>> sortTypeDefinitionAccordingDepth(
-            final Set<TypeDefinition<?>> unsortedTypeDefinitions) {
+            final Collection<TypeDefinition<?>> unsortedTypeDefinitions) {
         List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
 
         Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();