Refactored uses statement handling in parser.
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / util / ParserUtils.xtend
index 80b51988d168043be20a9dbc26a8e1ee013caf62..e3d3a4898ae78dde32e621a091e1253763a38cf4 100644 (file)
@@ -12,11 +12,13 @@ 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;
@@ -35,11 +37,14 @@ import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder.ChoiceN
 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.IdentitySchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ListSchemaNodeBuilder.ListSchemaNodeImpl;
 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 java.net.URI
+import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember
 
 public final class ParserUtils {
 
@@ -59,6 +64,14 @@ public final class ParserUtils {
         return new SchemaPath(path, schemaPath.isAbsolute());
     }
 
+    public static def SchemaPath correctSchemaPath(SchemaPath old, URI ns, Date revision, String prefix) {
+        val List<QName> newPath = new ArrayList();
+        for (name : old.path) {
+            newPath.add(new QName(ns, revision, prefix, name.localName))
+        }
+        return new SchemaPath(newPath, old.absolute) 
+    }
+
     /**
      * Get module import referenced by given prefix.
      *
@@ -202,22 +215,49 @@ public final class ParserUtils {
     public static def void fillAugmentTarget(AugmentationSchemaBuilder augment, DataNodeContainerBuilder target) {
         for (DataSchemaNodeBuilder child : augment.getChildNodeBuilders()) {
             val childCopy = CopyUtils.copy(child, target, false);
-            childCopy.setAugmenting(true);
+            if (augment.parent instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy);
             correctNodePath(child, target.getPath());
             correctNodePath(childCopy, target.getPath());
             try {
                 target.addChildNode(childCopy);
             } catch (YangParseException e) {
-
                 // more descriptive message
                 throw new YangParseException(augment.getModuleName(), augment.getLine(),
                     "Failed to perform augmentation: " + e.getMessage());
             }
+        }
+    }
 
+    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);
+            }
         }
-        for (UsesNodeBuilder usesNode : augment.getUsesNodes()) {
-            val copy = CopyUtils.copyUses(usesNode, target);
-            target.addUsesNode(copy);
+    }
+
+    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);
+            }
         }
     }
 
@@ -232,7 +272,10 @@ public final class ParserUtils {
     public static def void fillAugmentTarget(AugmentationSchemaBuilder augment, ChoiceBuilder target) {
         for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
             val childCopy = CopyUtils.copy(builder, target, false);
-            childCopy.setAugmenting(true);
+            if (augment.parent instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy)
             correctNodePath(builder, target.getPath());
             correctNodePath(childCopy, target.getPath());
             target.addCase(childCopy);
@@ -240,7 +283,7 @@ public final class ParserUtils {
         for (UsesNodeBuilder usesNode : augment.getUsesNodes()) {
             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");
             }
         }
     }
@@ -294,7 +337,11 @@ public final class ParserUtils {
                 var SchemaNodeBuilder nodeFound = dataNodeContainerParent.getDataChildByName(currentName);
                 // if not found, search in notifications
                 if (nodeFound == null && currentParent instanceof ModuleBuilder) {
-                       nodeFound = searchNotifications(currentParent as ModuleBuilder, currentName);
+                    nodeFound = searchNotifications(currentParent as ModuleBuilder, currentName);
+                }
+                // if not found, search in rpcs
+                if (nodeFound == null && currentParent instanceof ModuleBuilder) {
+                    nodeFound = searchRpcs(currentParent as ModuleBuilder, currentName);
                 }
                 // if not found, search in uses
                 if (nodeFound == null) {
@@ -310,6 +357,13 @@ public final class ParserUtils {
             } else if (currentParent instanceof ChoiceBuilder) {
                 val choiceParent = currentParent as ChoiceBuilder;
                 currentParent = choiceParent.getCaseNodeByName(currentName);
+            } else if (currentParent instanceof RpcDefinitionBuilder) {
+                val rpc = currentParent as RpcDefinitionBuilder;
+                if ("input".equals(currentName)) {
+                    currentParent = rpc.input;
+                } else if ("output".equals(currentName)) {
+                    currentParent = rpc.output;
+                }
             } else {
                 throw new YangParseException(moduleName, line,
                         "Error in augment parsing: failed to find node " + currentName);
@@ -333,10 +387,24 @@ public final class ParserUtils {
         return null;
     }
 
+    private static def searchRpcs(ModuleBuilder parent, String name) {
+        for(rpc : parent.rpcs) {
+            if(rpc.getQName().localName.equals(name)) {
+                return rpc;
+            }
+        }
+        return null;
+    }
+
     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);
@@ -347,7 +415,7 @@ public final class ParserUtils {
     }
     
     public static def getRpc(ModuleBuilder module,String name) {
-        for(rpc : module.rpcs) {
+        for(rpc : module.getRpcs()) {
             if(name == rpc.QName.localName) {
                 return rpc;
             }
@@ -356,7 +424,7 @@ public final class ParserUtils {
     }
     
     public static def getNotification(ModuleBuilder module,String name) {
-        for(notification : module.notifications) {
+        for(notification : module.getNotifications()) {
             if(name == notification.QName.localName) {
                 return notification;
             }
@@ -401,6 +469,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.
      *
@@ -411,12 +487,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)) {
@@ -547,25 +617,63 @@ public final class ParserUtils {
             return true;
         }
 
-        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 = findModuleFromBuilders(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);
+    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, "Failed to parse identityref base: " +
+                    baseString);
             }
-            return result;
+            val prefix = splittedBase.get(0);
+            val name = splittedBase.get(1);
+            val dependentModule = findModuleFromBuilders(modules, module, prefix, line);
+            if (dependentModule !== null) {
+                result = findIdentity(dependentModule.identities, name);
+            }
+        } else {
+            result = findIdentity(module.identities, baseString);
+        }
+        return result;
+    }
+
+    public static def IdentitySchemaNode findBaseIdentityFromContext(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            ModuleBuilder module, String baseString, int line, SchemaContext context) {
+        var IdentitySchemaNode result = null;
+
+        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);
+
+        if (result == null) {
+            throw new YangParseException(module.name, line, "Failed to find base identity");
+        }
+        return result;
+    }
+
+    private static def IdentitySchemaNodeBuilder findIdentity(Set<IdentitySchemaNodeBuilder> identities, String name) {
+        for (identity : identities) {
+            if (identity.QName.localName.equals(name)) {
+                return identity;
+            }
+        }
+        return null;
+    }
+
+    private static def IdentitySchemaNode findIdentityNode(Set<IdentitySchemaNode> identities, String name) {
+        for (identity : identities) {
+            if (identity.QName.localName.equals(name)) {
+                return identity;
+            }
+        }
+        return null;
+    }
 
         /**
      * Get module in which this node is defined.
@@ -583,5 +691,6 @@ public final class ParserUtils {
             }
             return parent as ModuleBuilder;
         }
-    }
-    
\ No newline at end of file
+
+}
+