Add DataObject{Identifier,Reference}.Builder(.WithKey)
[yangtools.git] / binding / binding-spec / src / main / java / org / opendaylight / yangtools / binding / impl / AbstractDataObjectReference.java
index 20585922597dd48b56e1bbb93751688a6d2b108f..53428d3bdd95f5b4cc2dce477d32f95932506b07 100644 (file)
@@ -7,13 +7,16 @@
  */
 package org.opendaylight.yangtools.binding.impl;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.base.MoreObjects;
-import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.collect.Iterables;
 import java.io.IOException;
 import java.io.NotSerializableException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamException;
+import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.opendaylight.yangtools.binding.DataObject;
@@ -30,35 +33,55 @@ public abstract sealed class AbstractDataObjectReference<T extends DataObject, S
     @java.io.Serial
     private static final long serialVersionUID = 1L;
 
-    // FIXME: YANGTOOLS-1577: final
+    private final @NonNull Iterable<? extends @NonNull S> steps;
+
+    protected AbstractDataObjectReference(final Iterable<? extends @NonNull S> steps) {
+        this.steps = requireNonNull(steps);
+    }
+
     @Override
-    public abstract Iterable<? extends @NonNull S> steps();
+    public final Iterable<? extends @NonNull S> steps() {
+        return steps;
+    }
 
-    // FIXME: YANGTOOLS-1577: final
     @Override
-    public abstract int hashCode();
+    public DataObjectStep<T> lastStep() {
+        return getLast(steps);
+    }
 
-    // FIXME: YANGTOOLS-1577: final
     @Override
-    public abstract boolean equals(Object obj);
+    public final int hashCode() {
+        int hash = 1;
+        for (var step : steps) {
+            hash = 31 * hash + step.hashCode();
+        }
+        return hash;
+    }
+
+    @Override
+    public final boolean equals(final Object obj) {
+        return this == obj || obj instanceof AbstractDataObjectReference other
+            && Iterables.elementsEqual(steps, other.steps);
+    }
 
     @Override
     public final String toString() {
         // FIXME: YANGTOOLS-1577: pretty-print steps instead
-        return addToStringAttributes(MoreObjects.toStringHelper(contract())).toString();
+        return MoreObjects.toStringHelper(contract()).add("steps", Iterables.toString(steps())).toString();
     }
 
     protected @NonNull Class<?> contract() {
         return DataObjectReference.class;
     }
 
-    /**
-     * Add class-specific toString attributes.
-     *
-     * @param toStringHelper ToStringHelper instance
-     * @return ToStringHelper instance which was passed in
-     */
-    protected abstract ToStringHelper addToStringAttributes(ToStringHelper toStringHelper);
+    @SuppressWarnings("unchecked")
+    protected static final <T> @NonNull T getLast(final Iterable<?> steps) {
+        return (@NonNull T) switch (steps) {
+            case AppendIterable<?> append -> append.last();
+            case List<?> list -> list.getLast();
+            default -> Iterables.getLast(steps);
+        };
+    }
 
     protected final void throwNSE() throws NotSerializableException {
         throw new NotSerializableException(getClass().getName());
@@ -74,7 +97,7 @@ public abstract sealed class AbstractDataObjectReference<T extends DataObject, S
     }
 
     @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);
     }