import org.opendaylight.yangtools.binding.runtime.api.ContainerRuntimeType;
import org.opendaylight.yangtools.binding.runtime.api.ListRuntimeType;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
private static @NonNull DataObjectStep<?> createItem(final @Nullable Class<? extends DataObject> caseClass,
final Class<?> childClass, final EffectiveStatement<?, ?> childSchema) {
return caseClass != null && childSchema instanceof AddedByUsesAware aware && aware.isAddedByUses()
- ? InstanceIdentifier.createStep((Class) caseClass, (Class) childClass)
- : InstanceIdentifier.createStep((Class) childClass);
+ ? DataObjectStep.of((Class) caseClass, (Class) childClass) : DataObjectStep.of((Class) childClass);
}
// FIXME: MDSAL-780: these methods perform analytics using java.lang.reflect to acquire the basic shape of the
import org.opendaylight.yangtools.binding.DataObject;
import org.opendaylight.yangtools.binding.DataObjectStep;
import org.opendaylight.yangtools.binding.runtime.api.CompositeRuntimeType;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
abstract sealed class DataObjectCodecPrototype<T extends CompositeRuntimeType> extends CommonDataObjectCodecPrototype<T>
DataObjectCodecPrototype(final Class<?> cls, final NodeIdentifier yangArg, final T type,
final CodecContextFactory factory) {
- this(InstanceIdentifier.createStep(cls.asSubclass(DataObject.class)), yangArg, type, factory);
+ this(DataObjectStep.of(cls.asSubclass(DataObject.class)), yangArg, type, factory);
}
DataObjectCodecPrototype(final DataObjectStep<?> bindingArg, final NodeIdentifier yangArg, final T type,
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.impl.DataObjectIdentifierImpl;
import org.opendaylight.yangtools.binding.impl.DataObjectIdentifierWithKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.KeyedBuilder;
/**
* A {@link DataObjectReference} matching at most one {@link DataObject}, consistent with YANG
KeyStep<K, T> lastStep();
@Override
- KeyedBuilder<T, K> toBuilder();
+ Builder.WithKey<T, K> toBuilder();
}
static @NonNull DataObjectIdentifier<?> ofUnsafeSteps(
static @NonNull DataObjectIdentifier<?> ofUnsafeSteps(
final ImmutableList<? extends @NonNull ExactDataObjectStep<?>> steps) {
- // FIXME: YANGTOOLS-1577: DataObjectReferenceImpl.ofUnsafeSteps() instead
return DataObjectIdentifierImpl.ofUnsafeSteps(steps);
}
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.impl.AbstractDataObjectReference;
+import org.opendaylight.yangtools.binding.impl.AbstractDataObjectReferenceBuilder;
+import org.opendaylight.yangtools.binding.impl.DataObjectIdentifierImpl;
+import org.opendaylight.yangtools.binding.impl.DataObjectReferenceBuilderWithKey;
import org.opendaylight.yangtools.binding.impl.DataObjectReferenceImpl;
import org.opendaylight.yangtools.binding.impl.DataObjectReferenceWithKey;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Builder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.KeyedBuilder;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
//* </ul>
public sealed interface DataObjectReference<T extends DataObject> extends Immutable, Serializable
permits DataObjectIdentifier, DataObjectReference.WithKey, AbstractDataObjectReference {
+ /**
+ * A builder of {@link DataObjectReference} objects.
+ *
+ * @param <T> type of {@link DataObject} held in the last step.
+ */
+ sealed interface Builder<T extends DataObject> permits Builder.WithKey, AbstractDataObjectReferenceBuilder {
+ /**
+ * A builder of {@link DataObjectReference.WithKey} objects.
+ *
+ * @param <T> type of {@link KeyAware} {@link DataObject} held in the last step.
+ * @param <K> {@link Key} type
+ */
+ sealed interface WithKey<T extends KeyAware<K> & DataObject, K extends Key<T>> extends Builder<T>
+ permits DataObjectReferenceBuilderWithKey, KeyedBuilder {
+ @Override
+ DataObjectReference.WithKey<T, K> build();
+ }
+
+ /**
+ * Update this builder to build a reference to a specific augmentation of the data object this builder currently
+ * points to.
+ *
+ * @param <N> augmentation type
+ * @param augmentation augmentation class
+ * @return this builder
+ * @throws NullPointerException if {@code augmentation} is {@code null}
+ */
+ <N extends DataObject & Augmentation<? super T>> @NonNull Builder<N> augmentation(
+ @NonNull Class<N> augmentation);
+
+ /**
+ * Append the specified container as a child of the data object this build currently references. This method
+ * should be used when you want to build an instance identifier by appending top-level elements.
+ *
+ * @param <N> Container type
+ * @param container Container to append
+ * @return this builder
+ * @throws NullPointerException if {@code container} is null
+ */
+ <N extends ChildOf<? super T>> @NonNull Builder<N> child(@NonNull Class<N> container);
+
+ /**
+ * Append the specified container as a child of the data object this build currently references. This method
+ * should be used when you want to build an reference by appending a container node to the identifier and the
+ * {@code container} is defined in a {@code grouping} used in a {@code case} statement.
+ *
+ * @param <C> Case type
+ * @param <N> Container type
+ * @param caze Choice case class
+ * @param container Container to append
+ * @return this builder
+ * @throws NullPointerException if {@code container} is null
+ */
+ <C extends ChoiceIn<? super T> & DataObject, N extends ChildOf<? super C>> @NonNull Builder<N> child(
+ Class<C> caze, @NonNull Class<N> container);
+
+ /**
+ * Append the specified listItem as a child of the data object this build currently references. This method
+ * should be used when you want to build a reference by appending a specific list element to the identifier.
+ *
+ * @param <N> List type
+ * @param <K> Key type
+ * @param listItem List to append
+ * @param listKey List key
+ * @return this builder
+ * @throws NullPointerException if any argument is null
+ */
+ <N extends KeyAware<K> & ChildOf<? super T>, K extends Key<N>> @NonNull WithKey<N, K> child(
+ @NonNull Class<@NonNull N> listItem, @NonNull K listKey);
+
+ /**
+ * Append the specified listItem as a child of the data object this build currently references. This
+ * method should be used when you want to build a reference by appending a specific list element to the
+ * identifier and the {@code list} is defined in a {@code grouping} used in a {@code case} statement.
+ *
+ * @param <C> Case type
+ * @param <N> List type
+ * @param <K> Key type
+ * @param caze Choice case class
+ * @param listItem List to append
+ * @param listKey List key
+ * @return this builder
+ * @throws NullPointerException if any argument is null
+ */
+ <C extends ChoiceIn<? super T> & DataObject, K extends Key<N>, N extends KeyAware<K> & ChildOf<? super C>>
+ @NonNull WithKey<N, K> child(@NonNull Class<C> caze, @NonNull Class<N> listItem, @NonNull K listKey);
+
+ /**
+ * Build the data object reference.
+ *
+ * @return resulting {@link DataObjectReference}.
+ */
+ @NonNull DataObjectReference<T> build();
+ }
+
/**
* A {@link DataObjectReference} pointing to a {@link KeyAware} {@link DataObject}, typically a map entry.
*
KeyStep<K, T> lastStep();
@Override
- KeyedBuilder<T, K> toBuilder();
+ Builder.WithKey<T, K> toBuilder();
@Override
default K key() {
return ofUnsafeSteps(ImmutableList.copyOf(steps));
}
+ @SuppressWarnings("unchecked")
static @NonNull DataObjectReference<?> ofUnsafeSteps(
final ImmutableList<? extends @NonNull DataObjectStep<?>> steps) {
+ if (steps.stream().allMatch(ExactDataObjectStep.class::isInstance)) {
+ return DataObjectIdentifierImpl.ofUnsafeSteps(
+ (ImmutableList<? extends @NonNull ExactDataObjectStep<?>>) steps);
+ }
return DataObjectReferenceImpl.ofUnsafeSteps(steps);
}
*/
public sealed interface DataObjectStep<T extends DataObject> extends Comparable<DataObjectStep<?>>, Serializable
permits ExactDataObjectStep, InexactDataObjectStep {
+
+ static <T extends DataObject> @NonNull DataObjectStep<T> of(final @NonNull Class<T> type) {
+ return of(null, type);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ static <T extends DataObject, C extends ChoiceIn<?> & DataObject> @NonNull DataObjectStep<T> of(
+ final @Nullable Class<C> caze, final @NonNull Class<T> type) {
+ return KeyAware.class.isAssignableFrom(type) ? new KeylessStep(type, caze) : new NodeStep<>(type, caze);
+ }
+
/**
* Return the data object type backing this PathArgument.
*
}
@NonNullByDefault
- public static final <T> Iterable<? extends T> concat(final Iterable<? extends T> others, final T last) {
+ protected static final <T> Iterable<? extends T> concat(final Iterable<? extends T> others, final T last) {
return new AppendIterable<>(others, last);
}
--- /dev/null
+/*
+ * Copyright (c) 2024 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.binding.impl;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.binding.Augmentation;
+import org.opendaylight.yangtools.binding.ChildOf;
+import org.opendaylight.yangtools.binding.ChoiceIn;
+import org.opendaylight.yangtools.binding.DataObject;
+import org.opendaylight.yangtools.binding.DataObjectReference;
+import org.opendaylight.yangtools.binding.DataObjectReference.Builder;
+import org.opendaylight.yangtools.binding.DataObjectStep;
+import org.opendaylight.yangtools.binding.ExactDataObjectStep;
+import org.opendaylight.yangtools.binding.Key;
+import org.opendaylight.yangtools.binding.KeyAware;
+import org.opendaylight.yangtools.binding.KeyStep;
+import org.opendaylight.yangtools.binding.NodeStep;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Base implementation of {@link Builder}.
+ */
+public abstract sealed class AbstractDataObjectReferenceBuilder<T extends DataObject> implements Builder<T>
+ permits DataObjectReferenceBuilder, DataObjectReferenceBuilderWithKey, InstanceIdentifier.Builder {
+ private final ArrayList<@NonNull DataObjectStep<?>> pathBuilder;
+ private final Iterable<? extends @NonNull DataObjectStep<?>> basePath;
+
+ private boolean wildcard;
+
+ protected AbstractDataObjectReferenceBuilder(final AbstractDataObjectReferenceBuilder<?> prev,
+ final DataObjectStep<?> item) {
+ pathBuilder = prev.pathBuilder;
+ basePath = prev.basePath;
+ wildcard = prev.wildcard;
+ appendItem(item);
+ }
+
+ protected AbstractDataObjectReferenceBuilder(final DataObjectReference<T> base) {
+ pathBuilder = new ArrayList<>(4);
+ wildcard = base.isWildcarded();
+ basePath = base.steps();
+ }
+
+ protected AbstractDataObjectReferenceBuilder(final DataObjectStep<?> item, final boolean wildcard) {
+ pathBuilder = new ArrayList<>(4);
+ basePath = null;
+ this.wildcard = wildcard;
+ appendItem(item);
+ }
+
+ @Override
+ public <N extends DataObject & Augmentation<? super T>> Builder<N> augmentation(final Class<N> augmentation) {
+ return append(new NodeStep<>(augmentation));
+ }
+
+ @Override
+ public <N extends ChildOf<? super T>> Builder<N> child(final Class<N> container) {
+ return append(DataObjectStep.of(container));
+ }
+
+ @Override
+ public <C extends ChoiceIn<? super T> & DataObject, N extends ChildOf<? super C>> Builder<N> child(
+ final Class<C> caze, final Class<N> container) {
+ return append(DataObjectStep.of(caze, container));
+ }
+
+ @Override
+ public <N extends KeyAware<K> & ChildOf<? super T>, K extends Key<N>> WithKey<N, K> child(final Class<N> listItem,
+ final K listKey) {
+ return append(new KeyStep<>(listItem, listKey));
+ }
+
+ @Override
+ public <C extends ChoiceIn<? super T> & DataObject, K extends Key<N>, N extends KeyAware<K> & ChildOf<? super C>>
+ WithKey<N, K> child(final Class<C> caze, final Class<N> listItem, final K listKey) {
+ return append(new KeyStep<>(listItem, requireNonNull(caze), listKey));
+ }
+
+ @Override
+ public abstract DataObjectReference<T> build();
+
+ protected abstract <X extends DataObject> @NonNull Builder<X> append(@NonNull DataObjectStep<X> step);
+
+ protected abstract <X extends DataObject & KeyAware<Y>, Y extends Key<X>> @NonNull WithKey<X, Y> append(
+ @NonNull KeyStep<Y, X> step);
+
+ protected final boolean wildcard() {
+ return wildcard;
+ }
+
+ protected final void appendItem(final DataObjectStep<?> item) {
+ pathBuilder.add(requireNonNull(item));
+ if (!(item instanceof ExactDataObjectStep)) {
+ wildcard = true;
+ }
+ }
+
+ protected final @NonNull Iterable<? extends @NonNull DataObjectStep<?>> buildSteps() {
+ final var prefix = basePath;
+ if (prefix == null) {
+ return pathBuilder.isEmpty() ? ImmutableList.of() : ImmutableList.copyOf(pathBuilder);
+ }
+
+ return switch (pathBuilder.size()) {
+ case 0 -> prefix;
+ case 1 -> new AppendIterable<>(prefix, pathBuilder.getFirst());
+ default -> ImmutableList.<DataObjectStep<?>>builder().addAll(prefix).addAll(pathBuilder).build();
+ };
+ }
+}
*/
package org.opendaylight.yangtools.binding.impl;
+import static com.google.common.base.Verify.verify;
+
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.io.ObjectInputStream;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.DataObject;
import org.opendaylight.yangtools.binding.DataObjectIdentifier;
+import org.opendaylight.yangtools.binding.DataObjectStep;
import org.opendaylight.yangtools.binding.ExactDataObjectStep;
+import org.opendaylight.yangtools.binding.KeyStep;
-// FIXME: YANGTOOLS-1577: non-abstract
-public abstract sealed class DataObjectIdentifierImpl<T extends DataObject>
+public sealed class DataObjectIdentifierImpl<T extends DataObject>
extends AbstractDataObjectReference<T, ExactDataObjectStep<?>> implements DataObjectIdentifier<T>
permits DataObjectIdentifierWithKey {
@java.io.Serial
super(steps);
}
+ DataObjectIdentifierImpl(final Void unused, final Iterable<? extends @NonNull DataObjectStep<?>> steps) {
+ this(verifySteps(steps));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static @NonNull Iterable<? extends @NonNull ExactDataObjectStep<?>> verifySteps(
+ final Iterable<? extends @NonNull DataObjectStep<?>> steps) {
+ steps.forEach(step -> verify(step instanceof ExactDataObjectStep, "%s is not an exact step", step));
+ return (Iterable<? extends @NonNull ExactDataObjectStep<?>>) steps;
+ }
+
public static final @NonNull DataObjectIdentifierImpl<?> ofUnsafeSteps(
final ImmutableList<? extends @NonNull ExactDataObjectStep<?>> steps) {
- // FIXME: YANGTOOLS-1577: implement this
- throw new UnsupportedOperationException();
+ final var last = steps.getLast();
+ return last instanceof KeyStep ? new DataObjectIdentifierWithKey<>(steps)
+ : new DataObjectIdentifierImpl<>(steps);
+ }
+
+ @Override
+ public AbstractDataObjectReferenceBuilder<T> toBuilder() {
+ return new DataObjectReferenceBuilder<>(this);
}
@Override
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.DataObject;
import org.opendaylight.yangtools.binding.DataObjectIdentifier.WithKey;
+import org.opendaylight.yangtools.binding.DataObjectStep;
import org.opendaylight.yangtools.binding.ExactDataObjectStep;
import org.opendaylight.yangtools.binding.Key;
import org.opendaylight.yangtools.binding.KeyAware;
import org.opendaylight.yangtools.binding.KeyStep;
-// FIXME: YANGTOOLS-1577: final
-public abstract non-sealed class DataObjectIdentifierWithKey<T extends KeyAware<K> & DataObject, K extends Key<T>>
+public final class DataObjectIdentifierWithKey<T extends KeyAware<K> & DataObject, K extends Key<T>>
extends DataObjectIdentifierImpl<T> implements WithKey<T, K> {
@java.io.Serial
private static final long serialVersionUID = 1L;
super(steps);
}
+ DataObjectIdentifierWithKey(final Void unused, final Iterable<? extends @NonNull DataObjectStep<?>> steps) {
+ super(unused, steps);
+ }
+
@Override
- public final KeyStep<K, T> lastStep() {
+ public KeyStep<K, T> lastStep() {
return getLast(steps());
}
+ @Override
+ public DataObjectReferenceBuilderWithKey<T, K> toBuilder() {
+ return new DataObjectReferenceBuilderWithKey<>(this);
+ }
+
@java.io.Serial
private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
throwNSE();
--- /dev/null
+/*
+ * Copyright (c) 2024 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.binding.impl;
+
+import org.opendaylight.yangtools.binding.DataObject;
+import org.opendaylight.yangtools.binding.DataObjectReference;
+import org.opendaylight.yangtools.binding.DataObjectStep;
+import org.opendaylight.yangtools.binding.Key;
+import org.opendaylight.yangtools.binding.KeyAware;
+import org.opendaylight.yangtools.binding.KeyStep;
+
+final class DataObjectReferenceBuilder<T extends DataObject> extends AbstractDataObjectReferenceBuilder<T> {
+ DataObjectReferenceBuilder(final AbstractDataObjectReferenceBuilder<?> prev, final DataObjectStep<?> item) {
+ super(prev, item);
+ }
+
+ DataObjectReferenceBuilder(final DataObjectReference<T> base) {
+ super(base);
+ }
+
+ DataObjectReferenceBuilder(final DataObjectStep<?> item, final boolean wildcard) {
+ super(item, wildcard);
+ }
+
+ @Override
+ public DataObjectReference<T> build() {
+ final var steps = buildSteps();
+ return wildcard() ? new DataObjectReferenceImpl<>(steps) : new DataObjectIdentifierImpl<>(null, steps);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected <X extends DataObject> DataObjectReferenceBuilder<X> append(final DataObjectStep<X> step) {
+ appendItem(step);
+ return (DataObjectReferenceBuilder<X>) this;
+ }
+
+ @Override
+ protected <X extends DataObject & KeyAware<Y>, Y extends Key<X>> DataObjectReferenceBuilderWithKey<X, Y> append(
+ final KeyStep<Y, X> step) {
+ return new DataObjectReferenceBuilderWithKey<>(this, step);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2024 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.binding.impl;
+
+import org.opendaylight.yangtools.binding.DataObject;
+import org.opendaylight.yangtools.binding.DataObjectReference;
+import org.opendaylight.yangtools.binding.DataObjectReference.Builder.WithKey;
+import org.opendaylight.yangtools.binding.DataObjectStep;
+import org.opendaylight.yangtools.binding.Key;
+import org.opendaylight.yangtools.binding.KeyAware;
+import org.opendaylight.yangtools.binding.KeyStep;
+
+public final class DataObjectReferenceBuilderWithKey<T extends KeyAware<K> & DataObject, K extends Key<T>>
+ extends AbstractDataObjectReferenceBuilder<T> implements WithKey<T, K> {
+ DataObjectReferenceBuilderWithKey(final DataObjectReferenceBuilder<?> prev, final DataObjectStep<?> item) {
+ super(prev, item);
+ }
+
+ DataObjectReferenceBuilderWithKey(final DataObjectReference.WithKey<T, K> base) {
+ super(base);
+ }
+
+ DataObjectReferenceBuilderWithKey(final KeyStep<K, T> item, final boolean wildcard) {
+ super(item, wildcard);
+ }
+
+ @Override
+ public DataObjectReference.WithKey<T, K> build() {
+ final var steps = buildSteps();
+ return wildcard() ? new DataObjectReferenceWithKey<>(steps) : new DataObjectIdentifierWithKey<>(null, steps);
+ }
+
+ @Override
+ protected <X extends DataObject> DataObjectReferenceBuilder<X> append(final DataObjectStep<X> step) {
+ return new DataObjectReferenceBuilder<>(this, step);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected <X extends DataObject & KeyAware<Y>, Y extends Key<X>> DataObjectReferenceBuilderWithKey<X, Y> append(
+ final KeyStep<Y, X> step) {
+ appendItem(step);
+ return (DataObjectReferenceBuilderWithKey<X, Y>) this;
+ }
+}
import java.io.ObjectStreamException;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.DataObject;
-import org.opendaylight.yangtools.binding.DataObjectReference;
import org.opendaylight.yangtools.binding.DataObjectStep;
-import org.opendaylight.yangtools.binding.ExactDataObjectStep;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.binding.KeyStep;
-// FIXME: YANGTOOLS-1577: non-abstract
-public abstract sealed class DataObjectReferenceImpl<T extends DataObject>
+public sealed class DataObjectReferenceImpl<T extends DataObject>
extends AbstractDataObjectReference<T, DataObjectStep<?>>
permits DataObjectReferenceWithKey {
@java.io.Serial
private static final long serialVersionUID = 1L;
- DataObjectReferenceImpl(final Iterable<? extends @NonNull ExactDataObjectStep<?>> steps) {
+ DataObjectReferenceImpl(final Iterable<? extends @NonNull DataObjectStep<?>> steps) {
super(steps);
}
- public static final @NonNull DataObjectReference<?> ofUnsafeSteps(
+ public static final @NonNull DataObjectReferenceImpl<?> ofUnsafeSteps(
final ImmutableList<? extends @NonNull DataObjectStep<?>> steps) {
- // FIXNE: YANGTOOLS-1577: dispatch to this class
- return InstanceIdentifier.unsafeOf(steps);
+ return steps.getLast() instanceof KeyStep ? new DataObjectReferenceWithKey<>(steps)
+ : new DataObjectReferenceImpl<>(steps);
+ }
+
+ @Override
+ public AbstractDataObjectReferenceBuilder<T> toBuilder() {
+ return new DataObjectReferenceBuilder<>(this);
}
@java.io.Serial
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.DataObject;
import org.opendaylight.yangtools.binding.DataObjectReference.WithKey;
-import org.opendaylight.yangtools.binding.ExactDataObjectStep;
+import org.opendaylight.yangtools.binding.DataObjectStep;
import org.opendaylight.yangtools.binding.Key;
import org.opendaylight.yangtools.binding.KeyAware;
import org.opendaylight.yangtools.binding.KeyStep;
-// FIXME: YANGTOOLS-1577: final
-public abstract non-sealed class DataObjectReferenceWithKey<T extends KeyAware<K> & DataObject, K extends Key<T>>
+public final class DataObjectReferenceWithKey<T extends KeyAware<K> & DataObject, K extends Key<T>>
extends DataObjectReferenceImpl<T> implements WithKey<T, K> {
@java.io.Serial
private static final long serialVersionUID = 1L;
- DataObjectReferenceWithKey(final Iterable<? extends @NonNull ExactDataObjectStep<?>> steps) {
+ DataObjectReferenceWithKey(final Iterable<? extends @NonNull DataObjectStep<?>> steps) {
super(steps);
}
@Override
- public final KeyStep<K, T> lastStep() {
+ public KeyStep<K, T> lastStep() {
return getLast(steps());
}
+ @Override
+ public DataObjectReferenceBuilderWithKey<T, K> toBuilder() {
+ return new DataObjectReferenceBuilderWithKey<>(this);
+ }
+
@java.io.Serial
private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
throwNSE();
@java.io.Serial
private Object readResolve() throws ObjectStreamException {
- return DataObjectReferenceImpl.ofUnsafeSteps(steps);
+ return DataObjectReference.ofUnsafeSteps(steps);
}
}
import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
-import com.google.common.annotations.Beta;
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
-import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.ChoiceIn;
import org.opendaylight.yangtools.binding.DataObject;
import org.opendaylight.yangtools.binding.DataObjectIdentifier;
+import org.opendaylight.yangtools.binding.DataObjectReference;
import org.opendaylight.yangtools.binding.DataObjectStep;
import org.opendaylight.yangtools.binding.DataRoot;
import org.opendaylight.yangtools.binding.ExactDataObjectStep;
import org.opendaylight.yangtools.binding.KeylessStep;
import org.opendaylight.yangtools.binding.NodeStep;
import org.opendaylight.yangtools.binding.impl.AbstractDataObjectReference;
+import org.opendaylight.yangtools.binding.impl.AbstractDataObjectReferenceBuilder;
import org.opendaylight.yangtools.concepts.HierarchicalIdentifier;
/**
*/
public final <N extends ChildOf<? super T>> @NonNull InstanceIdentifier<N> child(
final Class<@NonNull N> container) {
- return childIdentifier(createStep(container));
+ return childIdentifier(DataObjectStep.of(container));
}
/**
// FIXME: add a proper caller
public final <C extends ChoiceIn<? super T> & DataObject, N extends ChildOf<? super C>>
@NonNull InstanceIdentifier<N> child(final Class<@NonNull C> caze, final Class<@NonNull N> container) {
- return childIdentifier(createStep(caze, container));
+ return childIdentifier(DataObjectStep.of(caze, container));
}
/**
* @throws NullPointerException if {@code container} is null
*/
public static <T extends ChildOf<? extends DataRoot>> @NonNull Builder<T> builder(
- final Class<T> container) {
- return new RegularBuilder<>(createStep(container));
+ final @NonNull Class<T> container) {
+ return new RegularBuilder<>(DataObjectStep.of(container));
}
/**
* @throws NullPointerException if any argument is null
*/
public static <C extends ChoiceIn<? extends DataRoot> & DataObject, T extends ChildOf<? super C>>
- @NonNull Builder<T> builder(final Class<C> caze, final Class<T> container) {
- return new RegularBuilder<>(createStep(caze, container));
+ @NonNull Builder<T> builder(final @NonNull Class<C> caze, final @NonNull Class<T> container) {
+ return new RegularBuilder<>(DataObjectStep.of(caze, container));
}
/**
*/
public static <C extends ChoiceIn<? extends DataRoot> & DataObject,
N extends KeyAware<K> & ChildOf<? super C>, K extends Key<N>>
- @NonNull KeyedBuilder<N, K> builder(final Class<C> caze, final Class<N> listItem,
- final K listKey) {
+ @NonNull KeyedBuilder<N, K> builder(final @NonNull Class<C> caze, final @NonNull Class<N> listItem,
+ final @NonNull K listKey) {
return new KeyedBuilder<>(new KeyStep<>(listItem, requireNonNull(caze), listKey));
}
public static <R extends DataRoot & DataObject, T extends ChildOf<? super R>>
- @NonNull Builder<T> builderOfInherited(final Class<R> root, final Class<T> container) {
+ @NonNull Builder<T> builderOfInherited(final @NonNull Class<R> root, final @NonNull Class<T> container) {
// FIXME: we are losing root identity, hence namespaces may not work correctly
- return new RegularBuilder<>(createStep(container));
+ return new RegularBuilder<>(DataObjectStep.of(container));
}
public static <R extends DataRoot & DataObject, C extends ChoiceIn<? super R> & DataObject,
@NonNull Builder<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 RegularBuilder<>(createStep(caze, container));
+ return new RegularBuilder<>(DataObjectStep.of(caze, container));
}
public static <R extends DataRoot & DataObject, N extends KeyAware<K> & ChildOf<? super R>,
K extends Key<N>>
- @NonNull KeyedBuilder<N, K> builderOfInherited(final Class<R> root,
- final Class<N> listItem, final K listKey) {
+ @NonNull KeyedBuilder<N, K> builderOfInherited(final @NonNull Class<R> root,
+ final @NonNull Class<N> listItem, final @NonNull K listKey) {
// FIXME: we are losing root identity, hence namespaces may not work correctly
return new KeyedBuilder<>(new KeyStep<>(listItem, listKey));
}
return new KeyedBuilder<>(new KeyStep<>(listItem, requireNonNull(caze), listKey));
}
- @Beta
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public static <T extends DataObject, C extends ChoiceIn<?> & DataObject> @NonNull DataObjectStep<T> createStep(
- final Class<C> caze, final Class<T> type) {
- return KeyAware.class.isAssignableFrom(type) ? new KeylessStep(type, caze) : new NodeStep<>(type, caze);
- }
-
- @Beta
- public static <T extends DataObject> @NonNull DataObjectStep<T> createStep(final Class<T> type) {
- return createStep(null, type);
- }
-
/**
* Create an instance identifier for a very specific object type. This method implements {@link #create(Iterable)}
* semantics, except it is used by internal callers, which have assured that the argument is an immutable Iterable.
@SuppressWarnings("unchecked")
public static <T extends ChildOf<? extends DataRoot>> @NonNull InstanceIdentifier<T> create(
final Class<@NonNull T> type) {
- return (InstanceIdentifier<T>) internalCreate(ImmutableList.of(createStep(type)));
+ return (InstanceIdentifier<T>) internalCreate(ImmutableList.of(DataObjectStep.of(type)));
}
/**
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
final DataObjectStep<?> toStep() {
- return createStep((Class) caseType(), type());
+ return DataObjectStep.of((Class) caseType(), type());
}
@Override
*
* @param <T> Instance identifier target type
*/
- public abstract static sealed class Builder<T extends DataObject> {
- private final ArrayList<@NonNull DataObjectStep<?>> pathBuilder;
- private final Iterable<? extends @NonNull DataObjectStep<?>> basePath;
-
- private boolean wildcard;
-
+ public abstract static sealed class Builder<T extends DataObject> extends AbstractDataObjectReferenceBuilder<T> {
Builder(final Builder<?> prev, final DataObjectStep<?> item) {
- pathBuilder = prev.pathBuilder;
- basePath = prev.basePath;
- wildcard = prev.wildcard;
- appendItem(item);
+ super(prev, item);
}
Builder(final InstanceIdentifier<T> identifier) {
- pathBuilder = new ArrayList<>(4);
- wildcard = identifier.isWildcarded();
- basePath = identifier.steps();
+ super(identifier);
}
Builder(final DataObjectStep<?> item, final boolean wildcard) {
- pathBuilder = new ArrayList<>(4);
- basePath = null;
- this.wildcard = wildcard;
- appendItem(item);
+ super(item, wildcard);
}
- final boolean wildcard() {
- return wildcard;
- }
-
- /**
- * Build an identifier which refers to a specific augmentation of the current InstanceIdentifier referenced by
- * the builder.
- *
- * @param container augmentation class
- * @param <N> augmentation type
- * @return this builder
- * @throws NullPointerException if {@code container} is null
- */
+ @Override
public final <N extends DataObject & Augmentation<? super T>> Builder<N> augmentation(
- final Class<N> container) {
- return append(new NodeStep<>(container));
+ final Class<N> augmentation) {
+ return append(new NodeStep<>(augmentation));
}
- /**
- * Append the specified container as a child of the current InstanceIdentifier referenced by the builder. This
- * method should be used when you want to build an instance identifier by appending top-level elements, for
- * example
- * <pre>
- * InstanceIdentifier.builder().child(Nodes.class).build();
- * </pre>
- *
- * <p>
- * NOTE :- The above example is only for illustration purposes InstanceIdentifier.builder() has been deprecated
- * and should not be used. Use InstanceIdentifier.builder(Nodes.class) instead
- *
- * @param container Container to append
- * @param <N> Container type
- * @return this builder
- * @throws NullPointerException if {@code container} is null
- */
+ @Override
public final <N extends ChildOf<? super T>> Builder<N> child(final Class<N> container) {
- return append(createStep(container));
+ return append(DataObjectStep.of(container));
}
- /**
- * Append the specified container as a child of the current InstanceIdentifier referenced by the builder. This
- * method should be used when you want to build an instance identifier by appending a container node to the
- * identifier and the {@code container} is defined in a {@code grouping} used in a {@code case} statement.
- *
- * @param caze Choice case class
- * @param container Container to append
- * @param <C> Case type
- * @param <N> Container type
- * @return this builder
- * @throws NullPointerException if {@code container} is null
- */
+ @Override
public final <C extends ChoiceIn<? super T> & DataObject, N extends ChildOf<? super C>> Builder<N> child(
final Class<C> caze, final Class<N> container) {
- return append(createStep(caze, container));
+ return append(DataObjectStep.of(caze, container));
}
- /**
- * Append the specified listItem as a child of the current InstanceIdentifier referenced by the builder. This
- * method should be used when you want to build an instance identifier by appending a specific list element to
- * the identifier.
- *
- * @param listItem List to append
- * @param listKey List key
- * @param <N> List type
- * @param <K> Key type
- * @return this builder
- * @throws NullPointerException if any argument is null
- */
+ @Override
public final <N extends KeyAware<K> & ChildOf<? super T>, K extends Key<N>> KeyedBuilder<N, K> child(
final Class<@NonNull N> listItem, final K listKey) {
return append(new KeyStep<>(listItem, listKey));
}
- /**
- * Append the specified listItem as a child of the current InstanceIdentifier referenced by the builder. This
- * method should be used when you want to build an instance identifier by appending a specific list element to
- * the identifier and the {@code list} is defined in a {@code grouping} used in a {@code case} statement.
- *
- * @param caze Choice case class
- * @param listItem List to append
- * @param listKey List key
- * @param <C> Case type
- * @param <N> List type
- * @param <K> Key type
- * @return this builder
- * @throws NullPointerException if any argument is null
- */
+ @Override
public final <C extends ChoiceIn<? super T> & DataObject, K extends Key<N>,
N extends KeyAware<K> & ChildOf<? super C>> KeyedBuilder<N, K> child(final Class<C> caze,
final Class<N> listItem, final K listKey) {
return append(new KeyStep<>(listItem, requireNonNull(caze), listKey));
}
- /**
- * Build the instance identifier.
- *
- * @return Resulting {@link InstanceIdentifier}.
- */
+ @Override
public abstract @NonNull InstanceIdentifier<T> build();
- final Iterable<? extends DataObjectStep<?>> buildSteps() {
- final var prefix = basePath;
- if (prefix == null) {
- return pathBuilder.isEmpty() ? ImmutableList.of() : ImmutableList.copyOf(pathBuilder);
- }
-
- return switch (pathBuilder.size()) {
- case 0 -> prefix;
- case 1 -> concat(prefix, pathBuilder.getFirst());
- default -> ImmutableList.<DataObjectStep<?>>builder().addAll(prefix).addAll(pathBuilder).build();
- };
- }
-
@Override
- public final int hashCode() {
- int hash = 1;
- for (var step : pathArguments()) {
- hash = 31 * hash + step.hashCode();
- }
- return hash;
- }
+ protected abstract <X extends DataObject> @NonNull RegularBuilder<X> append(DataObjectStep<X> step);
@Override
- public final boolean equals(final Object obj) {
- return this == obj || obj instanceof Builder<?> other
- && wildcard == other.wildcard && Iterables.elementsEqual(pathArguments(), other.pathArguments());
- }
-
- // Note: not suitable for use in result
- private Iterable<? extends DataObjectStep<?>> pathArguments() {
- return basePath == null ? pathBuilder : Iterables.concat(basePath, pathBuilder);
- }
-
- final void appendItem(final DataObjectStep<?> item) {
- pathBuilder.add(requireNonNull(item));
- if (!(item instanceof ExactDataObjectStep)) {
- wildcard = true;
- }
- }
-
- abstract <X extends DataObject> @NonNull RegularBuilder<X> append(DataObjectStep<X> step);
-
- abstract <X extends DataObject & KeyAware<Y>, Y extends Key<X>> @NonNull KeyedBuilder<X, Y> append(
+ protected abstract <X extends DataObject & KeyAware<Y>, Y extends Key<X>> @NonNull KeyedBuilder<X, Y> append(
KeyStep<Y, X> step);
}
public static final class KeyedBuilder<T extends DataObject & KeyAware<K>, K extends Key<T>>
- extends Builder<T> {
+ extends Builder<T> implements DataObjectReference.Builder.WithKey<T, K> {
KeyedBuilder(final KeyStep<K, T> firstStep) {
super(firstStep, false);
}
}
@Override
- <X extends DataObject> @NonNull RegularBuilder<X> append(final DataObjectStep<X> step) {
+ protected <X extends DataObject> @NonNull RegularBuilder<X> append(final DataObjectStep<X> step) {
return new RegularBuilder<>(this, step);
}
@Override
@SuppressWarnings("unchecked")
- <X extends DataObject & KeyAware<Y>, Y extends Key<X>> KeyedBuilder<X, Y> append(final KeyStep<Y, X> step) {
+ protected <X extends DataObject & KeyAware<Y>, Y extends Key<X>> KeyedBuilder<X, Y> append(
+ final KeyStep<Y, X> step) {
appendItem(step);
return (KeyedBuilder<X, Y>) this;
}
@Override
@SuppressWarnings("unchecked")
- <X extends DataObject> RegularBuilder<X> append(final DataObjectStep<X> step) {
+ protected <X extends DataObject> RegularBuilder<X> append(final DataObjectStep<X> step) {
appendItem(step);
return (RegularBuilder<X>) this;
}
@Override
- <X extends DataObject & KeyAware<Y>, Y extends Key<X>> KeyedBuilder<X, Y> append(
+ protected <X extends DataObject & KeyAware<Y>, Y extends Key<X>> KeyedBuilder<X, Y> append(
final KeyStep<Y, X> item) {
return new KeyedBuilder<>(this, item);
}
assertNotNull(instanceIdentifier1.toString());
final InstanceIdentifier.Builder instanceIdentifierBuilder = instanceIdentifier1.toBuilder();
- assertEquals(instanceIdentifier1.hashCode(), instanceIdentifierBuilder.hashCode());
assertNotNull(instanceIdentifierBuilder.augmentation(InstantiatedFoo.class));
assertNotNull(instanceIdentifierBuilder.build());
}
assertEquals(instanceIdentifier, deserialized);
}
- @Test
- public void equalsTest() {
- final InstanceIdentifier.Builder<FooRoot> builder1 = InstanceIdentifier.create(FooRoot.class).toBuilder();
- final InstanceIdentifier.Builder<FooRoot> builder2 = InstanceIdentifier.create(FooRoot.class).toBuilder();
- final InstanceIdentifier.Builder<Nodes> builder3 = InstanceIdentifier.create(Nodes.class).toBuilder();
- final InstanceIdentifier.Builder<Nodes> builder4 = InstanceIdentifier.create(Nodes.class).toBuilder();
- final Object obj = new Object();
-
- assertTrue(builder1.equals(builder2));
- assertTrue(builder2.equals(builder1));
- assertTrue(builder2.equals(builder2));
- assertTrue(builder3.equals(builder4));
- assertTrue(builder4.equals(builder4));
- assertFalse(builder3.equals(builder1));
- assertFalse(builder3.equals(null));
- assertFalse(builder4.equals(null));
- assertFalse(builder1.equals(obj));
-
- builder3.child(Node.class, new NodeKey(10));
- assertFalse(builder3.equals(builder4));
- assertFalse(builder4.equals(builder3));
-
- builder4.child(Node.class, new NodeKey(20));
- assertFalse(builder3.equals(builder4));
- assertFalse(builder4.equals(builder3));
- }
-
- @Test
- public void hashCodeTest() {
- final InstanceIdentifier.Builder<FooRoot> builder1 = InstanceIdentifier.create(FooRoot.class).toBuilder();
- final InstanceIdentifier.Builder<FooRoot> builder2 = InstanceIdentifier.create(FooRoot.class).toBuilder();
- final InstanceIdentifier.Builder<Nodes> builder3 = InstanceIdentifier.create(Nodes.class).toBuilder();
- final InstanceIdentifier.Builder<Nodes> builder4 = InstanceIdentifier.create(Nodes.class).toBuilder();
- final Object obj = new Object();
-
- assertTrue(builder1.hashCode() == builder2.hashCode());
- assertTrue(builder1.hashCode() != builder3.hashCode());
- assertTrue(builder3.hashCode() == builder4.hashCode());
- assertTrue(builder2.hashCode() != builder4.hashCode());
- assertTrue(builder1.hashCode() != obj.hashCode());
-
- builder3.child(Node.class, new NodeKey(10));
-
- assertTrue(builder3.hashCode() != builder4.hashCode());
- }
-
@Test
public void verifyTargetTest() {
final InstanceIdentifier<Nodes> nodeId = InstanceIdentifier.create(Nodes.class);