Fixed bug in generating code for augments defined in uses. 47/1747/1
authorMartin Vitez <mvitez@cisco.com>
Tue, 8 Oct 2013 13:47:51 +0000 (15:47 +0200)
committerMartin Vitez <mvitez@cisco.com>
Tue, 8 Oct 2013 13:47:51 +0000 (15:47 +0200)
Fix for Bug 106.

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

index 742a19bbd6eabf227ce5f7300cfc3d8899ab5501..2adf3914f9d50c2500ab8324e5667a2b14feb0e3 100644 (file)
@@ -235,6 +235,58 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }\r
         return generatedTypes;\r
     }\r
+    \r
+    private def List<Type> dataNodeContainerToGenType(String basePackageName, DataNodeContainer node, Module module) {\r
+        if (node === null) {\r
+            return null;\r
+        }\r
+        if (!(node instanceof SchemaNode)) {\r
+            throw new IllegalArgumentException("node to generate must be instance of SchemaNode");\r
+        }\r
+        val List<Type> result = new ArrayList();\r
+\r
+        result.addAll(processUsesAugments(node, module));\r
+\r
+        val packageName = packageNameForGeneratedType(basePackageName, (node as SchemaNode).path);\r
+        val typeBuilder = addDefaultInterfaceDefinition(packageName, node as SchemaNode);\r
+        val schemaNodes = node.childNodes;\r
+        if (node instanceof ContainerSchemaNode) {\r
+            resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);\r
+            result.add(typeBuilder.toInstance());\r
+        } else if (node instanceof ListSchemaNode) {\r
+            val List<String> listKeys = listKeys(node as ListSchemaNode);\r
+            val genTOBuilder = resolveListKeyTOBuilder(packageName, node as ListSchemaNode);\r
+\r
+            if(genTOBuilder !== null) {\r
+                val identifierMarker = IDENTIFIER.parameterizedTypeFor(typeBuilder);\r
+                val identifiableMarker = IDENTIFIABLE.parameterizedTypeFor(genTOBuilder);\r
+                genTOBuilder.addImplementsType(identifierMarker);\r
+                typeBuilder.addImplementsType(identifiableMarker);\r
+            }\r
+            for (schemaNode : schemaNodes) {\r
+                if (!schemaNode.isAugmenting()) {\r
+                    addSchemaNodeToListBuilders(basePackageName, schemaNode, typeBuilder, genTOBuilder, listKeys);\r
+                }\r
+            }\r
+            result.addAll(typeBuildersToGenTypes(typeBuilder, genTOBuilder));\r
+        }\r
+        \r
+        return result;\r
+    }\r
+\r
+    private def List<Type> processUsesAugments(DataNodeContainer node, Module module) {\r
+        val List<Type> result = new ArrayList();\r
+        val basePackageName = moduleNamespaceToPackageName(module);\r
+\r
+        for (usesNode : node.uses) {\r
+            for (augment : usesNode.augmentations) {\r
+                result.addAll(augmentationToGenTypes(basePackageName, augment, module, true));\r
+                result.addAll(processUsesAugments(augment, module));\r
+            }\r
+        }\r
+\r
+        return result;\r
+    }\r
 \r
     /**\r
      * Converts all <b>containers</b> of the module to the list of\r
@@ -269,7 +321,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val basePackageName = moduleNamespaceToPackageName(module);\r
         for (container : schemaContainers) {\r
             if(!container.isAddedByUses()) {\r
-                generatedTypes.add(containerToGenType(basePackageName, container));\r
+                generatedTypes.addAll(dataNodeContainerToGenType(basePackageName, container, module));\r
             }\r
         }\r
         return generatedTypes;\r
@@ -308,7 +360,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         if(schemaLists !== null) {\r
             for (list : schemaLists) {\r
                 if(!list.isAddedByUses()) {\r
-                    generatedTypes.addAll(listToGenType(basePackageName, list));\r
+                    generatedTypes.addAll(dataNodeContainerToGenType(basePackageName, list, module));\r
                 }\r
             }\r
         }\r
@@ -331,7 +383,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             </ul>\r
      *\r
      */\r
-    private def List<GeneratedType> allChoicesToGenTypes(Module module) {\r
+    private def List<Type> allChoicesToGenTypes(Module module) {\r
         checkArgument(module !== null, "Module reference cannot be NULL.");\r
         checkArgument(module.name !== null, "Module name cannot be NULL.");\r
 \r
@@ -339,10 +391,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val choiceNodes = it.allChoices();\r
         val basePackageName = moduleNamespaceToPackageName(module);\r
 \r
-        val List<GeneratedType> generatedTypes = new ArrayList();\r
+        val List<Type> generatedTypes = new ArrayList();\r
         for (choice : choiceNodes) {\r
             if((choice !== null) && !choice.isAddedByUses()) {\r
-                generatedTypes.addAll(choiceToGeneratedType(basePackageName, choice));\r
+                generatedTypes.addAll(choiceToGeneratedType(basePackageName, choice, module));\r
             }\r
         }\r
         return generatedTypes;\r
@@ -377,7 +429,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));\r
+            generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment, module, false));\r
         }\r
         return generatedTypes;\r
     }\r
@@ -528,7 +580,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     if((nContainers !== null) && !nContainers.isEmpty()) {\r
                         for (container : nContainers) {\r
                             if(!container.isAddedByUses()) {\r
-                                genRPCTypes.add(containerToGenType(basePackageName, container));\r
+                                genRPCTypes.addAll(dataNodeContainerToGenType(basePackageName, container, module));\r
                             }\r
                         }\r
                     }\r
@@ -536,7 +588,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     if((nLists !== null) && !nLists.isEmpty()) {\r
                         for (list : nLists) {\r
                             if(!list.isAddedByUses()) {\r
-                                genRPCTypes.addAll(listToGenType(basePackageName, list));\r
+                                genRPCTypes.addAll(dataNodeContainerToGenType(basePackageName, list, module));\r
                             }\r
                         }\r
                     }\r
@@ -544,7 +596,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     if((nChoices !== null) && !nChoices.isEmpty()) {\r
                         for (choice : nChoices) {\r
                             if(!choice.isAddedByUses()) {\r
-                                genRPCTypes.addAll(choiceToGeneratedType(basePackageName, choice));\r
+                                genRPCTypes.addAll(choiceToGeneratedType(basePackageName, choice, module));\r
                             }\r
                         }\r
                     }\r
@@ -591,21 +643,25 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val basePackageName = moduleNamespaceToPackageName(module);\r
         val List<Type> generatedTypes = new ArrayList();\r
 \r
+        \r
+\r
         for (notification : notifications) {\r
             if(notification !== null) {\r
+                generatedTypes.addAll(processUsesAugments(notification, module));\r
+\r
                 val iter = new DataNodeIterator(notification);\r
 \r
                 // Containers\r
                 for (node : iter.allContainers()) {\r
                     if(!node.isAddedByUses()) {\r
-                        generatedTypes.add(containerToGenType(basePackageName, node));\r
+                        generatedTypes.addAll(dataNodeContainerToGenType(basePackageName, node, module));\r
                     }\r
                 }\r
 \r
                 // Lists\r
                 for (node : iter.allLists()) {\r
                     if(!node.isAddedByUses()) {\r
-                        generatedTypes.addAll(listToGenType(basePackageName, node));\r
+                        generatedTypes.addAll(dataNodeContainerToGenType(basePackageName, node, module));\r
                     }\r
                 }\r
                 val notificationInterface = addDefaultInterfaceDefinition(basePackageName, notification);\r
@@ -723,8 +779,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
             groupings);\r
 \r
         for (grouping : groupingsSortedByDependencies) {\r
-            val genType = groupingToGenType(basePackageName, grouping);\r
+            val genType = groupingToGenType(basePackageName, grouping, module);\r
             genTypes.add(genType);\r
+            genTypes.addAll(processUsesAugments(grouping, module));\r
             val schemaPath = grouping.path;\r
             allGroupings.put(schemaPath, genType);\r
         }\r
@@ -743,7 +800,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * @return GeneratedType which is generated from grouping (object of type\r
      *         <code>GroupingDefinition</code>)\r
      */\r
-    private def GeneratedType groupingToGenType(String basePackageName, GroupingDefinition grouping) {\r
+    private def GeneratedType groupingToGenType(String basePackageName, GroupingDefinition grouping, Module module) {\r
         if(grouping === null) {\r
             return null;\r
         }\r
@@ -753,6 +810,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         val typeBuilder = addDefaultInterfaceDefinition(packageName, grouping);\r
 \r
         resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);\r
+\r
         return typeBuilder.toInstance();\r
     }\r
 \r
@@ -853,12 +911,13 @@ 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) {\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
         // EVERY augmented interface will extends Augmentation<T> interface\r
         // and DataObject interface!!!\r
@@ -882,14 +941,19 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 targetType = new ReferencedTypeImpl(typePackage, typeName);\r
             }\r
             val augChildNodes = augSchema.childNodes;\r
+\r
             if(!(targetSchemaNode instanceof ChoiceNode)) {\r
-                val augTypeBuilder = addRawAugmentGenTypeDefinition(augmentPackageName, targetType, augSchema);\r
+                var packageName = augmentPackageName;\r
+                if (addedByUses) {\r
+                    packageName = packageNameForGeneratedType(augmentPackageName, augSchema.targetPath);\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));\r
+            genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes, module));\r
         }\r
                \r
         return genTypes;\r
@@ -952,32 +1016,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, Type targetTypeRef,\r
-        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
-        val Set<DataSchemaNode> augChildNodes = augSchema.childNodes;\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(augmentPackageName, augTypeBuilder, augChildNodes);\r
-        augmentBuilders.put(augTypeName, augTypeBuilder);\r
-        return augTypeBuilder;\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
 \r
     /**\r
      *\r
@@ -1008,7 +1071,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * @return list of <code>Type</code> which represents container, list and\r
      *         choice subnodes of augment\r
      */\r
-    private def List<Type> augmentationBodyToGenTypes(String augBasePackageName, Set<DataSchemaNode> augChildNodes) {\r
+    private def List<Type> augmentationBodyToGenTypes(String augBasePackageName, Set<DataSchemaNode> augChildNodes, Module module) {\r
         val List<Type> genTypes = new ArrayList();\r
         val List<DataNodeIterator> augSchemaIts = new ArrayList();\r
         for (childNode : augChildNodes) {\r
@@ -1016,16 +1079,16 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 augSchemaIts.add(new DataNodeIterator(childNode as DataNodeContainer));\r
 \r
                 if(childNode instanceof ContainerSchemaNode) {\r
-                    genTypes.add(containerToGenType(augBasePackageName, childNode as ContainerSchemaNode));\r
+                    genTypes.addAll(dataNodeContainerToGenType(augBasePackageName, childNode as ContainerSchemaNode, module));\r
                 } else if(childNode instanceof ListSchemaNode) {\r
-                    genTypes.addAll(listToGenType(augBasePackageName, childNode as ListSchemaNode));\r
+                    genTypes.addAll(dataNodeContainerToGenType(augBasePackageName, childNode as ListSchemaNode, module));\r
                 }\r
             } else if(childNode instanceof ChoiceNode) {\r
                 val choice = childNode as ChoiceNode;\r
                 for (caseNode : choice.cases) {\r
                     augSchemaIts.add(new DataNodeIterator(caseNode));\r
                 }\r
-                genTypes.addAll(choiceToGeneratedType(augBasePackageName, childNode as ChoiceNode));\r
+                genTypes.addAll(choiceToGeneratedType(augBasePackageName, childNode as ChoiceNode, module));\r
             }\r
         }\r
 \r
@@ -1036,17 +1099,17 @@ public class BindingGeneratorImpl implements BindingGenerator {
 \r
             if(augContainers !== null) {\r
                 for (container : augContainers) {\r
-                    genTypes.add(containerToGenType(augBasePackageName, container));\r
+                    genTypes.addAll(dataNodeContainerToGenType(augBasePackageName, container, module));\r
                 }\r
             }\r
             if(augLists !== null) {\r
                 for (list : augLists) {\r
-                    genTypes.addAll(listToGenType(augBasePackageName, list));\r
+                    genTypes.addAll(dataNodeContainerToGenType(augBasePackageName, list, module));\r
                 }\r
             }\r
             if(augChoices !== null) {\r
                 for (choice : augChoices) {\r
-                    genTypes.addAll(choiceToGeneratedType(augBasePackageName, choice));\r
+                    genTypes.addAll(choiceToGeneratedType(augBasePackageName, choice, module));\r
                 }\r
             }\r
         }\r
@@ -1073,32 +1136,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return genTypeName + index;\r
     }\r
 \r
-    /**\r
-     * Converts <code>containerNode</code> to generated type. Firstly the\r
-     * generated type builder is created. The subnodes of\r
-     * <code>containerNode</code> are added as methods and the instance of\r
-     * <code>GeneratedType</code> is returned.\r
-     *\r
-     * @param basePackageName\r
-     *            string contains the module package name\r
-     * @param containerNode\r
-     *            container schema node with the data about childs nodes and\r
-     *            schema paths\r
-     * @return generated type for <code>containerNode</code>\r
-     */\r
-    private def GeneratedType containerToGenType(String basePackageName, ContainerSchemaNode containerNode) {\r
-        if(containerNode === null) {\r
-            return null;\r
-        }\r
-\r
-        val packageName = packageNameForGeneratedType(basePackageName, containerNode.path);\r
-        val schemaNodes = containerNode.childNodes;\r
-        val typeBuilder = addDefaultInterfaceDefinition(packageName, containerNode);\r
-\r
-        resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);\r
-        return typeBuilder.toInstance();\r
-    }\r
-\r
     /**\r
      * Adds the methods to <code>typeBuilder</code> which represent subnodes of\r
      * node for which <code>typeBuilder</code> was created.\r
@@ -1268,11 +1305,11 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             </ul>\r
      *\r
      */\r
-    private def List<GeneratedType> choiceToGeneratedType(String basePackageName, ChoiceNode choiceNode) {\r
+    private def List<Type> choiceToGeneratedType(String basePackageName, ChoiceNode choiceNode, Module module) {\r
         checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");\r
         checkArgument(choiceNode !== null, "Choice Schema Node cannot be NULL.");\r
 \r
-        val List<GeneratedType> generatedTypes = new ArrayList();\r
+        val List<Type> generatedTypes = new ArrayList();\r
         val packageName = packageNameForGeneratedType(basePackageName, choiceNode.path);\r
         val choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);\r
 \r
@@ -1282,7 +1319,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         generatedTypes.add(choiceType);\r
         val Set<ChoiceCaseNode> caseNodes = choiceNode.cases;\r
         if((caseNodes !== null) && !caseNodes.isEmpty()) {\r
-            generatedTypes.addAll(generateTypesFromChoiceCases(basePackageName, choiceType, caseNodes));\r
+            generatedTypes.addAll(generateTypesFromChoiceCases(basePackageName, choiceType, caseNodes, module));\r
         }\r
         return generatedTypes;\r
     }\r
@@ -1313,13 +1350,13 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             </ul>\r
      *             *\r
      */\r
-    private def List<GeneratedType> generateTypesFromChoiceCases(String basePackageName, Type refChoiceType,\r
-        Set<ChoiceCaseNode> caseNodes) {\r
+    private def List<Type> generateTypesFromChoiceCases(String basePackageName, Type refChoiceType,\r
+        Set<ChoiceCaseNode> caseNodes, Module module) {\r
         checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");\r
         checkArgument(refChoiceType !== null, "Referenced Choice Type cannot be NULL.");\r
         checkArgument(caseNodes !== null, "Set of Choice Case Nodes cannot be NULL.");\r
 \r
-        val List<GeneratedType> generatedTypes = new ArrayList();\r
+        val List<Type> generatedTypes = new ArrayList();\r
         for (caseNode : caseNodes) {\r
             if(caseNode !== null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {\r
                 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);\r
@@ -1332,6 +1369,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 }\r
                 generatedTypes.add(caseTypeBuilder.toInstance());\r
             }\r
+            \r
+            generatedTypes.addAll(processUsesAugments(caseNode, module));\r
         }\r
 \r
         return generatedTypes;\r
@@ -1782,35 +1821,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return getMethod;\r
     }\r
 \r
-    private def listToGenType(String basePackageName, ListSchemaNode list) {\r
-        checkArgument(basePackageName !== null, "Package Name for Generated Type cannot be NULL.");\r
-        checkArgument(list !== null, "List Schema Node cannot be NULL.");\r
-\r
-        val packageName = packageNameForGeneratedType(basePackageName, list.path);\r
-\r
-        // val typeBuilder =\r
-        // resolveListTypeBuilder(packageName, list);\r
-        val typeBuilder = addDefaultInterfaceDefinition(packageName, list);\r
-\r
-        val List<String> listKeys = listKeys(list);\r
-        val genTOBuilder = resolveListKeyTOBuilder(packageName, list);\r
-\r
-        if(genTOBuilder !== null) {\r
-            val identifierMarker = IDENTIFIER.parameterizedTypeFor(typeBuilder);\r
-            val identifiableMarker = IDENTIFIABLE.parameterizedTypeFor(genTOBuilder);\r
-            genTOBuilder.addImplementsType(identifierMarker);\r
-            typeBuilder.addImplementsType(identifiableMarker);\r
-        }\r
-        val schemaNodes = list.childNodes;\r
-\r
-        for (schemaNode : schemaNodes) {\r
-            if(!schemaNode.isAugmenting()) {\r
-                addSchemaNodeToListBuilders(basePackageName, schemaNode, typeBuilder, genTOBuilder, listKeys);\r
-            }\r
-        }\r
-        return typeBuildersToGenTypes(typeBuilder, genTOBuilder);\r
-    }\r
-\r
     /**\r
      * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method\r
      * or to <code>genTOBuilder</code> as property.\r
index 15734fb3d71589e01531b87ce7265421950fdb27..6cb1135c6eb261c85eda22332d7b1d5a107eaf04 100644 (file)
@@ -347,9 +347,19 @@ public  class SchemaContextUtil {
         if (node != null) return findNodeInRpc(node as RpcDefinition,path.nextLevel)
         node = module.getNotificationByName(current);
         if (node != null) return findNodeInNotification(node as NotificationDefinition,path.nextLevel)
+        node = module.getGroupingByName(current);
+        if (node != null) return findNodeInGrouping(node as GroupingDefinition, path.nextLevel);
         return null
     }
-     
+
+    private static def SchemaNode findNodeInGrouping(GroupingDefinition grouping, List<QName> path) {
+        if (path.empty) return grouping;
+        val current = path.get(0);
+        val node = grouping.getDataChildByName(current);
+        if (node != null) return findNode(node, path.nextLevel);
+        return null;
+    }
+
     private static def SchemaNode findNodeInRpc(RpcDefinition rpc,List<QName> path) {
         if(path.empty) return rpc;
         val current = path.get(0);
@@ -431,6 +441,15 @@ public  class SchemaContextUtil {
         }
         return null;
     }
+    
+    public static def GroupingDefinition getGroupingByName(Module module, QName name) {
+        for (grouping : module.groupings) {
+            if (grouping.QName.equals(name)) {
+                return grouping;
+            }
+        }
+        return null;
+    }
 
     /**
      * Transforms string representation of XPath to Queue of QNames. The XPath is split by "/" and for each part of