Fixed bug in augment parsing. 08/1708/3
authorMartin Vitez <mvitez@cisco.com>
Mon, 7 Oct 2013 07:22:09 +0000 (09:22 +0200)
committerMartin Vitez <mvitez@cisco.com>
Mon, 7 Oct 2013 14:15:57 +0000 (16:15 +0200)
Bug appears when two augments point to same target node which was added by uses statement.

Change-Id: I92a9d0586c9c94cd92a929a492272cdbd54be492
Signed-off-by: Martin Vitez <mvitez@cisco.com>
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.xtend
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.xtend
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/UsesNodeBuilderImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.xtend

index fbaddc6f7f06af23fbeeac94faa38ea82f9ea10b..0fefb1c0a4959df1b80489a52c94910a12a1c16d 100644 (file)
@@ -61,7 +61,10 @@ 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;\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
+
 public class BindingGeneratorImpl implements BindingGenerator {\r
     /**\r
      * Outter key represents the package name. Outter value represents map of\r
@@ -374,7 +377,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));\r
+            generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment, module));\r
         }\r
         return generatedTypes;\r
     }\r
@@ -818,7 +821,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val moduleName = parseToClassName(module.name) + postfix;\r
 \r
         return new GeneratedTypeBuilderImpl(packageName, moduleName);\r
-\r
     }\r
 \r
     /**\r
@@ -843,7 +845,7 @@ 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) {\r
+    private def List<Type> augmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module) {\r
         checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");\r
         checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");\r
         checkState(augSchema.targetPath !== null,\r
@@ -853,7 +855,11 @@ public class BindingGeneratorImpl implements BindingGenerator {
         // EVERY augmented interface will extends Augmentation<T> interface\r
         // and DataObject interface!!!\r
         val targetPath = augSchema.targetPath;\r
-        val targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);\r
+        var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);\r
+        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
@@ -881,6 +887,44 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return genTypes;\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
+\r
+        if (path.isEmpty()) {\r
+            parent = module;\r
+        } else {\r
+            parent = findNodeInSchemaContext(schemaContext, path) as DataNodeContainer;\r
+        }\r
+\r
+        val Set<UsesNode> usesNodes = parent.getUses();\r
+        if (usesNodes == null || usesNodes.isEmpty()) {\r
+            return targetSchemaNode;\r
+        }\r
+        val Set<SchemaPath> groupingPaths = new HashSet<SchemaPath>();\r
+        for (uses : usesNodes) {\r
+            groupingPaths.add(uses.getGroupingPath());\r
+        }\r
+        val Set<GroupingDefinition> groupings = new HashSet<GroupingDefinition>();\r
+        for (gp : groupingPaths) {\r
+            groupings.add(findGrouping(schemaContext, module, gp.getPath()));\r
+        }\r
+\r
+        var DataSchemaNode result = findNodeInGroupings(groupings, targetSchemaNode.getQName().localName);\r
+        return result;\r
+    }\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
+            }\r
+        }\r
+        return null;\r
+    }\r
+\r
     /**\r
      * Returns a generated type builder for an augmentation.\r
      *\r
index 238b314f527483a4f4a61bc27e5a7c23801efae8..15734fb3d71589e01531b87ce7265421950fdb27 100644 (file)
@@ -28,6 +28,8 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
 import java.util.Date
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+import java.util.Set
 
 /**
  * The Schema Context Util contains support methods for searching through Schema Context modules for specified schema
@@ -302,13 +304,41 @@ public  class SchemaContextUtil {
     }
     
     
-    private static def SchemaNode findNodeInSchemaContext(SchemaContext context, List<QName> path) {
+    public static def SchemaNode findNodeInSchemaContext(SchemaContext context, List<QName> path) {
         val current = path.get(0);
         val module = context.findModuleByNamespaceAndRevision(current.namespace,current.revision);
         if(module === null) return null;
         return findNodeInModule(module,path);
     }
-    
+
+    public static def GroupingDefinition findGrouping(SchemaContext context, Module module, List<QName> path) {
+        var first = path.get(0);
+        var firstPrefix = first.getPrefix();
+        var Module m = context.findModuleByNamespace(first.namespace).iterator().next();
+        var DataNodeContainer currentParent = m;
+        for (qname : path) {
+            var boolean found = false;
+            var DataNodeContainer node = currentParent.getDataChildByName(qname.localName) as DataNodeContainer;
+            if (node == null) {
+                var Set<GroupingDefinition> groupings = currentParent.getGroupings();
+                for (gr : groupings) {
+                    if(gr.getQName().localName.equals(qname.localName)) {
+                        currentParent = gr;
+                        found = true;
+                    }
+                }
+            } else {
+                found = true;
+                currentParent = node;
+            }
+            if (!found) {
+                throw new IllegalArgumentException("Failed to find referenced grouping: " + path + "(" + qname.localName + ")");
+            }
+        }
+        
+        return currentParent as GroupingDefinition;
+    }
+
     private static def SchemaNode findNodeInModule(Module module, List<QName> path) {
         val current = path.get(0);
         var SchemaNode node = module.getDataChildByName(current);
index 4941e3f4cedc8557bbfb072b697ffdb87e3c68cd..625da75fda6ecd48a7e829752f3ad8c017752a14 100644 (file)
@@ -44,13 +44,28 @@ public final class UsesNodeBuilderImpl extends AbstractBuilder implements UsesNo
     private boolean addedByUses;
     private boolean augmenting;
     private AugmentationSchemaBuilder parentAugment;
-    private final Set<AugmentationSchemaBuilder> addedAugments = new HashSet<AugmentationSchemaBuilder>();
-    private final List<SchemaNodeBuilder> refineBuilders = new ArrayList<SchemaNodeBuilder>();
-    private final List<RefineHolder> refines = new ArrayList<RefineHolder>();
+    private final Set<AugmentationSchemaBuilder> addedAugments = new HashSet<>();
+    private final List<SchemaNodeBuilder> refineBuilders = new ArrayList<>();
+    private final List<RefineHolder> refines = new ArrayList<>();
 
+    /**
+     * Copies of target grouping child nodes.
+     */
     private final Set<DataSchemaNodeBuilder> targetChildren = new HashSet<>();
+
+    /**
+     * Copies of target grouping groupings.
+     */
     private final Set<GroupingBuilder> targetGroupings = new HashSet<>();
+
+    /**
+     * Copies of target grouping typedefs.
+     */
     private final Set<TypeDefinitionBuilder> targetTypedefs = new HashSet<>();
+
+    /**
+     * Copies of target grouping unknown nodes.
+     */
     private final List<UnknownSchemaNodeBuilder> targetUnknownNodes = new ArrayList<>();
 
     private final boolean isCopy;
@@ -90,14 +105,14 @@ public final class UsesNodeBuilderImpl extends AbstractBuilder implements UsesNo
             instance.setAddedByUses(addedByUses);
 
             // AUGMENTATIONS
-            final Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();
+            final Set<AugmentationSchema> augments = new HashSet<>();
             for (AugmentationSchemaBuilder builder : addedAugments) {
                 augments.add(builder.build());
             }
             instance.setAugmentations(augments);
 
             // REFINES
-            final Map<SchemaPath, SchemaNode> refineNodes = new HashMap<SchemaPath, SchemaNode>();
+            final Map<SchemaPath, SchemaNode> refineNodes = new HashMap<>();
             for (SchemaNodeBuilder refineBuilder : refineBuilders) {
                 SchemaNode refineNode = refineBuilder.build();
                 refineNodes.put(refineNode.getPath(), refineNode);
@@ -105,7 +120,7 @@ public final class UsesNodeBuilderImpl extends AbstractBuilder implements UsesNo
             instance.setRefines(refineNodes);
 
             // UNKNOWN NODES
-            List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+            List<UnknownSchemaNode> unknownNodes = new ArrayList<>();
             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
                 unknownNodes.add(b.build());
             }
index 3fb787fe6ac460644087a7631c9bec4026fcb26c..eff2d4f24816c1217d139cebcc5a9e5ec63f4af1 100644 (file)
@@ -348,7 +348,12 @@ public final class ParserUtils {
     private static def searchUses(DataNodeContainerBuilder dataNodeContainerParent, String name) {
         var currentName = name;
         for (unb : dataNodeContainerParent.usesNodes) {
-            val result = findNodeInUses(currentName, unb);
+            var result = searchInUsesTarget(currentName, unb);
+            if (result != null) {
+                return result;
+            }
+
+            result = findNodeInUses(currentName, unb);
             if (result != null) {
                 var copy = CopyUtils.copy(result, unb.getParent(), true);
                 unb.getTargetChildren().add(copy);
@@ -413,6 +418,14 @@ public final class ParserUtils {
             return true;
         }
 
+    private static def DataSchemaNodeBuilder searchInUsesTarget(String localName, UsesNodeBuilder uses) {
+        for(child : uses.targetChildren) {
+            if (child.getQName().getLocalName().equals(localName)) {
+                return child;
+            }
+        }
+    } 
+
         /**
      * Find node with given name in uses target.
      *
@@ -423,12 +436,6 @@ public final class ParserUtils {
      * @return node with given name if found, null otherwise
      */
     private static def DataSchemaNodeBuilder findNodeInUses(String localName, UsesNodeBuilder uses) {
-        for(child : uses.targetChildren) {
-            if (child.getQName().getLocalName().equals(localName)) {
-                return child;
-            }
-        }
-
         val target = uses.groupingBuilder;
         for (child : target.childNodeBuilders) {
             if (child.getQName().getLocalName().equals(localName)) {