BUG-1342: fixed bug in resolving augments with target added by uses.
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / SchemaContextUtil.java
index 53c1604b7c42d5d9c4efcfcc36a4034281d7bff6..fbf4c4389b05f140dbc3452c367a18627f707109 100644 (file)
@@ -7,10 +7,10 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
+import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
-
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -20,7 +20,6 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
@@ -80,7 +79,7 @@ public final class SchemaContextUtil {
         Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
         Preconditions.checkArgument(schemaPath != null, "Schema Path reference cannot be NULL");
 
-        final List<QName> prefixedPath = (schemaPath.getPath());
+        final Iterable<QName> prefixedPath = schemaPath.getPathFromRoot();
         if (prefixedPath == null) {
             LOG.debug("Schema path {} has null path", schemaPath);
             return null;
@@ -189,7 +188,7 @@ public final class SchemaContextUtil {
 
         SchemaPath actualNodePath = actualSchemaNode.getPath();
         if (actualNodePath != null) {
-            List<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualSchemaNode);
+            Iterable<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualSchemaNode);
 
             if (qnamePath != null) {
                 return findNodeInSchemaContext(context, qnamePath);
@@ -228,8 +227,8 @@ public final class SchemaContextUtil {
         return context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
     }
 
-    public static SchemaNode findNodeInSchemaContext(final SchemaContext context, final List<QName> path) {
-        final QName current = path.get(0);
+    public static SchemaNode findNodeInSchemaContext(final SchemaContext context, final Iterable<QName> path) {
+        final QName current = path.iterator().next();
 
         LOG.trace("Looking up module {} in context {}", current, path);
         final Module module = context.findModuleByNamespaceAndRevision(current.getNamespace(), current.getRevision());
@@ -241,8 +240,9 @@ public final class SchemaContextUtil {
         return findNodeInModule(module, path);
     }
 
-    public static GroupingDefinition findGrouping(final SchemaContext context, final Module module, final List<QName> path) {
-        QName first = path.get(0);
+    public static GroupingDefinition findGrouping(final SchemaContext context, final Module module, final Iterable<QName> path) {
+        Iterator<QName> iterator = path.iterator();
+        QName first = iterator.next();
         Module m = context.findModuleByNamespace(first.getNamespace()).iterator().next();
         DataNodeContainer currentParent = m;
         for (QName qname : path) {
@@ -267,8 +267,8 @@ public final class SchemaContextUtil {
         return (GroupingDefinition) currentParent;
     }
 
-    private static SchemaNode findNodeInModule(final Module module, final List<QName> path) {
-        final QName current = path.get(0);
+    private static SchemaNode findNodeInModule(final Module module, final Iterable<QName> path) {
+        final QName current = path.iterator().next();
 
         LOG.trace("Looking for data container {} in module {}", current, module);
         SchemaNode parent = module.getDataChildByName(current);
@@ -310,14 +310,14 @@ public final class SchemaContextUtil {
         return null;
     }
 
-    private static SchemaNode findNodeInGrouping(final GroupingDefinition grouping, final List<QName> path) {
-        if (path.isEmpty()) {
+    private static SchemaNode findNodeInGrouping(final GroupingDefinition grouping, final Iterable<QName> path) {
+        final QName current = Iterables.getFirst(path, null);
+        if (current == null) {
             LOG.debug("Found grouping {}", grouping);
             return grouping;
         }
 
         LOG.trace("Looking for path {} in grouping {}", path, grouping);
-        final QName current = path.get(0);
         final DataSchemaNode node = grouping.getDataChildByName(current);
         if (node == null) {
             LOG.debug("No node matching {} found in grouping {}", current, grouping);
@@ -327,14 +327,14 @@ public final class SchemaContextUtil {
         return findNode(node, nextLevel(path));
     }
 
-    private static SchemaNode findNodeInRpc(final RpcDefinition rpc, final List<QName> path) {
-        if (path.isEmpty()) {
+    private static SchemaNode findNodeInRpc(final RpcDefinition rpc, final Iterable<QName> path) {
+        final QName current = Iterables.getFirst(path, null);
+        if (current == null) {
             LOG.debug("Found RPC {}", rpc);
             return rpc;
         }
 
         LOG.trace("Looking for path {} in rpc {}", path, rpc);
-        final QName current = path.get(0);
         switch (current.getLocalName()) {
         case "input":
             return findNode(rpc.getInput(), nextLevel(path));
@@ -346,14 +346,14 @@ public final class SchemaContextUtil {
         }
     }
 
-    private static SchemaNode findNodeInNotification(final NotificationDefinition ntf, final List<QName> path) {
-        if (path.isEmpty()) {
+    private static SchemaNode findNodeInNotification(final NotificationDefinition ntf, final Iterable<QName> path) {
+        final QName current = Iterables.getFirst(path, null);
+        if (current == null) {
             LOG.debug("Found notification {}", ntf);
             return ntf;
         }
 
         LOG.trace("Looking for path {} in notification {}", path, ntf);
-        final QName current = path.get(0);
         DataSchemaNode node = ntf.getDataChildByName(current);
         if (node == null) {
             LOG.debug("No node matching {} found in notification {}", current, ntf);
@@ -363,11 +363,11 @@ public final class SchemaContextUtil {
         return findNode(node, nextLevel(path));
     }
 
-    private static SchemaNode findNode(final ChoiceNode parent, final List<QName> path) {
-        if (path.isEmpty()) {
+    private static SchemaNode findNode(final ChoiceNode parent, final Iterable<QName> path) {
+        final QName current = Iterables.getFirst(path, null);
+        if (current == null) {
             return parent;
         }
-        QName current = path.get(0);
         ChoiceCaseNode node = parent.getCaseNodeByName(current);
         if (node != null) {
             return findNodeInCase(node, nextLevel(path));
@@ -375,12 +375,12 @@ public final class SchemaContextUtil {
         return null;
     }
 
-    private static SchemaNode findNode(final ContainerSchemaNode parent, final List<QName> path) {
-        if (path.isEmpty()) {
+    private static SchemaNode findNode(final ContainerSchemaNode parent, final Iterable<QName> path) {
+        final QName current = Iterables.getFirst(path, null);
+        if (current == null) {
             return parent;
         }
 
-        final QName current = path.get(0);
         final DataSchemaNode node = parent.getDataChildByName(current);
         if (node == null) {
             LOG.debug("Failed to find {} in parent {}", path, parent);
@@ -390,12 +390,12 @@ public final class SchemaContextUtil {
         return findNode(node, nextLevel(path));
     }
 
-    private static SchemaNode findNode(final ListSchemaNode parent, final List<QName> path) {
-        if (path.isEmpty()) {
+    private static SchemaNode findNode(final ListSchemaNode parent, final Iterable<QName> path) {
+        final QName current = Iterables.getFirst(path, null);
+        if (current == null) {
             return parent;
         }
 
-        QName current = path.get(0);
         DataSchemaNode node = parent.getDataChildByName(current);
         if (node == null) {
             LOG.debug("Failed to find {} in parent {}", path, parent);
@@ -404,9 +404,9 @@ public final class SchemaContextUtil {
         return findNode(node, nextLevel(path));
     }
 
-    private static SchemaNode findNode(final DataSchemaNode parent, final List<QName> path) {
+    private static SchemaNode findNode(final DataSchemaNode parent, final Iterable<QName> path) {
         final SchemaNode node;
-        if (!path.isEmpty()) {
+        if (!Iterables.isEmpty(path)) {
             if (parent instanceof ContainerSchemaNode) {
                 node = findNode((ContainerSchemaNode) parent, path);
             } else if (parent instanceof ListSchemaNode) {
@@ -428,12 +428,12 @@ public final class SchemaContextUtil {
         return node;
     }
 
-    public static SchemaNode findNodeInCase(final ChoiceCaseNode parent, final List<QName> path) {
-        if (path.isEmpty()) {
+    public static SchemaNode findNodeInCase(final ChoiceCaseNode parent, final Iterable<QName> path) {
+        final QName current = Iterables.getFirst(path, null);
+        if (current == null) {
             return parent;
         }
 
-        QName current = path.get(0);
         DataSchemaNode node = parent.getDataChildByName(current);
         if (node == null) {
             LOG.debug("Failed to find {} in parent {}", path, parent);
@@ -451,8 +451,8 @@ public final class SchemaContextUtil {
         return null;
     }
 
-    private static List<QName> nextLevel(final List<QName> path) {
-        return path.subList(1, path.size());
+    private static Iterable<QName> nextLevel(final Iterable<QName> path) {
+        return Iterables.skip(path, 1);
     }
 
     public static NotificationDefinition getNotificationByName(final Module module, final QName name) {
@@ -498,7 +498,7 @@ public final class SchemaContextUtil {
         Preconditions.checkArgument(m != null, "Failed to find module for node {} in context {}", node, ctx);
 
         for (final UsesNode u : m.getUses()) {
-            final SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
+            final SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPathFromRoot());
             Preconditions.checkArgument(targetGrouping instanceof GroupingDefinition,
                     "Failed to generate code for augment in %s", u);
 
@@ -517,7 +517,7 @@ public final class SchemaContextUtil {
     }
 
     private static DataSchemaNode findCorrectTargetFromGrouping(final DataSchemaNode node, final SchemaContext ctx) {
-        if (node.getPath().getPath().size() != 1) {
+        if (Iterables.size(node.getPath().getPathTowardsRoot()) != 1) {
             QName currentName = node.getQName();
             // tmpPath is used to track level of nesting
             List<QName> tmpPath = new ArrayList<>();
@@ -625,8 +625,12 @@ public final class SchemaContextUtil {
     }
 
     private static DataSchemaNode getResultFromUses(final UsesNode u, final String currentName, final SchemaContext ctx) {
-        SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
-
+        SchemaNode targetGrouping = SchemaContextUtil.findNodeInSchemaContext(ctx, u.getGroupingPath()
+                .getPathFromRoot());
+        if (!(targetGrouping instanceof GroupingDefinition)) {
+            targetGrouping = findGrouping(ctx, getParentModule(targetGrouping, ctx), u.getGroupingPath()
+                    .getPathFromRoot());
+        }
         Preconditions.checkArgument(targetGrouping instanceof GroupingDefinition,
                 "Failed to generate code for augment in %s", u);
         GroupingDefinition gr = (GroupingDefinition) targetGrouping;
@@ -847,7 +851,7 @@ public final class SchemaContextUtil {
      *            Schema Path for Leafref
      * @return list of QName
      */
-    private static List<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
+    private static Iterable<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
             final RevisionAwareXPath relativeXPath, final SchemaNode leafrefParentNode) {
         Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
@@ -867,16 +871,13 @@ public final class SchemaContextUtil {
             ++colCount;
         }
 
-        final List<QName> absolutePath = new LinkedList<QName>();
-        List<QName> path = leafrefParentNode.getPath().getPath();
-        if (path != null) {
-            int lenght = path.size() - colCount;
-            absolutePath.addAll(path.subList(0, lenght));
-            for (String s : Iterables.skip(xpaths, colCount)) {
-                absolutePath.add(stringPathPartToQName(context, module, s));
-            }
-        }
-
-        return absolutePath;
+        final Iterable<QName> parent = leafrefParentNode.getPath().getPathFromRoot();
+        return Iterables.concat(Iterables.limit(parent, Iterables.size(parent) - colCount),
+                Iterables.transform(Iterables.skip(xpaths, colCount), new Function<String, QName>() {
+                    @Override
+                    public QName apply(final String input) {
+                        return stringPathPartToQName(context, module, input);
+                    }
+                }));
     }
 }