X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-binding%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fbinding%2FInstanceIdentifier.java;h=9a597152c3ce4f3aa1a4e04e8ff94c230378e0c4;hb=06452ecebb1998538c59a0a5ed47f47034045af5;hp=04f614da9385bd40709b75eadf2f648f4913503b;hpb=342ad28fd7c22e983072bd829f676e5e9a0b9466;p=yangtools.git diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java index 04f614da93..9a597152c3 100644 --- a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java +++ b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java @@ -7,6 +7,15 @@ */ package org.opendaylight.yangtools.yang.binding; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +import java.io.IOException; +import java.io.Serializable; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -14,13 +23,7 @@ import java.util.List; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.concepts.Path; - -import com.google.common.base.Objects; -import com.google.common.base.Objects.ToStringHelper; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableCollection; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; +import org.opendaylight.yangtools.util.HashCodeBuilder; /** * @@ -51,7 +54,8 @@ import com.google.common.collect.Iterables; * This would be the same as using a path like so, "/nodes/node/openflow:1" to refer to the openflow:1 node * */ -public class InstanceIdentifier implements Path>, Immutable { +public class InstanceIdentifier implements Path>, Immutable, Serializable { + private static final long serialVersionUID = 1L; /* * Protected to differentiate internal and external access. Internal * access is required never to modify the contents. References passed @@ -103,7 +107,7 @@ public class InstanceIdentifier implements Path implements Path other = (InstanceIdentifier) obj; + if (pathArguments == other.pathArguments) { + return true; + } + + /* + * We could now just go and compare the pathArguments, but that + * can be potentially expensive. Let's try to avoid that by + * checking various things that we have cached from pathArguments + * and trying to prove the identifiers are *not* equal. + */ if (hash != other.hash) { return false; } + if (wildcarded != other.wildcarded) { + return false; + } + if (targetType != other.targetType) { + return false; + } + if (fastNonEqual(other)) { + return false; + } + // Everything checks out so far, so we have to do a full equals return Iterables.elementsEqual(pathArguments, other.pathArguments); } + /** + * Perform class-specific fast checks for non-equality. This allows + * subclasses to avoid iterating over the pathArguments by performing + * quick checks on their specific fields. + * + * @param other The other identifier, guaranteed to be the same class + * @return @true if the other identifier cannot be equal to this one. + */ + protected boolean fastNonEqual(final InstanceIdentifier other) { + return false; + } + @Override public final String toString() { return addToStringAttributes(Objects.toStringHelper(this)).toString(); @@ -161,7 +197,7 @@ public class InstanceIdentifier implements Path ret = (InstanceIdentifier) create(Iterables.limit(getPathArguments(), i)); + final InstanceIdentifier ret = (InstanceIdentifier) internalCreate(Iterables.limit(getPathArguments(), i)); return ret; } @@ -285,10 +321,10 @@ public class InstanceIdentifier implements Path & ChildOf, K extends Identifier> InstanceIdentifier child( + public final & ChildOf, K extends Identifier> KeyedInstanceIdentifier child( final Class listItem, final K listKey) { final PathArgument arg = new IdentifiableItem<>(listItem, listKey); - return (InstanceIdentifier) childIdentifier(arg); + return (KeyedInstanceIdentifier) childIdentifier(arg); } @SuppressWarnings("unchecked") @@ -353,20 +389,17 @@ public class InstanceIdentifier implements Path - * List path = Arrays.asList(new Item(Nodes.class)) - * new InstanceIdentifier(path); - * * * @param pathArguments The path to a specific node in the data tree * @return InstanceIdentifier instance * @throws IllegalArgumentException if pathArguments is empty or * contains a null element. */ - public static InstanceIdentifier create(final Iterable pathArguments) { + private static InstanceIdentifier internalCreate(final Iterable pathArguments) { final Iterator it = Preconditions.checkNotNull(pathArguments, "pathArguments may not be null").iterator(); final HashCodeBuilder hashBuilder = new HashCodeBuilder<>(); boolean wildcard = false; @@ -385,14 +418,31 @@ public class InstanceIdentifier implements Path immutableArguments; + return trustedCreate(a, pathArguments, hashBuilder.toInstance(), wildcard); + } + + /** + * Create an instance identifier for a very specific object type. + * + * Example + *
+     *  List path = Arrays.asList(new Item(Nodes.class))
+     *  new InstanceIdentifier(path);
+     * 
+ * + * @param pathArguments The path to a specific node in the data tree + * @return InstanceIdentifier instance + * @throws IllegalArgumentException if pathArguments is empty or + * contains a null element. + */ + public static InstanceIdentifier create(final Iterable pathArguments) { if (pathArguments instanceof ImmutableCollection) { - immutableArguments = (Iterable) pathArguments; + @SuppressWarnings("unchecked") + final Iterable immutableArguments = (Iterable) pathArguments; + return internalCreate(immutableArguments); } else { - immutableArguments = ImmutableList.copyOf(pathArguments); + return internalCreate(ImmutableList.copyOf(pathArguments)); } - - return trustedCreate(a, immutableArguments, hashBuilder.toInstance(), wildcard); } /** @@ -426,7 +476,7 @@ public class InstanceIdentifier implements Path trustedCreate(final PathArgument arg, final Iterable pathArguments, final int hash, boolean wildcarded) { - if (Identifiable.class.isAssignableFrom(arg.getType())) { + if (Identifiable.class.isAssignableFrom(arg.getType()) && !(wildcarded)) { Identifier key = null; if (arg instanceof IdentifiableItem) { key = ((IdentifiableItem)arg).key; @@ -446,11 +496,12 @@ public class InstanceIdentifier implements Path { Class getType(); } - private static abstract class AbstractPathArgument implements PathArgument { + private static abstract class AbstractPathArgument implements PathArgument, Serializable { + private static final long serialVersionUID = 1L; private final Class type; protected AbstractPathArgument(final Class type) { @@ -464,10 +515,7 @@ public class InstanceIdentifier implements Path implements Path other = (AbstractPathArgument) obj; - if (type == null) { - if (other.type != null) { - return false; - } - } else if (!type.equals(other.type)) { - return false; - } - return true; + return type.equals(other.type); + } + + @Override + public int compareTo(final PathArgument arg) { + return type.getCanonicalName().compareTo(arg.getType().getCanonicalName()); } } @@ -500,6 +546,8 @@ public class InstanceIdentifier implements Path */ public static final class Item extends AbstractPathArgument { + private static final long serialVersionUID = 1L; + public Item(final Class type) { super(type); } @@ -518,6 +566,7 @@ public class InstanceIdentifier implements Path The identifier of the object */ public static final class IdentifiableItem & DataObject, T extends Identifier> extends AbstractPathArgument { + private static final long serialVersionUID = 1L; private final T key; public IdentifiableItem(final Class type, final T key) { @@ -531,12 +580,12 @@ public class InstanceIdentifier implements Path) obj).getKey()); + return super.equals(obj) && key.equals(((IdentifiableItem) obj).getKey()); } @Override public int hashCode() { - return key.hashCode(); + return super.hashCode() * 31 + key.hashCode(); } @Override @@ -602,4 +651,18 @@ public class InstanceIdentifier implements Path build(); } + + private void writeObject(final java.io.ObjectOutputStream out) throws IOException { + out.writeObject(targetType); + out.writeBoolean(wildcarded); + out.writeInt(hash); + out.write(Iterables.size(pathArguments)); + for (Object o : pathArguments) { + out.writeObject(o); + } + } + + private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + // TODO Auto-generated method stub + } }