Merge "BUG-944: optimize SchemaContextUtil"
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / SchemaContextUtil.java
index f05c20614d542618be17cef838aad0919f6b4e63..53c1604b7c42d5d9c4efcfcc36a4034281d7bff6 100644 (file)
@@ -8,15 +8,19 @@
 package org.opendaylight.yangtools.yang.model.util;
 
 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.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
+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;
@@ -48,6 +52,8 @@ import org.slf4j.LoggerFactory;
  */
 public final class SchemaContextUtil {
     private static final Logger LOG = LoggerFactory.getLogger(SchemaContextUtil.class);
+    private static final Splitter COLON_SPLITTER = Splitter.on(':');
+    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
 
     private SchemaContextUtil() {
     }
@@ -215,13 +221,10 @@ public final class SchemaContextUtil {
         Preconditions.checkState(schemaNode.getPath() != null, "Schema Path for Schema Node is not "
                 + "set properly (Schema Path is NULL)");
 
-        List<QName> qnamedPath = schemaNode.getPath().getPath();
-        if (qnamedPath == null || qnamedPath.isEmpty()) {
-            throw new IllegalStateException("Schema Path contains invalid state of path parts."
-                    + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
-                    + "of path.");
-        }
-        QName qname = qnamedPath.get(qnamedPath.size() - 1);
+        final QName qname = Iterables.getFirst(schemaNode.getPath().getPathTowardsRoot(), null);
+        Preconditions.checkState(qname != null,
+                "Schema Path contains invalid state of path parts. " +
+                "The Schema Path MUST contain at least ONE QName which defines namespace and Local name of path.");
         return context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
     }
 
@@ -521,13 +524,8 @@ public final class SchemaContextUtil {
             Object parent = null;
 
             // create schema path of parent node
-            SchemaPath sp = node.getPath();
-            List<QName> newNames = new ArrayList<>(sp.getPath());
-            // parentPath = nodePath - lastQName
-            newNames.remove(newNames.size() - 1);
-            SchemaPath newSp = SchemaPath.create(newNames, sp.isAbsolute());
-            // find parent node by its schema path
-            parent = findDataSchemaNode(ctx, newSp);
+            SchemaPath sp = node.getPath().getParent();
+            parent = findDataSchemaNode(ctx, sp);
 
             do {
                 tmpPath.add(currentName);
@@ -549,21 +547,17 @@ public final class SchemaContextUtil {
                 // groupings => parent is added by grouping too, so repeat same
                 // process for parent
                 if (result == null) {
+                    final SchemaNode sn = (SchemaNode) parent;
+
                     // set current name to name of parent node
-                    currentName = ((SchemaNode) parent).getQName();
+                    currentName = sn.getQName();
                     Preconditions.checkArgument(parent instanceof SchemaNode,
                             "Failed to generate code for augmend node {} at parent {}", node, parent);
+
                     // create schema path for parent of current parent
-                    SchemaPath nodeSp = ((SchemaNode) parent).getPath();
-                    List<QName> nodeNewNames = new ArrayList<>(nodeSp.getPath());
-                    nodeNewNames.remove(nodeNewNames.size() - 1);
-                    // set new parent based on path
-                    if (nodeNewNames.isEmpty()) {
-                        parent = getParentModule((SchemaNode) parent, ctx);
-                    } else {
-                        SchemaPath nodeNewSp = new SchemaPath(nodeNewNames, nodeSp.isAbsolute());
-                        parent = findDataSchemaNode(ctx, nodeNewSp);
-                    }
+                    final SchemaPath parentSp = sn.getPath().getParent();
+                    parent = parentSp.getPathFromRoot().iterator().hasNext() ? findDataSchemaNode(ctx, parentSp)
+                            : getParentModule(sn, ctx);
                 } else {
                     // if wanted node was found in grouping, traverse this node
                     // based on level of nesting
@@ -591,11 +585,7 @@ public final class SchemaContextUtil {
         AugmentationSchema augment = null;
         do {
             SchemaPath sp = ((SchemaNode) parent).getPath();
-            List<QName> names = sp.getPath();
-            List<QName> newNames = new ArrayList<>(names);
-            newNames.remove(newNames.size() - 1);
-            SchemaPath newSp = SchemaPath.create(newNames, sp.isAbsolute());
-            parent = findDataSchemaNode(ctx, newSp);
+            parent = findDataSchemaNode(ctx, sp.getParent());
             if (parent instanceof AugmentationTarget) {
                 tmpPath.add(currentName);
                 tmpTree.add((SchemaNode) currentNode);
@@ -644,7 +634,7 @@ public final class SchemaContextUtil {
     }
 
     private static Module getParentModule(final SchemaNode node, final SchemaContext ctx) {
-        QName qname = node.getPath().getPath().get(0);
+        QName qname = node.getPath().getPathFromRoot().iterator().next();
         URI namespace = qname.getNamespace();
         Date revision = qname.getRevision();
         return ctx.findModuleByNamespaceAndRevision(namespace, revision);
@@ -753,8 +743,7 @@ public final class SchemaContextUtil {
         Preconditions.checkArgument(xpath != null, "XPath string reference cannot be NULL");
 
         List<QName> path = new LinkedList<QName>();
-        String[] prefixedPath = xpath.split("/");
-        for (String pathComponent : prefixedPath) {
+        for (String pathComponent : SLASH_SPLITTER.split(xpath)) {
             if (!pathComponent.isEmpty()) {
                 path.add(stringPathPartToQName(context, parentModule, pathComponent));
             }
@@ -788,14 +777,18 @@ public final class SchemaContextUtil {
         Preconditions.checkArgument(parentModule != null, "Parent Module reference cannot be NULL");
         Preconditions.checkArgument(prefixedPathPart != null, "Prefixed Path Part cannot be NULL!");
 
-        if (prefixedPathPart.contains(":")) {
-            String[] prefixedName = prefixedPathPart.split(":");
-            Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]);
+        if (prefixedPathPart.indexOf(':') != -1) {
+            final Iterator<String> prefixedName = COLON_SPLITTER.split(prefixedPathPart).iterator();
+            final String modulePrefix = prefixedName.next();
+
+            Module module = resolveModuleForPrefix(context, parentModule, modulePrefix);
             Preconditions.checkArgument(module != null, "Failed to resolve xpath: no module found for prefix %s in module %s",
-                    prefixedName[0], parentModule.getName());
-            return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]);
+                    modulePrefix, parentModule.getName());
+
+            // FIXME: Module should have a QNameModule handle
+            return QName.create(module.getNamespace(), module.getRevision(), prefixedName.next());
         } else {
-            return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
+            return QName.create(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
         }
     }
 
@@ -865,25 +858,23 @@ public final class SchemaContextUtil {
         Preconditions.checkState(leafrefParentNode.getPath() != null,
                 "Schema Path reference for Leafref cannot be NULL");
 
-        List<QName> absolutePath = new LinkedList<QName>();
-        String strXPath = relativeXPath.toString();
-        String[] xpaths = strXPath.split("/");
+        final Iterable<String> xpaths = SLASH_SPLITTER.split(relativeXPath.toString());
 
+        // Find out how many "parent" components there are
+        // FIXME: is .contains() the right check here?
         int colCount = 0;
-        while (xpaths[colCount].contains("..")) {
-            colCount = colCount + 1;
+        for (Iterator<String> it = xpaths.iterator(); it.hasNext() && it.next().contains(".."); ) {
+            ++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));
-            List<String> xpathsList = Arrays.asList(xpaths);
-            List<String> sublistedXPath = xpathsList.subList(colCount, xpaths.length);
-            List<QName> sublist = new ArrayList<>();
-            for (String pathPart : sublistedXPath) {
-                sublist.add(stringPathPartToQName(context, module, pathPart));
+            for (String s : Iterables.skip(xpaths, colCount)) {
+                absolutePath.add(stringPathPartToQName(context, module, s));
             }
-            absolutePath.addAll(sublist);
         }
 
         return absolutePath;