--- /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.concepts;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.util.Iterator;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * An opinionated superclass for implementing {@link HierarchicalIdentifier}s.
+ *
+ * <p>
+ * It assumes that the identifier is composed of multiple non-null steps available via {@link #itemIterator()} and that
+ * {@link #contains(AbstractHierarchicalIdentifier)} semantics can be implemented using simple in-order comparison of
+ * these steps.
+ *
+ * <p>
+ * Furthermore it mandates that serialization occurs via {@link #writeReplace()}, following the Serialization Proxy
+ * pattern.
+ */
+public abstract class AbstractHierarchicalIdentifier<T extends AbstractHierarchicalIdentifier<T, I>, I>
+ implements HierarchicalIdentifier<T> {
+ @java.io.Serial
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public final boolean contains(final T other) {
+ if (this != other) {
+ final var oit = other.itemIterator();
+ final var it = itemIterator();
+ while (it.hasNext()) {
+ if (!oit.hasNext() || !it.next().equals(oit.next())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ protected abstract @NonNull Iterator<@NonNull I> itemIterator();
+
+ @java.io.Serial
+ protected abstract @NonNull Object writeReplace() throws ObjectStreamException;
+
+ /**
+ * Utility method throwing a {@link NotSerializableException}. It is useful when implementing
+ * {@link #readObject(ObjectInputStream)}, {@link #readObjectNoData()} and {@link #writeObject(ObjectOutputStream)}
+ * methods, which all subclasses should define as serialization is driven via {@link #writeReplace()}.
+ *
+ * @throws NotSerializableException always
+ */
+ protected final void throwNSE() throws NotSerializableException {
+ throw new NotSerializableException(getClass().getName());
+ }
+
+ @Override
+ public abstract int hashCode();
+
+ @Override
+ public abstract boolean equals(Object obj);
+
+ @Override
+ public abstract String toString();
+
+ @java.io.Serial
+ private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
+ throwNSE();
+ }
+
+ @java.io.Serial
+ private void readObjectNoData() throws ObjectStreamException {
+ throwNSE();
+ }
+
+ @java.io.Serial
+ private void writeObject(final ObjectOutputStream stream) throws IOException {
+ throwNSE();
+ }
+}
*/
package org.opendaylight.yangtools.yang.data.api;
-import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.reflect.Array;
import java.util.function.Function;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.concepts.HierarchicalIdentifier;
+import org.opendaylight.yangtools.concepts.AbstractHierarchicalIdentifier;
import org.opendaylight.yangtools.concepts.Identifier;
import org.opendaylight.yangtools.concepts.Mutable;
import org.opendaylight.yangtools.util.ImmutableOffsetMap;
*
* @see <a href="http://www.rfc-editor.org/rfc/rfc6020#section-9.13">RFC6020</a>
*/
-public abstract sealed class YangInstanceIdentifier implements HierarchicalIdentifier<YangInstanceIdentifier>
+public abstract sealed class YangInstanceIdentifier
+ extends AbstractHierarchicalIdentifier<YangInstanceIdentifier, YangInstanceIdentifier.PathArgument>
permits FixedYangInstanceIdentifier, StackedYangInstanceIdentifier {
@java.io.Serial
private static final long serialVersionUID = 4L;
return Optional.of(this);
}
- final Iterator<PathArgument> lit = getPathArguments().iterator();
+ final var lit = getPathArguments().iterator();
int common = 0;
- for (PathArgument element : ancestor.getPathArguments()) {
+ for (var element : ancestor.getPathArguments()) {
// Ancestor is not really an ancestor
if (!lit.hasNext() || !lit.next().equals(element)) {
return Optional.empty();
}
@Override
- public final boolean contains(final YangInstanceIdentifier other) {
- if (this == other) {
- return true;
- }
+ protected final Iterator<PathArgument> itemIterator() {
+ return getPathArguments().iterator();
+ }
- checkArgument(other != null, "other should not be null");
- final Iterator<PathArgument> oit = other.getPathArguments().iterator();
+ @Override
+ protected final Object writeReplace() {
+ return new YIDv1(this);
+ }
- for (PathArgument element : getPathArguments()) {
- if (!oit.hasNext()) {
- return false;
- }
+ @java.io.Serial
+ private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
+ throwNSE();
+ }
- if (!element.equals(oit.next())) {
- return false;
- }
- }
+ @java.io.Serial
+ private void readObjectNoData() throws ObjectStreamException {
+ throwNSE();
+ }
- return true;
+ @java.io.Serial
+ private void writeObject(final ObjectOutputStream stream) throws IOException {
+ throwNSE();
}
@Override
* The cache is thread-safe - if multiple computations occurs at the
* same time, cache will be overwritten with same result.
*/
- final String ret = (String) TO_STRING_CACHE.getAcquire(this);
+ final var ret = (String) TO_STRING_CACHE.getAcquire(this);
return ret != null ? ret : loadToString();
}
abstract int computeHashCode();
- @java.io.Serial
- final Object writeReplace() {
- return new YIDv1(this);
- }
-
/**
* Returns new builder for InstanceIdentifier with empty path arguments.
*