Revert "Revert "BUG-994: reorganize SchemaPath into a tree"" 07/8407/2
authorRobert Varga <rovarga@cisco.com>
Fri, 27 Jun 2014 12:46:08 +0000 (14:46 +0200)
committerRobert Varga <rovarga@cisco.com>
Mon, 30 Jun 2014 09:03:59 +0000 (11:03 +0200)
This reverts commit 65f3c40b20bd437268a3ebc83afe23aa07f80eaf.

Change-Id: I4540def627dcafbb39afa17a8e4ff076622d347c
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/SchemaPath.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java

index 6a72b0efbd7ae3957203ad579348f485a377cdb9..e1778e47cd1d67839d853a2767e8d1d8c3070466 100644 (file)
@@ -14,11 +14,11 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
 import java.util.Arrays;
-import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.util.HashCodeBuilder;
 import org.opendaylight.yangtools.yang.common.QName;
 
 /**
@@ -29,8 +29,8 @@ public abstract class SchemaPath implements Immutable {
      * An absolute SchemaPath.
      */
     private static final class AbsoluteSchemaPath extends SchemaPath {
-        private AbsoluteSchemaPath(final Iterable<QName> path, final int hash) {
-            super(path, hash);
+        private AbsoluteSchemaPath(final SchemaPath parent, final QName qname) {
+            super(parent, qname);
         }
 
         @Override
@@ -39,8 +39,8 @@ public abstract class SchemaPath implements Immutable {
         }
 
         @Override
-        protected SchemaPath createInstance(final Iterable<QName> path, final int hash) {
-            return new AbsoluteSchemaPath(path, hash);
+        protected SchemaPath createInstance(final SchemaPath parent, final QName qname) {
+            return new AbsoluteSchemaPath(parent, qname);
         }
     }
 
@@ -48,8 +48,8 @@ public abstract class SchemaPath implements Immutable {
      * A relative SchemaPath.
      */
     private static final class RelativeSchemaPath extends SchemaPath {
-        private RelativeSchemaPath(final Iterable<QName> path, final int hash) {
-            super(path, hash);
+        private RelativeSchemaPath(final SchemaPath parent, final QName qname) {
+            super(parent, qname);
         }
 
         @Override
@@ -58,25 +58,30 @@ public abstract class SchemaPath implements Immutable {
         }
 
         @Override
-        protected SchemaPath createInstance(final Iterable<QName> path, final int hash) {
-            return new RelativeSchemaPath(path, hash);
+        protected SchemaPath createInstance(final SchemaPath parent, final QName qname) {
+            return new RelativeSchemaPath(parent, qname);
         }
     }
 
     /**
      * Shared instance of the conceptual root schema node.
      */
-    public static final SchemaPath ROOT = new AbsoluteSchemaPath(Collections.<QName>emptyList(), Boolean.TRUE.hashCode());
+    public static final SchemaPath ROOT = new AbsoluteSchemaPath(null, null);
 
     /**
      * Shared instance of the "same" relative schema node.
      */
-    public static final SchemaPath SAME = new RelativeSchemaPath(Collections.<QName>emptyList(), Boolean.FALSE.hashCode());
+    public static final SchemaPath SAME = new RelativeSchemaPath(null, null);
 
     /**
-     * List of QName instances which represents complete path to the node.
+     * Parent path.
      */
-    private final Iterable<QName> path;
+    private final SchemaPath parent;
+
+    /**
+     * This component.
+     */
+    private final QName qname;
 
     /**
      * Cached hash code. We can use this since we are immutable.
@@ -91,7 +96,7 @@ public abstract class SchemaPath implements Immutable {
 
     private ImmutableList<QName> getLegacyPath() {
         if (legacyPath == null) {
-            legacyPath = ImmutableList.copyOf(path);
+            legacyPath = ImmutableList.copyOf(getPathTowardsRoot()).reverse();
         }
 
         return legacyPath;
@@ -110,9 +115,16 @@ public abstract class SchemaPath implements Immutable {
         return getLegacyPath();
     }
 
-    protected SchemaPath(final Iterable<QName> path, final int hash) {
-        this.path = Preconditions.checkNotNull(path);
-        this.hash = hash;
+    protected SchemaPath(final SchemaPath parent, final QName qname) {
+        this.parent = parent;
+        this.qname = qname;
+
+        int h = parent == null ? 0 : parent.hashCode();
+        if (qname != null) {
+            h = h * 31 + qname.hashCode();
+        }
+
+        hash = h;
     }
 
     /**
@@ -155,20 +167,7 @@ public abstract class SchemaPath implements Immutable {
      * @param hash intended hash code
      * @return A new SchemaPath instance
      */
-    protected abstract SchemaPath createInstance(Iterable<QName> path, int hash);
-
-    private SchemaPath trustedCreateChild(final Iterable<QName> relative) {
-        if (Iterables.isEmpty(relative)) {
-            return this;
-        }
-
-        final HashCodeBuilder<QName> b = new HashCodeBuilder<>(hash);
-        for (QName p : relative) {
-            b.addArgument(p);
-        }
-
-        return createInstance(Iterables.concat(path, relative), b.toInstance());
-    }
+    protected abstract SchemaPath createInstance(SchemaPath parent, QName qname);
 
     /**
      * Create a child path based on concatenation of this path and a relative path.
@@ -181,7 +180,12 @@ public abstract class SchemaPath implements Immutable {
             return this;
         }
 
-        return trustedCreateChild(ImmutableList.copyOf(relative));
+        SchemaPath parent = this;
+        for (QName qname : relative) {
+            parent = parent.createInstance(parent, qname);
+        }
+
+        return parent;
     }
 
     /**
@@ -192,7 +196,13 @@ public abstract class SchemaPath implements Immutable {
      */
     public SchemaPath createChild(final SchemaPath relative) {
         Preconditions.checkArgument(!relative.isAbsolute(), "Child creation requires relative path");
-        return trustedCreateChild(relative.path);
+
+        SchemaPath parent = this;
+        for (QName qname : relative.getPathFromRoot()) {
+            parent = parent.createInstance(parent, qname);
+        }
+
+        return parent;
     }
 
     /**
@@ -215,7 +225,7 @@ public abstract class SchemaPath implements Immutable {
      *         path from the root to the schema node.
      */
     public Iterable<QName> getPathFromRoot() {
-        return path;
+        return getLegacyPath();
     }
 
     /**
@@ -226,7 +236,35 @@ public abstract class SchemaPath implements Immutable {
      *         path from the schema node towards the root.
      */
     public Iterable<QName> getPathTowardsRoot() {
-        return getLegacyPath().reverse();
+        return new Iterable<QName>() {
+            @Override
+            public Iterator<QName> iterator() {
+                return new Iterator<QName>() {
+                    private SchemaPath current = SchemaPath.this;
+
+                    @Override
+                    public boolean hasNext() {
+                        return current.parent != null;
+                    }
+
+                    @Override
+                    public QName next() {
+                        if (current.parent != null) {
+                            final QName ret = current.qname;
+                            current = current.parent;
+                            return ret;
+                        } else {
+                            throw new NoSuchElementException("No more elements available");
+                        }
+                    }
+
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException("Component removal not supported");
+                    }
+                };
+            }
+        };
     }
 
     /**
@@ -235,13 +273,7 @@ public abstract class SchemaPath implements Immutable {
      * @return Parent path, null if this SchemaPath is already toplevel.
      */
     public SchemaPath getParent() {
-        final int size = Iterables.size(path);
-        if (size != 0) {
-            final SchemaPath parent = isAbsolute() ? ROOT : SAME;
-            return parent.trustedCreateChild(Iterables.limit(path, size - 1));
-        } else {
-            return null;
-        }
+        return parent;
     }
 
     /**
@@ -268,8 +300,22 @@ public abstract class SchemaPath implements Immutable {
         if (getClass() != obj.getClass()) {
             return false;
         }
-        SchemaPath other = (SchemaPath) obj;
-        return Iterables.elementsEqual(path, other.path);
+        final SchemaPath other = (SchemaPath) obj;
+
+        if (qname != null) {
+            if (!qname.equals(other.qname)) {
+                return false;
+            }
+        } else {
+            if (other.qname != null) {
+                return false;
+            }
+        }
+
+        if (parent == null) {
+            return other.parent == null;
+        }
+        return parent.equals(other.parent);
     }
 
     @Override
@@ -278,6 +324,6 @@ public abstract class SchemaPath implements Immutable {
     }
 
     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
-        return toStringHelper.add("path", path);
+        return toStringHelper.add("path", getPathFromRoot());
     }
 }
index 2af7159ffed81dd8d70cabaf205648acbefc2b0d..fc98c1daf0aef88d6e202743d0db8e3fcb56576d 100644 (file)
@@ -10,7 +10,6 @@ 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.ImmutableList;
 import com.google.common.collect.Iterables;
 
 import java.net.URI;
@@ -869,14 +868,13 @@ public final class SchemaContextUtil {
             ++colCount;
         }
 
-        final ImmutableList<QName> relative = ImmutableList.copyOf(
+        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);
                     }
                 }));
-        final Iterable<QName> parent = leafrefParentNode.getPath().getPathFromRoot();
-        return Iterables.concat(Iterables.limit(parent, Iterables.size(parent) - colCount), relative);
     }
 }