Merge "Added generated code compilation test."
authorTony Tkacik <ttkacik@cisco.com>
Wed, 9 Oct 2013 11:13:47 +0000 (11:13 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 9 Oct 2013 11:13:47 +0000 (11:13 +0000)
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.xtend
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/GeneratorJavaFileTest.java
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/test.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/list-gen/test.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/GroupingDefinitionDependencySort.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/DataNodeIterator.java

index 2adf3914f9d50c2500ab8324e5667a2b14feb0e3..69c9e163aab1834540b77fc9adc9572793adccaf 100644 (file)
@@ -774,7 +774,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
         checkArgument(module !== null, "Module parameter can not be null");\r
         val List<Type> genTypes = new ArrayList();\r
         val basePackageName = moduleNamespaceToPackageName(module);\r
-        val Set<GroupingDefinition> groupings = module.groupings;\r
+        val it = new DataNodeIterator(module);\r
+        val List<GroupingDefinition> groupings = it.allGroupings();\r
         val List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort().sort(\r
             groupings);\r
 \r
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java
new file mode 100644 (file)
index 0000000..06d09b1
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+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 TEST_PATH = "target" + FS + "test";
+    private static final File TEST_DIR = new File(TEST_PATH);
+
+    private static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
+    private static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
+    private static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
+    private static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
+
+    private YangParserImpl parser;
+    private BindingGenerator bindingGenerator;
+
+    @BeforeClass
+    public static void createTestDirs() {
+        if (TEST_DIR.exists()) {
+            deleteTestDir(TEST_DIR);
+        }
+        assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
+        assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
+    }
+
+    @Before
+    public void init() {
+        parser = new YangParserImpl();
+        bindingGenerator = new BindingGeneratorImpl();
+    }
+
+    /**
+     * Method to clean resources. It is manually called at the end of each test
+     * instead of marking it with @After annotation to prevent removing
+     * generated code if test fails.
+     */
+    public void cleanUp(File... resourceDirs) {
+        for (File resourceDir : resourceDirs) {
+            if (resourceDir.exists()) {
+                deleteTestDir(resourceDir);
+            }
+        }
+    }
+
+    @Test
+    public void testListGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "list-gen");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "list-gen");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/list-gen");
+        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);
+
+        File parent = new File(sourcesOutputDir, "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1"
+                + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008");
+        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());
+
+        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);
+
+        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);
+
+        // test list key constructor arguments ordering
+        try {
+            linksKeyClass.getConstructor(Byte.class, String.class, Integer.class);
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("Parameters of list key constructor are not properly ordered");
+        }
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void testAugmentUnderUsesGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-under-uses");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-under-uses");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/augment-under-uses");
+        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);
+
+        File parent = new File(sourcesOutputDir + FS + "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS
+                + "v1" + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008");
+        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());
+
+        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);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void compilationTest() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "yang");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "yang");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/yang");
+        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);
+
+        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);
+    }
+
+    private List<File> getSourceFiles(String path) {
+        final String resPath = getClass().getResource(path).getPath();
+        final File sourcesDir = new File(resPath);
+        final List<File> sourceFiles = new ArrayList<>();
+        final File[] fileArray = sourcesDir.listFiles();
+        sourceFiles.addAll(Arrays.asList(fileArray));
+        return sourceFiles;
+    }
+
+    private static void deleteTestDir(File file) {
+        if (file.isDirectory()) {
+            for (File f : file.listFiles()) {
+                deleteTestDir(f);
+            }
+        }
+        if (!file.delete()) {
+            throw new RuntimeException("Failed to clean up after test");
+        }
+    }
+
+    /**
+     * Search recursively given directory for *.java files.
+     * 
+     * @param directory
+     *            directory to search
+     * @return List of java files found
+     */
+    private List<File> getJavaFiles(File directory) {
+        List<File> result = new ArrayList<File>();
+        for (File file : directory.listFiles()) {
+            if (file.isDirectory()) {
+                result.addAll(getJavaFiles(file));
+            } else {
+                String absPath = file.getAbsolutePath();
+                if (absPath.endsWith(".java")) {
+                    result.add(file);
+                }
+            }
+        }
+        return result;
+    }
+}
index 9eea68af90a8a47c03e44619a628bd006696b0d3..1b18fe95136128965c391b284ba8be38ab04bbde 100644 (file)
@@ -41,32 +41,6 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 public class GeneratorJavaFileTest {
     private static final String FS = File.separator;
     private static final String PATH = "target/test/test-dir";
-    private final File testDir = new File(PATH);
-
-    private static final String GENERATOR_OUTPUT_PATH = "target/test/src";
-    private static final File GENERATOR_OUTPUT = new File(GENERATOR_OUTPUT_PATH);
-    private static final String COMPILER_OUTPUT_PATH = "target/test/bin";
-    private static final File COMPILER_OUTPUT = new File(COMPILER_OUTPUT_PATH);
-
-    @Before
-    public void init() {
-        assertTrue(testDir.mkdirs());
-        assertTrue(COMPILER_OUTPUT.mkdirs());
-        assertTrue(GENERATOR_OUTPUT.mkdirs());
-    }
-
-    @After
-    public void cleanUp() {
-        if (testDir.exists()) {
-            deleteTestDir(testDir);
-        }
-        if (COMPILER_OUTPUT.exists()) {
-            deleteTestDir(COMPILER_OUTPUT);
-        }
-        if (GENERATOR_OUTPUT.exists()) {
-            deleteTestDir(GENERATOR_OUTPUT);
-        }
-    }
 
     @Test
     public void test() throws IOException {
@@ -94,73 +68,10 @@ public class GeneratorJavaFileTest {
         assertTrue(filesList.contains("Type4Builder.java"));
     }
 
-    @Test
-    public void compilationTest() throws Exception {
-        final YangParserImpl parser = new YangParserImpl();
-        final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
-
-        final String resPath = getClass().getResource("/yang").getPath();
-        final File sourcesDir = new File(resPath);
-        final List<File> sourceFiles = new ArrayList<File>();
-        final File[] fileArray = sourcesDir.listFiles();
-
-        for (int i = 0; i < fileArray.length; ++i) {
-            sourceFiles.add(fileArray[i]);
-        }
-
-        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(new File(GENERATOR_OUTPUT_PATH));
-
-        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
-
-        List<File> filesList = getJavaFiles(new File(GENERATOR_OUTPUT_PATH));
-        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
-        Iterable<String> options = Arrays.asList(new String[] { "-d", COMPILER_OUTPUT_PATH });
-        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
-        assertTrue(compiled);
-    }
-
     private GeneratedType createGeneratedType(String pkgName, String name) {
         GeneratedTypeBuilder builder = new GeneratedTypeBuilderImpl(pkgName, name);
         builder.addImplementsType(BindingTypes.DATA_OBJECT);
         return builder.toInstance();
     }
 
-    private void deleteTestDir(File file) {
-        if (file.isDirectory()) {
-            for (File f : file.listFiles()) {
-                deleteTestDir(f);
-            }
-        }
-        if (!file.delete()) {
-            throw new RuntimeException("Failed to clean up after test");
-        }
-    }
-
-    /**
-     * Search recursively given directory for *.java files.
-     *
-     * @param directory
-     *            directory to search
-     * @return List of java files found
-     */
-    private List<File> getJavaFiles(File directory) {
-        List<File> result = new ArrayList<File>();
-        for (File file : directory.listFiles()) {
-            if (file.isDirectory()) {
-                result.addAll(getJavaFiles(file));
-            } else {
-                String absPath = file.getAbsolutePath();
-                if (absPath.endsWith(".java")) {
-                    result.add(file);
-                }
-            }
-        }
-        return result;
-    }
 }
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
new file mode 100644 (file)
index 0000000..a13c39e
--- /dev/null
@@ -0,0 +1,26 @@
+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/list-gen/test.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/list-gen/test.yang
new file mode 100644 (file)
index 0000000..fed4743
--- /dev/null
@@ -0,0 +1,43 @@
+module test {
+    yang-version 1;
+    namespace "urn:opendaylight:test";
+    prefix "t";
+
+    revision "2013-10-08" {
+    }
+
+    grouping key-args {
+        leaf id {
+            type int8;
+        }
+        leaf name {
+            type string;
+        }
+        leaf size {
+            type int32;
+        }
+    }
+
+    list links {
+        uses key-args;
+        key "size name id";
+
+        anyxml text;
+        choice level;
+        container node;
+        grouping link-group {
+            leaf source {
+                type int8;
+            }
+        }
+        leaf links-id {
+            type int32;
+        }
+        list node-list {
+        }
+        typedef nodes-type {
+            type string;
+        }
+    }
+
+}
index 509b69867e2f91bcd3a2aa29d7e70f65cb283888..2936e31e269658f60751025d8c2eb69a2a625457 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.sal.binding.yang.types;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -31,22 +32,22 @@ public class GroupingDefinitionDependencySort {
     /**
      * Sorts set <code>groupingDefinitions</code> according to the mutual
      * dependencies.<br />
-     * 
+     *
      * Elements of <code>groupingDefinitions</code> are firstly transformed to
      * {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node
      * Node} interfaces and then are sorted by
      * {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort#sort(Set)
      * sort()} method of <code>TopologicalSort</code>.<br />
      * <br />
-     * 
-     * 
+     *
+     *
      * <i>Definition of dependency relation:<br />
      * The first <code>GroupingDefinition</code> object (in this context)
      * depends on second <code>GroupingDefinition</code> object if the first one
      * contains in its set of <code>UsesNode</code> (obtained through
      * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer#getUses()
      * getUses} method) reference to the second one.</i>
-     * 
+     *
      * @param groupingDefinitions
      *            set of grouping definition which should be sorted according to
      *            mutual dependencies
@@ -54,9 +55,9 @@ public class GroupingDefinitionDependencySort {
      *         dependencies
      * @throws IllegalArgumentException
      *             if <code>groupingDefinitions</code>
-     * 
+     *
      */
-    public List<GroupingDefinition> sort(final Set<GroupingDefinition> groupingDefinitions) {
+    public List<GroupingDefinition> sort(final Collection<GroupingDefinition> groupingDefinitions) {
         if (groupingDefinitions == null) {
             throw new IllegalArgumentException("Set of Type Definitions " + "cannot be NULL!");
         }
@@ -75,7 +76,7 @@ public class GroupingDefinitionDependencySort {
     /**
      * Wraps every grouping definition to node type and adds to every node
      * information about dependencies.
-     * 
+     *
      * The map with mapping from schema path (represents grouping definition) to
      * node is created. For every created node (next <i>nodeFrom</i>) is for its
      * wrapped grouping definition passed the set of its <i>uses nodes</i>
@@ -83,14 +84,14 @@ public class GroupingDefinitionDependencySort {
      * <i>nodeTo</i>). This dependency relationship between nodeFrom and all
      * found nodesTo is modeled with creating of one edge from nodeFrom to
      * nodeTo.
-     * 
-     * 
+     *
+     *
      * @param groupingDefinitions
      *            set of goruping definition which will be wrapped to nodes
-     * 
+     *
      * @return set of nodes where every one contains wrapped grouping definition
      */
-    private Set<Node> groupingDefinitionsToNodes(final Set<GroupingDefinition> groupingDefinitions) {
+    private Set<Node> groupingDefinitionsToNodes(final Collection<GroupingDefinition> groupingDefinitions) {
         final Map<SchemaPath, Node> nodeMap = Maps.newHashMap();
         final Set<Node> resultNodes = Sets.newHashSet();
 
@@ -125,7 +126,7 @@ public class GroupingDefinitionDependencySort {
      * <code>container</code>, from uses in groupings inside
      * <code>container</code> and from uses inside child nodes of the
      * <code>container</code>.
-     * 
+     *
      * @param container
      *            data node container which can contain some uses of grouping
      * @return set of uses nodes which were find in <code>container</code>.
index 6fb90d96cb3b1e60160447102706171105922b1f..518d6d8a894c502f8faaceda7e234a970bbe4de9 100644 (file)
@@ -12,7 +12,16 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
-import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 
 public class DataNodeIterator implements Iterator<DataSchemaNode> {
 
@@ -21,6 +30,7 @@ public class DataNodeIterator implements Iterator<DataSchemaNode> {
     private final List<ContainerSchemaNode> allContainers;
     private final List<ChoiceNode> allChoices;
     private final List<DataSchemaNode> allChilds;
+    private final List<GroupingDefinition> allGroupings;
 
     public DataNodeIterator(final DataNodeContainer container) {
         if (container == null) {
@@ -31,6 +41,7 @@ public class DataNodeIterator implements Iterator<DataSchemaNode> {
         this.allLists = new ArrayList<>();
         this.allChilds = new ArrayList<>();
         this.allChoices = new ArrayList<>();
+        this.allGroupings = new ArrayList<>();
 
         this.container = container;
         traverse(this.container);
@@ -48,6 +59,10 @@ public class DataNodeIterator implements Iterator<DataSchemaNode> {
         return allChoices;
     }
 
+    public List<GroupingDefinition> allGroupings() {
+        return allGroupings;
+    }
+
     private void traverse(final DataNodeContainer dataNode) {
         if (dataNode == null) {
             return;
@@ -114,6 +129,7 @@ public class DataNodeIterator implements Iterator<DataSchemaNode> {
         final Set<GroupingDefinition> groupings = dataNode.getGroupings();
         if (groupings != null) {
             for (GroupingDefinition grouping : groupings) {
+                allGroupings.add(grouping);
                 traverse(grouping);
             }
         }