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;
/**
* 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
}
@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);
}
}
* 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
}
@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.
private ImmutableList<QName> getLegacyPath() {
if (legacyPath == null) {
- legacyPath = ImmutableList.copyOf(path);
+ legacyPath = ImmutableList.copyOf(getPathTowardsRoot()).reverse();
}
return legacyPath;
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;
}
/**
* @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.
return this;
}
- return trustedCreateChild(ImmutableList.copyOf(relative));
+ SchemaPath parent = this;
+ for (QName qname : relative) {
+ parent = parent.createInstance(parent, qname);
+ }
+
+ return parent;
}
/**
*/
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;
}
/**
* path from the root to the schema node.
*/
public Iterable<QName> getPathFromRoot() {
- return path;
+ return getLegacyPath();
}
/**
* 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");
+ }
+ };
+ }
+ };
}
/**
* @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;
}
/**
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
}
protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
- return toStringHelper.add("path", path);
+ return toStringHelper.add("path", getPathFromRoot());
}
}