final class FixedYangInstanceIdentifier extends YangInstanceIdentifier implements Cloneable {
static final @NonNull FixedYangInstanceIdentifier EMPTY_INSTANCE = new FixedYangInstanceIdentifier(
- ImmutableList.of(), new HashCodeBuilder<>().build());
+ ImmutableList.of());
private static final long serialVersionUID = 1L;
private final ImmutableList<PathArgument> path;
private transient volatile YangInstanceIdentifier parent;
- FixedYangInstanceIdentifier(final ImmutableList<PathArgument> path, final int hash) {
- super(hash);
+ FixedYangInstanceIdentifier(final ImmutableList<PathArgument> path) {
this.path = requireNonNull(path, "path must not be null.");
}
- static @NonNull FixedYangInstanceIdentifier create(final Iterable<? extends PathArgument> path, final int hash) {
- return new FixedYangInstanceIdentifier(ImmutableList.copyOf(path), hash);
+ static @NonNull FixedYangInstanceIdentifier of(final ImmutableList<PathArgument> path) {
+ return path.isEmpty() ? EMPTY_INSTANCE : new FixedYangInstanceIdentifier(path);
+ }
+
+ static @NonNull FixedYangInstanceIdentifier of(final List<PathArgument> path) {
+ return path.isEmpty() ? EMPTY_INSTANCE : new FixedYangInstanceIdentifier(ImmutableList.copyOf(path));
}
@Override
@Override
YangInstanceIdentifier createRelativeIdentifier(final int skipFromRoot) {
- if (skipFromRoot == path.size()) {
- return EMPTY_INSTANCE;
- }
-
- final ImmutableList<PathArgument> newPath = path.subList(skipFromRoot, path.size());
- final HashCodeBuilder<PathArgument> hash = new HashCodeBuilder<>();
- for (PathArgument a : newPath) {
- hash.addArgument(a);
- }
-
- return new FixedYangInstanceIdentifier(newPath, hash.build());
+ return skipFromRoot == path.size() ? EMPTY_INSTANCE
+ : new FixedYangInstanceIdentifier(path.subList(skipFromRoot, path.size()));
}
private Object readResolve() throws ObjectStreamException {
}
@Override
- boolean pathArgumentsEqual(final YangInstanceIdentifier other) {
- if (other instanceof FixedYangInstanceIdentifier) {
- return path.equals(((FixedYangInstanceIdentifier) other).path);
+ int computeHashCode() {
+ int ret = 1;
+ for (PathArgument arg : path) {
+ ret = HashCodeBuilder.nextHashCode(ret, arg);
}
- return super.pathArgumentsEqual(other);
+ return ret;
}
@Override
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.util.HashCodeBuilder;
final class StackedYangInstanceIdentifier extends YangInstanceIdentifier implements Cloneable {
private static final long serialVersionUID = 1L;
private transient volatile StackedPathArguments pathArguments;
private transient volatile StackedReversePathArguments reversePathArguments;
- StackedYangInstanceIdentifier(final YangInstanceIdentifier parent, final PathArgument pathArgument,
- final int hash) {
- super(hash);
+ StackedYangInstanceIdentifier(final YangInstanceIdentifier parent, final PathArgument pathArgument) {
this.parent = requireNonNull(parent);
this.pathArgument = requireNonNull(pathArgument);
}
current = stacked.getParent();
} while (current.tryPathArguments() == null);
- ret = new StackedPathArguments(current, Lists.reverse(stack));
- pathArguments = ret;
+ pathArguments = ret = new StackedPathArguments(current, Lists.reverse(stack));
}
return ret;
return YangInstanceIdentifier.create(Iterables.skip(getPathArguments(), skipFromRoot));
}
+ @Override
+ int computeHashCode() {
+ return HashCodeBuilder.nextHashCode(parent.hashCode(), pathArgument);
+ }
+
@Override
boolean pathArgumentsEqual(final YangInstanceIdentifier other) {
if (other instanceof StackedYangInstanceIdentifier) {
if (parent instanceof FixedYangInstanceIdentifier) {
p = (FixedYangInstanceIdentifier) parent;
} else {
- p = FixedYangInstanceIdentifier.create(parent.getPathArguments(), parent.hashCode());
+ p = FixedYangInstanceIdentifier.of(parent.getPathArguments());
}
outputStream.writeObject(p);
}
import org.opendaylight.yangtools.concepts.HierarchicalIdentifier;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.concepts.Mutable;
-import org.opendaylight.yangtools.util.HashCodeBuilder;
import org.opendaylight.yangtools.util.ImmutableOffsetMap;
import org.opendaylight.yangtools.util.SingletonSet;
import org.opendaylight.yangtools.yang.common.QName;
*
* @see <a href="http://tools.ietf.org/html/rfc6020#section-9.13">RFC6020</a>
*/
-// FIXME: 7.0.0: this concept needs to be moved to yang-common, as parser components need the ability to refer
-// to data nodes -- most notably XPath expressions and {@code default} statement arguments need to be able
-// to represent these.
+// FIXME: sealed once we have JDK17+
public abstract class YangInstanceIdentifier implements HierarchicalIdentifier<YangInstanceIdentifier> {
private static final long serialVersionUID = 4L;
private static final VarHandle TO_STRING_CACHE;
+ private static final VarHandle HASH;
static {
+ final var lookup = MethodHandles.lookup();
try {
- TO_STRING_CACHE = MethodHandles.lookup().findVarHandle(YangInstanceIdentifier.class, "toStringCache",
- String.class);
+ HASH = lookup.findVarHandle(YangInstanceIdentifier.class, "hash", int.class);
+ TO_STRING_CACHE = lookup.findVarHandle(YangInstanceIdentifier.class, "toStringCache", String.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new ExceptionInInitializerError(e);
}
}
-
- private final int hash;
+ @SuppressWarnings("unused")
+ private int hash;
@SuppressWarnings("unused")
private transient String toStringCache = null;
- // Package-private to prevent outside subclassing
- YangInstanceIdentifier(final int hash) {
- this.hash = hash;
+ YangInstanceIdentifier() {
+ // Package-private to prevent outside subclassing
}
/**
abstract @NonNull YangInstanceIdentifier createRelativeIdentifier(int skipFromRoot);
- abstract @Nullable Collection<PathArgument> tryPathArguments();
+ abstract @Nullable List<PathArgument> tryPathArguments();
- abstract @Nullable Collection<PathArgument> tryReversePathArguments();
+ abstract @Nullable List<PathArgument> tryReversePathArguments();
/**
* Check if this instance identifier has empty path arguments, e.g. it is
public abstract PathArgument getLastPathArgument();
public static @NonNull YangInstanceIdentifier create(final Iterable<? extends PathArgument> path) {
- if (Iterables.isEmpty(path)) {
- return empty();
- }
-
- final HashCodeBuilder<PathArgument> hash = new HashCodeBuilder<>();
- for (PathArgument a : path) {
- hash.addArgument(a);
- }
-
- return FixedYangInstanceIdentifier.create(path, hash.build());
+ return Iterables.isEmpty(path) ? empty() : new FixedYangInstanceIdentifier(ImmutableList.copyOf(path));
}
public static @NonNull YangInstanceIdentifier create(final PathArgument pathArgument) {
- return new FixedYangInstanceIdentifier(ImmutableList.of(pathArgument),
- HashCodeBuilder.nextHashCode(1, pathArgument));
+ return new FixedYangInstanceIdentifier(ImmutableList.of(pathArgument));
}
public static @NonNull YangInstanceIdentifier create(final PathArgument... path) {
}
boolean pathArgumentsEqual(final YangInstanceIdentifier other) {
- return Iterables.elementsEqual(getPathArguments(), other.getPathArguments());
+ return getPathArguments().equals(other.getPathArguments());
}
@Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof YangInstanceIdentifier)) {
- return false;
- }
- YangInstanceIdentifier other = (YangInstanceIdentifier) obj;
- if (this.hashCode() != obj.hashCode()) {
- return false;
- }
-
- return pathArgumentsEqual(other);
+ public final boolean equals(final Object obj) {
+ return this == obj || obj instanceof YangInstanceIdentifier && pathArgumentsEqual((YangInstanceIdentifier) obj);
}
/**
* @return Instance Identifier with additional path argument added to the end.
*/
public final @NonNull YangInstanceIdentifier node(final PathArgument arg) {
- return new StackedYangInstanceIdentifier(this, arg, HashCodeBuilder.nextHashCode(hash, arg));
+ return new StackedYangInstanceIdentifier(this, arg);
}
/**
* Used lists, maps are immutable. Path Arguments (elements) are also
* immutable, since the PathArgument contract requires immutability.
*/
- return hash;
+ final int local = (int) HASH.getAcquire(this);
+ return local != 0 ? local : loadHashCode();
}
private static int hashCode(final Object value) {
return Objects.hashCode(value);
}
+ private int loadHashCode() {
+ final int computed = computeHashCode();
+ HASH.setRelease(this, computed);
+ return computed;
+ }
+
+ abstract int computeHashCode();
+
final Object writeReplace() {
return new YIDv1(this);
}
* @return new builder for InstanceIdentifier with path arguments copied from original instance identifier.
*/
public static @NonNull InstanceIdentifierBuilder builder(final YangInstanceIdentifier origin) {
- return new YangInstanceIdentifierBuilder(origin.getPathArguments(), origin.hashCode());
+ return new YangInstanceIdentifierBuilder(origin.getPathArguments());
}
/**
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.util.HashCodeBuilder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
final class YangInstanceIdentifierBuilder implements InstanceIdentifierBuilder {
- private final HashCodeBuilder<PathArgument> hash;
private final List<PathArgument> path;
YangInstanceIdentifierBuilder() {
- this.hash = new HashCodeBuilder<>();
- this.path = new ArrayList<>();
+ path = new ArrayList<>();
}
- YangInstanceIdentifierBuilder(final List<PathArgument> prefix, final int hash) {
- this.path = new ArrayList<>(prefix);
- this.hash = new HashCodeBuilder<>(hash);
+ YangInstanceIdentifierBuilder(final List<PathArgument> prefix) {
+ path = new ArrayList<>(prefix);
}
private @NonNull InstanceIdentifierBuilder addArgument(final PathArgument arg) {
path.add(arg);
- hash.addArgument(arg);
return this;
}
@Override
public InstanceIdentifierBuilder append(final Collection<? extends PathArgument> args) {
path.addAll(args);
- args.forEach(hash::addArgument);
return this;
}
@Override
public YangInstanceIdentifier build() {
- return FixedYangInstanceIdentifier.create(path, hash.build());
+ return FixedYangInstanceIdentifier.of(path);
}
}