--- /dev/null
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.binding;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.util.HashCodeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+abstract sealed class AbstractInstanceIdentifierBuilder<T extends DataObject> implements InstanceIdentifierBuilder<T> {
+ static final class Regular<T extends DataObject> extends AbstractInstanceIdentifierBuilder<T> {
+ private @NonNull Class<T> type;
+
+ Regular(final Item<T> item) {
+ super(item, Identifiable.class.isAssignableFrom(item.getType()));
+ type = item.getType();
+ }
+
+ Regular(final InstanceIdentifier<T> identifier) {
+ super(identifier);
+ type = identifier.getTargetType();
+ }
+
+ private Regular(final Keyed<?, ?> prev, final Item<T> item, final boolean wildcard) {
+ super(prev, item, wildcard);
+ type = item.getType();
+ }
+
+ @Override
+ public InstanceIdentifier<T> build() {
+ return new InstanceIdentifier<>(type, pathArguments(), wildcard(), hashCode());
+ }
+
+ @Override
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ <X extends DataObject> Regular<X> append(final Item<X> item, final boolean isWildcard) {
+ appendItem(item, isWildcard);
+ type = (Class) item.getType();
+ return (Regular<X>) this;
+ }
+
+ @Override
+ <X extends DataObject & Identifiable<Y>, Y extends Identifier<X>> Keyed<X, Y> append(
+ final IdentifiableItem<X, Y> item) {
+ return new Keyed<>(this, item);
+ }
+ }
+
+ static final class Keyed<T extends DataObject & Identifiable<K>, K extends Identifier<T>>
+ extends AbstractInstanceIdentifierBuilder<T> implements InstanceIdentifier.KeyedBuilder<T, K> {
+ private @NonNull IdentifiableItem<T, K> lastItem;
+
+ Keyed(final IdentifiableItem<T, K> item) {
+ super(item, false);
+ lastItem = requireNonNull(item);
+ }
+
+ Keyed(final KeyedInstanceIdentifier<T, K> identifier) {
+ super(identifier);
+ lastItem = IdentifiableItem.of(identifier.getTargetType(), identifier.getKey());
+ }
+
+ private Keyed(final Regular<?> prev, final IdentifiableItem<T, K> item) {
+ super(prev, item, false);
+ lastItem = requireNonNull(item);
+ }
+
+ @Override
+ public KeyedInstanceIdentifier<T, K> build() {
+ return new KeyedInstanceIdentifier<>(lastItem.getType(), pathArguments(), wildcard(), hashCode(),
+ lastItem.getKey());
+ }
+
+ @Override
+ <X extends DataObject> @NonNull Regular<X> append(final Item<X> item, final boolean isWildcard) {
+ return new Regular<>(this, item, isWildcard);
+ }
+
+ @Override
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ <X extends DataObject & Identifiable<Y>, Y extends Identifier<X>> Keyed<X, Y> append(
+ final IdentifiableItem<X, Y> item) {
+ appendItem(item, false);
+ lastItem = (IdentifiableItem) item;
+ return (Keyed<X, Y>) this;
+ }
+ }
+
+ private final ImmutableList.Builder<PathArgument> pathBuilder;
+ private final HashCodeBuilder<PathArgument> hashBuilder;
+ private final Iterable<? extends PathArgument> basePath;
+
+ private boolean wildcard;
+
+ AbstractInstanceIdentifierBuilder(final AbstractInstanceIdentifierBuilder<?> prev, final PathArgument item,
+ final boolean isWildcard) {
+ pathBuilder = prev.pathBuilder;
+ hashBuilder = prev.hashBuilder;
+ basePath = prev.basePath;
+ wildcard = prev.wildcard;
+ appendItem(item, isWildcard);
+ }
+
+ AbstractInstanceIdentifierBuilder(final InstanceIdentifier<T> identifier) {
+ pathBuilder = ImmutableList.builder();
+ hashBuilder = new HashCodeBuilder<>(identifier.hashCode());
+ wildcard = identifier.isWildcarded();
+ basePath = identifier.pathArguments;
+ }
+
+ AbstractInstanceIdentifierBuilder(final PathArgument item, final boolean wildcard) {
+ pathBuilder = ImmutableList.builder();
+ hashBuilder = new HashCodeBuilder<>();
+ basePath = null;
+ hashBuilder.addArgument(item);
+ pathBuilder.add(item);
+ this.wildcard = wildcard;
+ }
+
+ final boolean wildcard() {
+ return wildcard;
+ }
+
+ @Override
+ public final <N extends DataObject & Augmentation<? super T>> Regular<N> augmentation(final Class<N> container) {
+ return append(Item.of(container), false);
+ }
+
+ @Override
+ public final <N extends ChildOf<? super T>> Regular<N> child(final Class<N> container) {
+ return append(Item.of(container), Identifiable.class.isAssignableFrom(container));
+ }
+
+ @Override
+ public final <C extends ChoiceIn<? super T> & DataObject, N extends ChildOf<? super C>> Regular<N> child(
+ final Class<C> caze, final Class<N> container) {
+ return append(Item.of(caze, container), Identifiable.class.isAssignableFrom(container));
+ }
+
+ @Override
+ public final <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> Keyed<N, K> child(
+ final Class<@NonNull N> listItem, final K listKey) {
+ return append(IdentifiableItem.of(listItem, listKey));
+ }
+
+ @Override
+ public final <C extends ChoiceIn<? super T> & DataObject, K extends Identifier<N>,
+ N extends Identifiable<K> & ChildOf<? super C>> Keyed<N, K> child(final Class<C> caze,
+ final Class<N> listItem, final K listKey) {
+ return append(IdentifiableItem.of(caze, listItem, listKey));
+ }
+
+ final Iterable<PathArgument> pathArguments() {
+ final var args = pathBuilder.build();
+ return basePath == null ? args : Iterables.concat(basePath, args);
+ }
+
+ final void appendItem(final PathArgument item, final boolean isWildcard) {
+ hashBuilder.addArgument(item);
+ pathBuilder.add(item);
+ wildcard |= isWildcard;
+ }
+
+ abstract <X extends DataObject> @NonNull Regular<X> append(Item<X> item, boolean isWildcard);
+
+ abstract <X extends DataObject & Identifiable<Y>, Y extends Identifier<X>>
+ @NonNull Keyed<X, Y> append(IdentifiableItem<X, Y> item);
+
+ @Override
+ public final int hashCode() {
+ return hashBuilder.build();
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ return this == obj || obj instanceof AbstractInstanceIdentifierBuilder<?> other
+ && wildcard == other.wildcard && hashCode() == other.hashCode()
+ && Iterables.elementsEqual(pathArguments(), other.pathArguments());
+ }
+}
InstanceIdentifier(final Class<T> type, final Iterable<PathArgument> pathArguments, final boolean wildcarded,
final int hash) {
this.pathArguments = requireNonNull(pathArguments);
- this.targetType = requireNonNull(type);
+ targetType = requireNonNull(type);
this.wildcarded = wildcarded;
this.hash = hash;
}
public final boolean contains(final InstanceIdentifier<? extends DataObject> other) {
requireNonNull(other, "other should not be null");
- final Iterator<?> lit = pathArguments.iterator();
final Iterator<?> oit = other.pathArguments.iterator();
- while (lit.hasNext()) {
+ for (PathArgument pathArgument : pathArguments) {
if (!oit.hasNext()) {
return false;
}
- if (!lit.next().equals(oit.next())) {
+ if (!pathArgument.equals(oit.next())) {
return false;
}
}
public final boolean containsWildcarded(final InstanceIdentifier<?> other) {
requireNonNull(other, "other should not be null");
- final Iterator<PathArgument> lit = pathArguments.iterator();
final Iterator<PathArgument> oit = other.pathArguments.iterator();
- while (lit.hasNext()) {
+ for (PathArgument la : pathArguments) {
if (!oit.hasNext()) {
return false;
}
- final PathArgument la = lit.next();
final PathArgument oa = oit.next();
if (!la.getType().equals(oa.getType())) {
return childIdentifier(Item.of(container));
}
+ @Serial
+ private Object writeReplace() throws ObjectStreamException {
+ return new InstanceIdentifierV3<>(this);
+ }
+
/**
* Create a builder rooted at this key.
*
*/
// FIXME: rename this method to 'toBuilder()'
public @NonNull InstanceIdentifierBuilder<T> builder() {
- return new InstanceIdentifierBuilderImpl<>(Item.of(targetType), pathArguments, hash, wildcarded);
+ return new AbstractInstanceIdentifierBuilder.Regular<>(this);
}
/**
*/
public static <T extends ChildOf<? extends DataRoot>> @NonNull InstanceIdentifierBuilder<T> builder(
final Class<T> container) {
- return new InstanceIdentifierBuilderImpl<>(Item.of(container));
+ return new AbstractInstanceIdentifierBuilder.Regular<>(Item.of(container));
}
/**
*/
public static <C extends ChoiceIn<? extends DataRoot> & DataObject, T extends ChildOf<? super C>>
@NonNull InstanceIdentifierBuilder<T> builder(final Class<C> caze, final Class<T> container) {
- return new InstanceIdentifierBuilderImpl<>(Item.of(caze, container));
+ return new AbstractInstanceIdentifierBuilder.Regular<>(Item.of(caze, container));
}
/**
* @throws NullPointerException if any argument is null
*/
public static <N extends Identifiable<K> & ChildOf<? extends DataRoot>,
- K extends Identifier<N>> @NonNull InstanceIdentifierBuilder<N> builder(final Class<N> listItem,
+ K extends Identifier<N>> @NonNull KeyedBuilder<N, K> builder(final Class<N> listItem,
final K listKey) {
- return new InstanceIdentifierBuilderImpl<>(IdentifiableItem.of(listItem, listKey));
+ return new AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(listItem, listKey));
}
/**
*/
public static <C extends ChoiceIn<? extends DataRoot> & DataObject,
N extends Identifiable<K> & ChildOf<? super C>, K extends Identifier<N>>
- @NonNull InstanceIdentifierBuilder<N> builder(final Class<C> caze, final Class<N> listItem,
+ @NonNull KeyedBuilder<N, K> builder(final Class<C> caze, final Class<N> listItem,
final K listKey) {
- return new InstanceIdentifierBuilderImpl<>(IdentifiableItem.of(caze, listItem, listKey));
+ return new AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(caze, listItem, listKey));
}
public static <R extends DataRoot & DataObject, T extends ChildOf<? super R>>
@NonNull InstanceIdentifierBuilder<T> builderOfInherited(final Class<R> root, final Class<T> container) {
// FIXME: we are losing root identity, hence namespaces may not work correctly
- return new InstanceIdentifierBuilderImpl<>(Item.of(container));
+ return new AbstractInstanceIdentifierBuilder.Regular<>(Item.of(container));
}
public static <R extends DataRoot & DataObject, C extends ChoiceIn<? super R> & DataObject,
@NonNull InstanceIdentifierBuilder<T> builderOfInherited(final Class<R> root,
final Class<C> caze, final Class<T> container) {
// FIXME: we are losing root identity, hence namespaces may not work correctly
- return new InstanceIdentifierBuilderImpl<>(Item.of(caze, container));
+ return new AbstractInstanceIdentifierBuilder.Regular<>(Item.of(caze, container));
}
public static <R extends DataRoot & DataObject, N extends Identifiable<K> & ChildOf<? super R>,
K extends Identifier<N>>
- @NonNull InstanceIdentifierBuilder<N> builderOfInherited(final Class<R> root,
+ @NonNull KeyedBuilder<N, K> builderOfInherited(final Class<R> root,
final Class<N> listItem, final K listKey) {
// FIXME: we are losing root identity, hence namespaces may not work correctly
- return new InstanceIdentifierBuilderImpl<>(IdentifiableItem.of(listItem, listKey));
+ return new AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(listItem, listKey));
}
public static <R extends DataRoot & DataObject, C extends ChoiceIn<? super R> & DataObject,
N extends Identifiable<K> & ChildOf<? super C>, K extends Identifier<N>>
- @NonNull InstanceIdentifierBuilder<N> builderOfInherited(final Class<R> root,
+ @NonNull KeyedBuilder<N, K> builderOfInherited(final Class<R> root,
final Class<C> caze, final Class<N> listItem, final K listKey) {
// FIXME: we are losing root identity, hence namespaces may not work correctly
- return new InstanceIdentifierBuilderImpl<>(IdentifiableItem.of(caze, listItem, listKey));
+ return new AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(caze, listItem, listKey));
}
/**
}
// FIXME: rename to 'Builder'
- // FIXME: introduce KeyedBuilder with specialized build() method
public interface InstanceIdentifierBuilder<T extends DataObject> {
/**
* Append the specified container as a child of the current InstanceIdentifier referenced by the builder. This
* @throws NullPointerException if any argument is null
*/
<N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>>
- @NonNull InstanceIdentifierBuilder<N> child(Class<@NonNull N> listItem, K listKey);
+ @NonNull KeyedBuilder<N, K> child(Class<@NonNull N> listItem, K listKey);
/**
* Append the specified listItem as a child of the current InstanceIdentifier referenced by the builder. This
* @throws NullPointerException if any argument is null
*/
<C extends ChoiceIn<? super T> & DataObject, K extends Identifier<N>,
- N extends Identifiable<K> & ChildOf<? super C>> @NonNull InstanceIdentifierBuilder<N> child(
+ N extends Identifiable<K> & ChildOf<? super C>> @NonNull KeyedBuilder<N, K> child(
Class<C> caze, Class<N> listItem, K listKey);
/**
@NonNull InstanceIdentifier<T> build();
}
- @Serial
- private Object writeReplace() throws ObjectStreamException {
- return new InstanceIdentifierV3<>(this);
+ public interface KeyedBuilder<T extends DataObject & Identifiable<K>, K extends Identifier<T>>
+ extends InstanceIdentifierBuilder<T> {
+ /**
+ * Build the instance identifier.
+ *
+ * @return Resulting instance identifier.
+ */
+ @Override
+ @NonNull KeyedInstanceIdentifier<T, K> build();
}
}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.binding;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import java.util.Objects;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.util.HashCodeBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-
-final class InstanceIdentifierBuilderImpl<T extends DataObject> implements InstanceIdentifierBuilder<T> {
- private final ImmutableList.Builder<PathArgument> pathBuilder = ImmutableList.builder();
- private final HashCodeBuilder<PathArgument> hashBuilder;
- private final Iterable<? extends PathArgument> basePath;
- private boolean wildcard;
- private PathArgument arg;
-
- private InstanceIdentifierBuilderImpl(final PathArgument item) {
- hashBuilder = new HashCodeBuilder<>();
- basePath = null;
- arg = requireNonNull(item);
- hashBuilder.addArgument(item);
- pathBuilder.add(item);
- wildcard = false;
- }
-
- InstanceIdentifierBuilderImpl(final IdentifiableItem<? super T, ?> item) {
- this((PathArgument) item);
- }
-
- InstanceIdentifierBuilderImpl(final Item<T> item) {
- this((PathArgument) item);
- if (Identifiable.class.isAssignableFrom(item.getType())) {
- wildcard = true;
- }
- }
-
- InstanceIdentifierBuilderImpl(final PathArgument item, final Iterable<? extends PathArgument> pathArguments,
- final int hash, final boolean wildcard) {
- hashBuilder = new HashCodeBuilder<>(hash);
- basePath = pathArguments;
- this.wildcard = wildcard;
- arg = item;
- }
-
- @Override
- public int hashCode() {
- return hashBuilder.build();
- }
-
- @Override
- public boolean equals(final Object obj) {
- return this == obj || obj instanceof InstanceIdentifierBuilderImpl<?> other
- && wildcard == other.wildcard && Objects.equals(basePath, other.basePath) && Objects.equals(arg, other.arg)
- && hashBuilder.build() == other.hashBuilder.build();
- }
-
- @Override
- public <N extends ChildOf<? super T>> InstanceIdentifierBuilderImpl<N> child(final Class<N> container) {
- return addNode(container);
- }
-
- @Override
- public <C extends ChoiceIn<? super T> & DataObject, N extends ChildOf<? super C>> InstanceIdentifierBuilder<N>
- child(final Class<C> caze, final Class<N> container) {
- return addWildNode(Item.of(caze, container));
- }
-
- @Override
- public <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilderImpl<N>
- child(final Class<@NonNull N> listItem, final K listKey) {
- return addNode(IdentifiableItem.of(listItem, listKey));
- }
-
- @Override
- public <C extends ChoiceIn<? super T> & DataObject, K extends Identifier<N>,
- N extends Identifiable<K> & ChildOf<? super C>> InstanceIdentifierBuilder<N> child(final Class<C> caze,
- final Class<N> listItem, final K listKey) {
- return addNode(IdentifiableItem.of(caze, listItem, listKey));
- }
-
- /**
- * Build an identifier which refers to a specific augmentation of the current InstanceIdentifier referenced by
- * the builder.
- *
- * @param container Augmentation to be added
- * @param <N> Augmentation type
- * @return This builder
- */
- @Override
- public <N extends DataObject & Augmentation<? super T>> InstanceIdentifierBuilderImpl<N> augmentation(
- final Class<N> container) {
- return addNode(container);
- }
-
- @Override
- public InstanceIdentifier<T> build() {
- Preconditions.checkState(arg != null, "No path arguments present");
-
- final Iterable<PathArgument> pathArguments;
- if (basePath == null) {
- pathArguments = pathBuilder.build();
- } else {
- pathArguments = Iterables.concat(basePath, pathBuilder.build());
- }
-
- return InstanceIdentifier.trustedCreate(arg, pathArguments, hashBuilder.build(), wildcard);
- }
-
- private <N extends DataObject> @NonNull InstanceIdentifierBuilderImpl<N> addWildNode(final PathArgument newArg) {
- if (Identifiable.class.isAssignableFrom(newArg.getType())) {
- wildcard = true;
- }
- return addNode(newArg);
- }
-
- @SuppressWarnings("unchecked")
- private <N extends DataObject> @NonNull InstanceIdentifierBuilderImpl<N> addNode(final PathArgument newArg) {
- arg = newArg;
- hashBuilder.addArgument(newArg);
- pathBuilder.add(newArg);
- return (InstanceIdentifierBuilderImpl<N>) this;
- }
-
- private <N extends DataObject> @NonNull InstanceIdentifierBuilderImpl<N> addNode(final Class<N> container) {
- return addWildNode(Item.of(container));
- }
-}
}
@Override
- public final InstanceIdentifierBuilder<T> builder() {
- return new InstanceIdentifierBuilderImpl<>(IdentifiableItem.of(getTargetType(), key), pathArguments,
- hashCode(), isWildcarded());
+ public final KeyedBuilder<T, K> builder() {
+ return new AbstractInstanceIdentifierBuilder.Keyed<>(this);
}
@Override
builder4.child(Node.class, new NodeKey(20));
assertFalse(builder3.equals(builder4));
assertFalse(builder4.equals(builder3));
-
- InstanceIdentifierBuilder<Nodes> iib1 = new InstanceIdentifierBuilderImpl<>(null, null, 31, true);
- InstanceIdentifierBuilder<Nodes> iib2 = new InstanceIdentifierBuilderImpl<>(null, null, 31, false);
- InstanceIdentifierBuilder<Nodes> iib3 = new InstanceIdentifierBuilderImpl<>(null, null, 31, true);
- assertFalse(iib1.equals(iib2));
- assertFalse(iib2.equals(iib1));
- assertTrue(iib1.equals(iib3));
- assertTrue(iib3.equals(iib1));
}
@Test