Added support for parsing submodules & added dependency utility parser
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / util / ParserUtils.xtend
index 4bd5a247840c4034a5909a58531229e7f1b2b5a2..861778590e816e05ebc655caf393afcd34f1b33e 100644 (file)
@@ -12,16 +12,15 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
@@ -31,17 +30,36 @@ import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder.ChoiceNodeImpl;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder.ChoiceCaseNodeImpl;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder.ContainerSchemaNodeImpl;
-import org.opendaylight.yangtools.yang.parser.builder.impl.IdentityrefTypeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ListSchemaNodeBuilder.ListSchemaNodeImpl;
+import org.opendaylight.yangtools.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.NotificationBuilder.NotificationDefinitionImpl;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
 import org.opendaylight.yangtools.yang.parser.builder.impl.RpcDefinitionBuilder
-
+import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import java.util.HashSet
+import java.net.URI
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
+import org.opendaylight.yangtools.yang.parser.builder.impl.AnyXmlBuilder
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+import org.opendaylight.yangtools.yang.parser.builder.impl.ListSchemaNodeBuilder
+import org.opendaylight.yangtools.yang.parser.builder.impl.LeafListSchemaNodeBuilder
+import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder
+import org.opendaylight.yangtools.yang.parser.builder.impl.GroupingBuilderImpl
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.parser.builder.impl.TypeDefinitionBuilderImpl
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder
+import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilder
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import com.google.common.base.Preconditions
 
 public final class ParserUtils {
 
@@ -53,7 +71,7 @@ public final class ParserUtils {
      *
      * @param schemaPath
      * @param qname
-     * @return
+     * @return new SchemaPath from given path and qname
      */
     public static def SchemaPath createSchemaPath(SchemaPath schemaPath, QName... qname) {
         val path = new ArrayList<QName>(schemaPath.getPath());
@@ -93,12 +111,14 @@ public final class ParserUtils {
      *            current line in yang model
      * @return module builder if found, null otherwise
      */
-    public static def ModuleBuilder findDependentModuleBuilder(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+    public static def ModuleBuilder findModuleFromBuilders(Map<String, TreeMap<Date, ModuleBuilder>> modules,
         ModuleBuilder module, String prefix, int line) {
         var ModuleBuilder dependentModule = null;
         var Date dependentModuleRevision = null;
 
-        if (prefix.equals(module.getPrefix())) {
+        if(prefix == null) {
+            dependentModule = module;
+        } else if (prefix.equals(module.getPrefix())) {
             dependentModule = module;
         } else {
             val ModuleImport dependentModuleImport = getModuleImport(module, prefix);
@@ -136,6 +156,10 @@ public final class ParserUtils {
      */
     public static def Module findModuleFromContext(SchemaContext context, ModuleBuilder currentModule,
         String prefix, int line) {
+        if (context === null) {
+            throw new YangParseException(currentModule.getName(), line,
+                "Cannot find module with prefix '" + prefix + "'.");
+        }
         val modulesByRevision = new TreeMap<Date, Module>();
 
         val dependentModuleImport = ParserUtils.getModuleImport(currentModule, prefix);
@@ -190,6 +214,9 @@ public final class ParserUtils {
         return new SchemaPath(path, absolute);
     }
 
+    public static def dispatch fillAugmentTarget(AugmentationSchemaBuilder augment, Builder target) {
+    }
+
     /**
      * Add all augment's child nodes to given target.
      *
@@ -198,12 +225,13 @@ public final class ParserUtils {
      * @param target
      *            augmentation target node
      */
-    public static def void fillAugmentTarget(AugmentationSchemaBuilder augment, DataNodeContainerBuilder target) {
+    public static def dispatch fillAugmentTarget(AugmentationSchemaBuilder augment, DataNodeContainerBuilder target) {
         for (DataSchemaNodeBuilder child : augment.getChildNodeBuilders()) {
             val childCopy = CopyUtils.copy(child, target, false);
-            childCopy.setAugmenting(true);
-            correctNodePath(child, target.getPath());
-            correctNodePath(childCopy, target.getPath());
+            if (augment.parent instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy);
             try {
                 target.addChildNode(childCopy);
             } catch (YangParseException e) {
@@ -212,11 +240,6 @@ public final class ParserUtils {
                 throw new YangParseException(augment.getModuleName(), augment.getLine(),
                     "Failed to perform augmentation: " + e.getMessage());
             }
-
-        }
-        for (UsesNodeBuilder usesNode : augment.getUsesNodes()) {
-            val copy = CopyUtils.copyUses(usesNode, target);
-            target.addUsesNode(copy);
         }
     }
 
@@ -228,119 +251,122 @@ public final class ParserUtils {
      * @param target
      *            augmentation target choice node
      */
-    public static def void fillAugmentTarget(AugmentationSchemaBuilder augment, ChoiceBuilder target) {
+    public static def dispatch fillAugmentTarget(AugmentationSchemaBuilder augment, ChoiceBuilder target) {
         for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
             val childCopy = CopyUtils.copy(builder, target, false);
-            childCopy.setAugmenting(true);
-            correctNodePath(builder, target.getPath());
-            correctNodePath(childCopy, target.getPath());
+            if (augment.parent instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy)
             target.addCase(childCopy);
         }
-        for (UsesNodeBuilder usesNode : augment.getUsesNodes()) {
+        for (UsesNodeBuilder usesNode : augment.getUsesNodeBuilders()) {
             if (usesNode !== null) {
                 throw new YangParseException(augment.getModuleName(), augment.getLine(),
-                    "Error in augment parsing: cannot augment uses to choice");
+                    "Error in augment parsing: cannot augment choice with nodes from grouping");
             }
         }
     }
 
     /**
-     * Create new schema path of node based on parent node schema path.
-     *
-     * @param node
-     *            node to correct
-     * @param parentSchemaPath
-     *            schema path of node parent
+     * Set augmenting flag to true for node and all its child nodes.
      */
-    static def void correctNodePath(SchemaNodeBuilder node, SchemaPath parentSchemaPath) {
-
-        // set correct path
-        val targetNodePath = new ArrayList<QName>(parentSchemaPath.getPath());
-        targetNodePath.add(node.getQName());
-        node.setPath(new SchemaPath(targetNodePath, true));
-
-        // set correct path for all child nodes
-        if (node instanceof DataNodeContainerBuilder) {
-            val dataNodeContainer = node as DataNodeContainerBuilder;
-            for (DataSchemaNodeBuilder child : dataNodeContainer.getChildNodeBuilders()) {
-                correctNodePath(child, node.getPath());
+    private static def void setNodeAugmenting(DataSchemaNodeBuilder child) {
+        child.setAugmenting(true);
+        if (child instanceof DataNodeContainerBuilder) {
+            val DataNodeContainerBuilder dataNodeChild = child as DataNodeContainerBuilder;
+            for (inner : dataNodeChild.getChildNodeBuilders()) {
+                setNodeAugmenting(inner);
+            }
+        } else if (child instanceof ChoiceBuilder) {
+            val ChoiceBuilder choiceChild = child as ChoiceBuilder;
+            for (inner : choiceChild.cases) {
+                setNodeAugmenting(inner);
             }
         }
+    }
 
-        // set correct path for all cases
-        if (node instanceof ChoiceBuilder) {
-            val choiceBuilder = node as ChoiceBuilder;
-            for (ChoiceCaseBuilder choiceCaseBuilder : choiceBuilder.getCases()) {
-                correctNodePath(choiceCaseBuilder, node.getPath());
+    /**
+     * Set addedByUses flag to true for node and all its child nodes. 
+     */
+    public static def void setNodeAddedByUses(GroupingMember child) {
+        child.setAddedByUses(true);
+        if (child instanceof DataNodeContainerBuilder) {
+            val DataNodeContainerBuilder dataNodeChild = child as DataNodeContainerBuilder;
+            for (inner : dataNodeChild.getChildNodeBuilders()) {
+                setNodeAddedByUses(inner);
+            }
+        } else if (child instanceof ChoiceBuilder) {
+            val ChoiceBuilder choiceChild = child as ChoiceBuilder;
+            for (inner : choiceChild.cases) {
+                setNodeAddedByUses(inner);
             }
         }
     }
 
+    public static def DataSchemaNodeBuilder findSchemaNode(List<QName> path, SchemaNodeBuilder parentNode) {
+        var DataSchemaNodeBuilder node
+        var SchemaNodeBuilder parent = parentNode
+        var int i = 0;
+        while (i < path.size) {
+            val String name = path.get(i).localName
+            if (parent instanceof DataNodeContainerBuilder) {
+                node = (parent as DataNodeContainerBuilder).getDataChildByName(name)
+            } else if (parent instanceof ChoiceBuilder) {
+                node = (parent as ChoiceBuilder).getCaseNodeByName(name)
+            } else if (parent instanceof RpcDefinitionBuilder) {
+                if ("input".equals(name)) {
+                    node = (parent as RpcDefinitionBuilder).input
+                } else if ("output".equals(name)) {
+                    node = (parent as RpcDefinitionBuilder).output
+                } else {
+                    return null
+                }
+            } else {
+                return null
+            }
 
-
-    public static dispatch def SchemaNodeBuilder findNode(ModuleBuilder parent,List<QName> path) {
-        var node = _findNode(parent as DataNodeContainerBuilder,path);
-        if(node !== null) return node;
-        
-        val current = path.get(0);
-        node = parent.getRpc(current.localName);
-        if(node !== null) return _findNode(node as RpcDefinitionBuilder,path.nextLevel);
-        node = parent.getNotification(current.localName);
-        return node;
-    }
-    
-    public static dispatch def SchemaNodeBuilder findNode(DataNodeContainerBuilder parent,List<QName> path) {
-        if(path.empty) return parent as SchemaNodeBuilder;
-        
-        var current = path.get(0);
-        var node = parent.getDataChildByName(current.localName)
-        if(node !== null) return findNode(node,path.nextLevel);
-        for (UsesNodeBuilder unb : parent.usesNodes) {
-            node  = findNodeInUses(current.localName, unb);
-            if (node !== null) {
-                 return findNode(node,path.nextLevel);
+            if (i < path.size - 1) {
+                parent = node
             }
+            i = i + 1
         }
+
+        return node
     }
-    
-    public static dispatch def SchemaNodeBuilder findNode(RpcDefinitionBuilder parent,List<QName> path) {
-        val current = path.get(0);
-        switch(current.localName) {
-            case "input": return findNode(parent.input,path.nextLevel)
-            case "output": return findNode(parent.output,path.nextLevel)
-        }
-        return null;
-    }
-    
-    public static dispatch def SchemaNodeBuilder findNode(ChoiceBuilder parent,List<QName> path) {
-        if(path.empty) return parent as SchemaNodeBuilder;
-        var current = path.get(0);
-        val node = parent.getCaseNodeByName(current.localName);
-        if(node === null) return null;
-        return findNode(node,path.nextLevel);
-    }
-    
-    public static def getRpc(ModuleBuilder module,String name) {
-        for(rpc : module.rpcs) {
-            if(name == rpc.QName.localName) {
-                return rpc;
+
+    public static def SchemaNodeBuilder findSchemaNodeInModule(List<QName> pathToNode, ModuleBuilder module) {
+        val List<QName> path = new ArrayList(pathToNode)
+        val QName first = path.remove(0)
+
+        var SchemaNodeBuilder node = module.getDataChildByName(first.localName)
+        if (node == null) {
+            val notifications = module.getAddedNotifications
+            for (notification : notifications) {
+                if (notification.QName.localName.equals(first.localName)) {
+                    node = notification
+                }
             }
         }
-        return null;
-    }
-    
-    public static def getNotification(ModuleBuilder module,String name) {
-        for(notification : module.notifications) {
-            if(name == notification.QName.localName) {
-                return notification;
+        if (node == null) {
+            val rpcs = module.getAddedRpcs
+            for (rpc : rpcs) {
+                if (rpc.QName.localName.equals(first.localName)) {
+                    node = rpc
+                }
             }
         }
+        if (node == null) {
+            return null;
+        }
+
+        if (!path.empty) {
+            node = findSchemaNode(path, node)
+        }
+
+        return node
     }
-    
-    private static def nextLevel(List<QName> path){
-        return path.subList(1,path.size)
-    }
-    
+
     /**
      * Find augment target node and perform augmentation.
      *
@@ -351,203 +377,183 @@ public final class ParserUtils {
      *            path to augment target
      * @return true if augmentation process succeed, false otherwise
      */
-    public static def boolean processAugmentation(AugmentationSchemaBuilder augment, Builder firstNodeParent,
-        List<QName> path) {
-
-            // traverse augment target path and try to reach target node
-            val currentParent = findNode(firstNodeParent,path);
-            if (currentParent === null) return false;
-            
-            if ((currentParent instanceof DataNodeContainerBuilder)) {
-                fillAugmentTarget(augment, currentParent as DataNodeContainerBuilder);
-            } else if (currentParent instanceof ChoiceBuilder) {
-                fillAugmentTarget(augment, currentParent as ChoiceBuilder);
-            } else {
-                throw new YangParseException(augment.getModuleName(), augment.getLine(),
-                    "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
-            }
-            (currentParent as AugmentationTargetBuilder).addAugmentation(augment);
-            val oldPath = (currentParent as SchemaNodeBuilder).getPath();
-            augment.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-            augment.setResolved(true);
-            return true;
-        }
-
-        /**
-     * Find node with given name in uses target.
-     *
-     * @param localName
-     *            name of node to find
-     * @param uses
-     *            uses node which target grouping should be searched
-     * @return node with given name if found, null otherwise
-     */
-        private static def DataSchemaNodeBuilder findNodeInUses(String localName, UsesNodeBuilder uses) {
-            val target = uses.getGroupingBuilder();
-            for (DataSchemaNodeBuilder child : target.getChildNodeBuilders()) {
-                if (child.getQName().getLocalName().equals(localName)) {
-                    return child;
-                }
-            }
-            for (UsesNodeBuilder usesNode : target.getUsesNodes()) {
-                val result = findNodeInUses(localName, usesNode);
-                if (result !== null) {
-                    return result;
-                }
-            }
-            return null;
+    public static def boolean processAugmentation(AugmentationSchemaBuilder augment, ModuleBuilder firstNodeParent) {
+        val path = augment.targetPath.path
+        var Builder targetNode = findSchemaNodeInModule(path, firstNodeParent as ModuleBuilder)
+        if(targetNode === null) return false;
+
+        if ((targetNode instanceof DataNodeContainerBuilder)) {
+            val targetDataNodeContainer = targetNode as DataNodeContainerBuilder;
+            augment.setTargetNodeSchemaPath(targetDataNodeContainer.getPath());
+        } else if (targetNode instanceof ChoiceBuilder) {
+            val targetChoiceBuilder = targetNode as ChoiceBuilder;
+            augment.setTargetNodeSchemaPath(targetChoiceBuilder.getPath());
+        } else {
+            throw new YangParseException(augment.getModuleName(), augment.getLine(),
+                "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
         }
+        fillAugmentTarget(augment, targetNode);
+        (targetNode as AugmentationTargetBuilder).addAugmentation(augment);
+        augment.setResolved(true);
+        return true;
+    }
 
-        /**
-     * Find augment target node in given context and perform augmentation.
-     *
-     * @param augment
-     * @param path
-     *            path to augment target
-     * @param module
-     *            current module
-     * @param prefix
-     *            current prefix of target module
-     * @param context
-     *            SchemaContext containing already resolved modules
-     * @return true if augment process succeed, false otherwise
-     */
-        public static def boolean processAugmentationOnContext(AugmentationSchemaBuilder augment, List<QName> path,
-            ModuleBuilder module, String prefix, SchemaContext context) {
-            val int line = augment.getLine();
-            val Module dependentModule = findModuleFromContext(context, module, prefix, line);
-            if (dependentModule === null) {
-                throw new YangParseException(module.getName(), line,
-                    "Error in augment parsing: failed to find module with prefix " + prefix + ".");
-            }
-
-            var currentName = path.get(0).getLocalName();
-            var SchemaNode currentParent = dependentModule.getDataChildByName(currentName);
-            if (currentParent === null) {
-                val notifications = dependentModule.getNotifications();
-                for (NotificationDefinition ntf : notifications) {
-                    if (ntf.getQName().getLocalName().equals(currentName)) {
-                        currentParent = ntf;
-                    }
-                }
-            }
-            if (currentParent === null) {
+    public static def IdentitySchemaNodeBuilder findBaseIdentity(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+        ModuleBuilder module, String baseString, int line) {
+        var IdentitySchemaNodeBuilder result = null;
+        if (baseString.contains(":")) {
+            val String[] splittedBase = baseString.split(":");
+            if (splittedBase.length > 2) {
                 throw new YangParseException(module.getName(), line,
-                    "Error in augment parsing: failed to find node " + currentName + ".");
+                    "Failed to parse identityref base: " + baseString);
             }
-
-            for (qname : path.nextLevel) {
-                currentName = qname.getLocalName();
-                if (currentParent instanceof DataNodeContainer) {
-                    currentParent = (currentParent as DataNodeContainer).getDataChildByName(currentName);
-                } else if (currentParent instanceof ChoiceNode) {
-                    currentParent = (currentParent as ChoiceNode).getCaseNodeByName(currentName);
-                } else {
-                    throw new YangParseException(augment.getModuleName(), line,
-                        "Error in augment parsing: failed to find node " + currentName);
-                }
-
-                // if node in path not found, return false
-                if (currentParent === null) {
-                    throw new YangParseException(module.getName(), line,
-                        "Error in augment parsing: failed to find node " + currentName + ".");
-                }
+            val prefix = splittedBase.get(0);
+            val name = splittedBase.get(1);
+            val dependentModule = findModuleFromBuilders(modules, module, prefix, line);
+            if (dependentModule !== null) {
+                result = findIdentity(dependentModule.getAddedIdentities, name);
             }
+        } else {
+            result = findIdentity(module.getAddedIdentities, baseString);
+        }
+        return result;
+    }
 
-            val oldPath = currentParent.path;
+    public static def IdentitySchemaNode findBaseIdentityFromContext(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+        ModuleBuilder module, String baseString, int line, SchemaContext context) {
+        var IdentitySchemaNode result = null;
 
-            if (!(currentParent instanceof AugmentationTarget)) {
-                throw new YangParseException(module.getName(), line,
-                    "Target of type " + currentParent.class + " cannot be augmented.");
-            }
+        val String[] splittedBase = baseString.split(":");
+        if (splittedBase.length > 2) {
+            throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + baseString);
+        }
+        val prefix = splittedBase.get(0);
+        val name = splittedBase.get(1);
+        val dependentModule = findModuleFromContext(context, module, prefix, line);
+        result = findIdentityNode(dependentModule.identities, name);
 
-            switch (currentParent) {
-                case (currentParent instanceof ContainerSchemaNodeImpl): {
+        if (result == null) {
+            throw new YangParseException(module.name, line, "Failed to find base identity");
+        }
+        return result;
+    }
 
-                    // includes container, input and output statement
-                    val c = currentParent as ContainerSchemaNodeImpl;
-                    val cb = c.toBuilder();
-                    fillAugmentTarget(augment, cb);
-                    (cb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    cb.rebuild();
-                }
-                case (currentParent instanceof ListSchemaNodeImpl): {
-                    val l = currentParent as ListSchemaNodeImpl;
-                    val lb = l.toBuilder();
-                    fillAugmentTarget(augment, lb);
-                    (lb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    lb.rebuild();
-                    augment.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
-                case (currentParent instanceof ChoiceNodeImpl): {
-                    val ch = currentParent as ChoiceNodeImpl;
-                    val chb = ch.toBuilder();
-                    fillAugmentTarget(augment, chb);
-                    (chb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    chb.rebuild();
-                    augment.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
-                case (currentParent instanceof ChoiceCaseNodeImpl): {
-                    val chc = currentParent as ChoiceCaseNodeImpl;
-                    val chcb = chc.toBuilder();
-                    fillAugmentTarget(augment, chcb);
-                    (chcb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    chcb.rebuild();
-                    augment.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
-                case (currentParent instanceof NotificationDefinitionImpl): {
-                    val nd = currentParent as NotificationDefinitionImpl;
-                    val nb = nd.toBuilder();
-                    fillAugmentTarget(augment, nb);
-                    (nb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    nb.rebuild();
-                    augment.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
+    private static def IdentitySchemaNodeBuilder findIdentity(Set<IdentitySchemaNodeBuilder> identities, String name) {
+        for (identity : identities) {
+            if (identity.QName.localName.equals(name)) {
+                return identity;
             }
-            augment.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-            augment.setResolved(true);
-            return true;
         }
+        return null;
+    }
 
-        public static def QName findFullQName(Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            ModuleBuilder module, IdentityrefTypeBuilder idref) {
-            var QName result = null;
-            val String baseString = idref.getBaseString();
-            if (baseString.contains(":")) {
-                val String[] splittedBase = baseString.split(":");
-                if (splittedBase.length > 2) {
-                    throw new YangParseException(module.getName(), idref.getLine(),
-                        "Failed to parse identityref base: " + baseString);
-                }
-                val prefix = splittedBase.get(0);
-                val name = splittedBase.get(1);
-                val dependentModule = findDependentModuleBuilder(modules, module, prefix, idref.getLine());
-                result = new QName(dependentModule.getNamespace(), dependentModule.getRevision(), prefix, name);
-            } else {
-                result = new QName(module.getNamespace(), module.getRevision(), module.getPrefix(), baseString);
+    private static def IdentitySchemaNode findIdentityNode(Set<IdentitySchemaNode> identities, String name) {
+        for (identity : identities) {
+            if (identity.QName.localName.equals(name)) {
+                return identity;
             }
-            return result;
         }
+        return null;
+    }
 
-        /**
+    /**
      * Get module in which this node is defined.
      *
      * @param node
      * @return builder of module where this node is defined
      */
-        public static def ModuleBuilder getParentModule(Builder node) {
-            if (node instanceof ModuleBuilder) {
-                return node as ModuleBuilder;
-            }
-            var parent = node.getParent();
-            while (!(parent instanceof ModuleBuilder)) {
-                parent = parent.getParent();
-            }
-            return parent as ModuleBuilder;
+    public static def ModuleBuilder getParentModule(Builder node) {
+        if (node instanceof ModuleBuilder) {
+            return node as ModuleBuilder;
+        }
+        var parent = node.getParent();
+        while (!(parent instanceof ModuleBuilder)) {
+            parent = parent.getParent();
+        }
+        Preconditions.checkState(parent instanceof ModuleBuilder)
+        var parentModule = parent as ModuleBuilder
+        if(parentModule.submodule) {
+           parentModule = parentModule.parent; 
+        }
+        return parentModule;
+    }
+
+    public static def Set<DataSchemaNodeBuilder> wrapChildNodes(String moduleName, int line, Set<DataSchemaNode> nodes,
+        SchemaPath parentPath, URI ns, Date rev, String pref) {
+        val Set<DataSchemaNodeBuilder> result = new HashSet()
+
+        for (DataSchemaNode node : nodes) {
+            val qname = new QName(ns, rev, pref, node.QName.localName)
+            val DataSchemaNodeBuilder wrapped = wrapChildNode(moduleName, line, node, parentPath, qname)
+            result.add(wrapped)
         }
+        return result
     }
-    
\ No newline at end of file
+
+    public static def DataSchemaNodeBuilder wrapChildNode(String moduleName, int line, DataSchemaNode node,
+        SchemaPath parentPath, QName qname) {
+        val List<QName> path = new ArrayList(parentPath.getPath())
+        path.add(qname)
+        val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
+
+        if (node instanceof AnyXmlSchemaNode) {
+            return new AnyXmlBuilder(moduleName, line, qname, schemaPath, (node as AnyXmlSchemaNode));
+        } else if (node instanceof ChoiceNode) {
+            return new ChoiceBuilder(moduleName, line, qname, schemaPath, (node as ChoiceNode));
+        } else if (node instanceof ContainerSchemaNode) {
+            return new ContainerSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as ContainerSchemaNode));
+        } else if (node instanceof LeafSchemaNode) {
+            return new LeafSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as LeafSchemaNode));
+        } else if (node instanceof LeafListSchemaNode) {
+            return new LeafListSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as LeafListSchemaNode));
+        } else if (node instanceof ListSchemaNode) {
+            return new ListSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as ListSchemaNode));
+        } else if (node instanceof ChoiceCaseNode) {
+            return new ChoiceCaseBuilder(moduleName, line, qname, schemaPath, (node as ChoiceCaseNode));
+        } else {
+            throw new YangParseException(moduleName, line,
+                "Failed to copy node: Unknown type of DataSchemaNode: " + node)
+        }
+    }
+
+    public static def Set<GroupingBuilder> wrapGroupings(String moduleName, int line, Set<GroupingDefinition> nodes,
+        SchemaPath parentPath, URI ns, Date rev, String pref) {
+        val Set<GroupingBuilder> result = new HashSet()
+        for (GroupingDefinition node : nodes) {
+            val qname = new QName(ns, rev, pref, node.QName.localName)
+            val List<QName> path = new ArrayList(parentPath.getPath())
+            path.add(qname)
+            val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
+            result.add(new GroupingBuilderImpl(moduleName, line, qname, schemaPath, node))
+        }
+        return result
+    }
+
+    public static def Set<TypeDefinitionBuilder> wrapTypedefs(String moduleName, int line, DataNodeContainer dataNode,
+        SchemaPath parentPath, URI ns, Date rev, String pref) {
+        val Set<TypeDefinition<?>> nodes = dataNode.typeDefinitions
+        val Set<TypeDefinitionBuilder> result = new HashSet()
+        for (TypeDefinition<?> node : nodes) {
+            val qname = new QName(ns, rev, pref, node.QName.localName)
+            val List<QName> path = new ArrayList(parentPath.getPath())
+            path.add(qname)
+            val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
+            result.add(new TypeDefinitionBuilderImpl(moduleName, line, qname, schemaPath, (node as ExtendedType)))
+        }
+        return result
+    }
+
+    public static def List<UnknownSchemaNodeBuilder> wrapUnknownNodes(String moduleName, int line,
+        List<UnknownSchemaNode> nodes, SchemaPath parentPath, URI ns, Date rev, String pref) {
+        val List<UnknownSchemaNodeBuilder> result = new ArrayList()
+        for (UnknownSchemaNode node : nodes) {
+            val qname = new QName(ns, rev, pref, node.QName.localName)
+            val List<QName> path = new ArrayList(parentPath.getPath())
+            path.add(qname)
+            val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
+            result.add(new UnknownSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as UnknownSchemaNode)))
+        }
+        return result
+    }
+
+}